Exemple #1
0
        public static void ApplyDamage(Part hitPart, RaycastHit hit, float multiplier, float penetrationfactor, float caliber, float projmass, float impactVelocity, float DmgMult, double distanceTraveled, bool explosive, bool hasRichocheted, Vessel sourceVessel, string name)
        {
            //hitting a vessel Part
            //No struts, they cause weird bugs :) -BahamutoD
            if (hitPart == null)
            {
                return;
            }
            if (hitPart.partInfo.name.Contains("Strut"))
            {
                return;
            }

            // Add decals
            if (BDArmorySettings.BULLET_HITS)
            {
                BulletHitFX.CreateBulletHit(hitPart, hit.point, hit, hit.normal, hasRichocheted, caliber, penetrationfactor);
            }
            // Apply damage
            float damage;

            damage = hitPart.AddBallisticDamage(projmass, caliber, multiplier, penetrationfactor, DmgMult, impactVelocity);

            if (BDArmorySettings.BATTLEDAMAGE)
            {
                BattleDamageHandler.CheckDamageFX(hitPart, caliber, penetrationfactor, explosive, sourceVessel.GetName(), hit);
            }
            // Debug.Log("DEBUG Ballistic damage to " + hitPart + ": " + damage + ", calibre: " + caliber + ", multiplier: " + multiplier + ", pen: " + penetrationfactor);

            // Update scoring structures
            ApplyScore(hitPart, sourceVessel, distanceTraveled, damage, name);
        }
Exemple #2
0
        private void ApplyDamage(Part hitPart, RaycastHit hit, float multiplier, float penetrationfactor)
        {
            if (OnlyVisual)
            {
                return;
            }

            //hitting a vessel Part
            //No struts, they cause weird bugs :) -BahamutoD
            if (hitPart == null)
            {
                return;
            }
            if (hitPart.partInfo.name.Contains("Strut"))
            {
                return;
            }

            if (BDArmorySettings.BULLET_HITS)
            {
                BulletHitFX.CreateBulletHit(hitPart, hit.point, hit, hit.normal, hasRichocheted, caliber,
                                            penetrationfactor);
            }

            if (explosive)
            {
                hitPart.AddBallisticDamage(bulletMass - tntMass, caliber, multiplier, penetrationfactor,
                                           bulletDmgMult, impactVelocity);
            }
            else
            {
                hitPart.AddBallisticDamage(bulletMass, caliber, multiplier, penetrationfactor,
                                           bulletDmgMult, impactVelocity);
            }
        }
 void Update()
 {
     if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && vessel != null && !vessel.packed)
     {
         if (this.part.temperature > 493) //autoignition temp of kerosene is 220 c
         {
             var isOnFire = part.GetComponentInChildren <FireFX>();
             if (isOnFire == null)
             {
                 string fireStarter;
                 var    vesselFire = part.vessel.GetComponentInChildren <FireFX>();
                 if (vesselFire != null)
                 {
                     fireStarter = vesselFire.SourceVessel;
                 }
                 else
                 {
                     fireStarter = part.vessel.GetName();
                 }
                 Vector3    firePosition = part.transform.up * 10;
                 Ray        LoSRay       = new Ray(transform.position, (transform.position + firePosition) - transform.position);
                 RaycastHit hit;
                 if (Physics.Raycast(LoSRay, out hit, 10, 9076737)) // only add fires to parts in LoS of blast
                 {
                     BulletHitFX.AttachFire(hit, part, 50, fireStarter);
                 }
                 Debug.Log("[SelfSealingTank] Fuel auto-ignition! " + part.name + " is on fire!");
             }
         }
     }
 }
Exemple #4
0
        protected void CollisionEnter(Collision col)
        {
            if (BDArmorySettings.DRAW_DEBUG_LABELS)
            {
                Debug.Log("[BDArmory]: Missile Collided");
            }

            if (TimeIndex > 2 && HasFired && col.collider.gameObject.GetComponentInParent <Part>().GetFireFX())
            {
                ContactPoint contact = col.contacts[0];
                Vector3      pos     = contact.point;
                BulletHitFX.AttachFlames(pos, col.collider.gameObject.GetComponentInParent <Part>());
            }

            if (HasExploded || !HasFired)
            {
                return;
            }

            if (DetonationDistanceState != DetonationDistanceStates.CheckingProximity)
            {
                return;
            }

            Debug.Log("[BDArmory]: Missile Collided - Triggering Detonation");
            Detonate();
        }
Exemple #5
0
        private bool CheckGroundHit(Part hitPart, RaycastHit hit)
        {
            if (hitPart == null)
            {
                if (BDArmorySettings.BULLET_HITS)
                {
                    BulletHitFX.CreateBulletHit(hitPart, hit.point, hit, hit.normal, true, caliber, 0);
                }

                return(true);
            }
            return(false);
        }
Exemple #6
0
        public void DoRicochet(Part p, RaycastHit hit, float hitAngle)
        {
            //ricochet
            if (BDArmorySettings.BULLET_HITS)
            {
                BulletHitFX.CreateBulletHit(p, hit.point, hit, hit.normal, true, caliber, 0);
            }

            tracerStartWidth /= 2;
            tracerEndWidth   /= 2;

            transform.position = hit.point;
            currentVelocity    = Vector3.Reflect(currentVelocity, hit.normal);
            currentVelocity    = (hitAngle / 150) * currentVelocity * 0.65f;

            Vector3 randomDirection = UnityEngine.Random.rotation * Vector3.one;

            currentVelocity = Vector3.RotateTowards(currentVelocity, randomDirection,
                                                    UnityEngine.Random.Range(0f, 5f) * Mathf.Deg2Rad, 0);
        }
        private void ApplyDamage(Part hitPart, RaycastHit hit)
        {
            //hitting a vessel Part
            //No struts, they cause weird bugs :) -BahamutoD
            if (hitPart == null)
            {
                return;
            }
            if (hitPart.partInfo.name.Contains("Strut"))
            {
                return;
            }
            float explDamage = 0;

            if (BDArmorySettings.BULLET_HITS)
            {
                BulletHitFX.CreateBulletHit(hitPart, hit.point, hit, hit.normal, false, 200, 3);
            }
            if (CASELevel == 2)
            {
                explDamage = 100;
                hitPart.AddDamage(explDamage);
                float armorToReduce = hitPart.GetArmorThickness() * 0.25f;
                hitPart.ReduceArmor(armorToReduce);
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BD DEBUG]" + hitPart.name + "damaged, armor reduced by " + armorToReduce);
                }
            }
            else //CASE I
            {
                explDamage = (hitPart.Modules.GetModule <HitpointTracker>().GetMaxHitpoints() * 0.9f);
                explDamage = Mathf.Clamp(explDamage, 0, 600);
                hitPart.AddDamage(explDamage);
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BD DEBUG]" + hitPart.name + "damaged for " + (hitPart.MaxDamage() * 0.9f));
                }
                if (BDArmorySettings.BATTLEDAMAGE)
                {
                    Misc.BattleDamageHandler.CheckDamageFX(hitPart, 200, 3, true, SourceVessel, hit);
                }
            }
            {
                var aName = SourceVessel;
                var tName = part.vessel.GetName();

                if (aName != null && tName != null && aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(aName) && BDACompetitionMode.Instance.Scores.ContainsKey(tName))
                {
                    if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                    {
                        BDAScoreService.Instance.TrackDamage(aName, tName, explDamage);
                    }
                    var aData = BDACompetitionMode.Instance.Scores[aName];
                    aData.Score += 1;

                    if (part.vessel.GetName() == "Pinata")
                    {
                        aData.PinataHits++;
                    }

                    var tData = BDACompetitionMode.Instance.Scores[tName];
                    tData.lastPersonWhoHitMe = aName;
                    tData.lastHitTime        = Planetarium.GetUniversalTime();
                    tData.everyoneWhoHitMe.Add(aName);
                    // Track hits
                    if (tData.hitCounts.ContainsKey(aName))
                    {
                        ++tData.hitCounts[aName];
                    }
                    else
                    {
                        tData.hitCounts.Add(aName, 1);
                    }
                    // Track damage
                    if (tData.damageFromBullets.ContainsKey(aName))
                    {
                        tData.damageFromBullets[aName] += explDamage;
                    }
                    else
                    {
                        tData.damageFromBullets.Add(aName, explDamage);
                    }
                }
            }
        }
        public static void CheckDamageFX(Part part, float caliber, float penetrationFactor, bool explosivedamage, string attacker, RaycastHit hitLoc)
        {
            if (!BDArmorySettings.BATTLEDAMAGE || BDArmorySettings.PAINTBALL_MODE)
            {
                return;
            }

            double damageChance = Mathf.Clamp((BDArmorySettings.BD_DAMAGE_CHANCE * ((1 - part.GetDamagePercentage()) * 10) * (penetrationFactor / 2)), 0, 100); //more heavily damaged parts more likely to take battledamage

            if (BDArmorySettings.BD_TANKS)
            {
                if (part.HasFuel())
                {
                    var alreadyburning = part.GetComponentInChildren <FireFX>();
                    var rubbertank     = part.FindModuleImplementing <ModuleSelfSealingTank>();
                    if (rubbertank != null)
                    {
                        if (rubbertank.SSTank && part.GetDamagePercentage() > 0.66f)
                        {
                            return;
                        }
                    }
                    if (penetrationFactor > 1.2)
                    {
                        if (alreadyburning != null)
                        {
                            BulletHitFX.AttachFire(hitLoc, part, caliber, attacker);
                        }
                        else
                        {
                            BulletHitFX.AttachLeak(hitLoc, part, caliber, explosivedamage, attacker);
                        }
                    }
                }
            }
            if (BDArmorySettings.BD_FIRES_ENABLED)
            {
                if (part.isBattery())
                {
                    var alreadyburning = part.GetComponentInChildren <FireFX>();
                    if (alreadyburning == null)
                    {
                        double Diceroll = UnityEngine.Random.Range(0, 100);
                        if (explosivedamage)
                        {
                            Diceroll *= 0.66;
                        }
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BD Debug]: Battery Dice Roll: " + Diceroll);
                        }
                        if (Diceroll <= BDArmorySettings.BD_DAMAGE_CHANCE)
                        {
                            BulletHitFX.AttachFire(hitLoc, part, caliber, attacker);
                        }
                    }
                }
            }
            //AmmoBins
            if (BDArmorySettings.BD_AMMOBINS && penetrationFactor > 1.2 && part.GetDamagePercentage() < 0.9f) //explosions have penetration of 0.5, should stop explosions phasing though parts from detonating ammo
            {
                var ammo = part.FindModuleImplementing <ModuleCASE>();
                if (ammo != null)
                {
                    double Diceroll = UnityEngine.Random.Range(0, 100);
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BD Debug]: Ammo TAC DiceRoll: " + Diceroll + "; needs: " + damageChance);
                    }
                    if (Diceroll <= (damageChance) && part.GetDamagePercentage() < 0.95f)
                    {
                        ammo.SourceVessel = attacker;
                        ammo.DetonateIfPossible();
                    }
                }
            }
            //Propulsaion Damage
            if (BDArmorySettings.BD_PROPULSION)
            {
                if (part.isEngine() && part.GetDamagePercentage() < 0.95f) //first hit's free
                {
                    foreach (var engine in part.GetComponentsInChildren <ModuleEngines>())
                    {
                        if (engine.thrustPercentage > 20) //engines take thrust damage per hit
                        {
                            //engine.maxThrust -= ((engine.maxThrust * 0.125f) / 100); // doesn't seem to adjust thrust; investigate
                            //engine.thrustPercentage -= ((engine.maxThrust * 0.125f) / 100); //workaround hack
                            engine.thrustPercentage -= (((1 - part.GetDamagePercentage()) * (penetrationFactor / 2)) * BDArmorySettings.BD_PROP_DAM_RATE); //AP does bonus damage
                            Mathf.Clamp(engine.thrustPercentage, 15f, 100);                                                                                //even heavily damaged engines will still put out something
                            if (BDArmorySettings.DRAW_DEBUG_LABELS)
                            {
                                Debug.Log("[BD Debug]: engine thrust: " + engine.thrustPercentage);
                            }

                            /*
                             * float enginelevel = engine.thrustPercentage;
                             * if (BDArmorySettings.BD_BALANCED_THRUST) //need to poke this more later, not working properly
                             * {
                             *  using (List<Part>.Enumerator pSym = part.symmetryCounterparts.GetEnumerator())
                             *      while (pSym.MoveNext())
                             *      {
                             *          if (pSym.Current == null) continue;
                             *          if (pSym.Current != part && pSym.Current.vessel == part.vessel)
                             *          {
                             *              var symEngine = pSym.Current.FindModuleImplementing<ModuleEngines>();
                             *              if (symEngine != null)
                             *              {
                             *                  symEngine.thrustPercentage = enginelevel;
                             *              }
                             *          }
                             *      }
                             * }
                             */
                        }
                        if (part.GetDamagePercentage() < 0.75f || (part.GetDamagePercentage() < 0.82f && penetrationFactor > 2))
                        {
                            var leak = part.GetComponentInChildren <FuelLeakFX>();
                            if (leak == null)
                            {
                                BulletHitFX.AttachLeak(hitLoc, part, caliber, explosivedamage, attacker);
                            }
                        }
                        if (part.GetDamagePercentage() < 0.50f || (part.GetDamagePercentage() < 0.625f && penetrationFactor > 2))
                        {
                            var alreadyburning = part.GetComponentInChildren <FireFX>();
                            if (alreadyburning == null)
                            {
                                BulletHitFX.AttachFire(hitLoc, part, caliber, attacker);
                            }
                        }
                        if (part.GetDamagePercentage() < 0.25f)
                        {
                            if (engine.EngineIgnited)
                            {
                                engine.PlayFlameoutFX(true);
                                engine.Shutdown(); //kill a badly damaged engine and don't allow restart
                                engine.allowRestart = false;
                            }
                        }
                    }
                }
                if (BDArmorySettings.BD_INTAKES) //intake damage
                {
                    var intake = part.FindModuleImplementing <ModuleResourceIntake>();
                    if (intake != null)
                    {
                        float HEBonus = 0.7f;
                        if (explosivedamage)
                        {
                            HEBonus = 1.4f;
                        }
                        intake.intakeSpeed *= (1 - (((1 - part.GetDamagePercentage()) * HEBonus) / BDArmorySettings.BD_PROP_DAM_RATE)); //HE does bonus damage
                        Mathf.Clamp((float)intake.intakeSpeed, 0, 99999);

                        intake.area *= (1 - (((1 - part.GetDamagePercentage()) * HEBonus) / BDArmorySettings.BD_PROP_DAM_RATE)); //HE does bonus damage
                        Mathf.Clamp((float)intake.area, 0.0002f, 99999);                                                         //even shredded intake ducting will still get some air to engines
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BD Debug]: Intake damage: Current Area: " + intake.area + "; Intake Speed: " + intake.intakeSpeed);
                        }
                    }
                }
                if (BDArmorySettings.BD_GIMBALS) //engine gimbal damage
                {
                    var gimbal = part.FindModuleImplementing <ModuleGimbal>();
                    if (gimbal != null)
                    {
                        double HEBonus = 1;
                        if (explosivedamage)
                        {
                            HEBonus = 1.5;
                        }
                        //gimbal.gimbalRange *= (1 - (((1 - part.GetDamagePercentatge()) * HEBonus) / BDArmorySettings.BD_PROP_DAM_RATE)); //HE does bonus damage
                        double Diceroll = UnityEngine.Random.Range(0, 100);
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BD Debug]: Gimbal DiceRoll: " + Diceroll);
                        }
                        if (Diceroll <= (BDArmorySettings.BD_DAMAGE_CHANCE * HEBonus))
                        {
                            gimbal.enabled     = false;
                            gimbal.gimbalRange = 0;
                        }
                    }
                }
            }
            //Aero Damage
            if (BDArmorySettings.BD_AEROPARTS)
            {
                float HEBonus = 1;
                if (explosivedamage)
                {
                    HEBonus = 2; //explosive rounds blow bigger holes in wings
                }
                Mathf.Clamp(penetrationFactor, 0.1f, 3);
                HEBonus /= penetrationFactor; //faster rounds punch cleaner holes
                float liftDam = ((caliber / 20000) * HEBonus) * BDArmorySettings.BD_LIFT_LOSS_RATE;
                if (part.GetComponent <ModuleLiftingSurface>() != null)
                {
                    ModuleLiftingSurface wing;
                    wing = part.GetComponent <ModuleLiftingSurface>();
                    //2x4m wing board = 2 Lift, 0.25 Lift/m2. 20mm round = 20*20=400/20000= 0.02 Lift reduced per hit, 100 rounds to reduce lift to 0. mind you, it only takes ~15 rounds to destroy the wing...
                    if (wing.deflectionLiftCoeff > ((part.mass * 5) + liftDam)) //stock mass/lift ratio is 10; 0.2t wing has 2.0 lift; clamp lift lost at half
                    {
                        wing.deflectionLiftCoeff -= liftDam;
                    }
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BD DEBUG] " + part.name + "took lift damage: " + liftDam + ", current lift: " + wing.deflectionLiftCoeff);
                    }
                }
                if (part.GetComponent <ModuleControlSurface>() != null && part.GetDamagePercentage() > 0.125f)
                {
                    ModuleControlSurface aileron;
                    aileron = part.GetComponent <ModuleControlSurface>();
                    if (aileron.deflectionLiftCoeff > ((part.mass * 2.5f) + liftDam)) //stock ctrl surface mass/lift ratio is 5
                    {
                        aileron.deflectionLiftCoeff -= liftDam;
                    }
                    if (BDArmorySettings.BD_CTRL_SRF)
                    {
                        int Diceroll = (int)UnityEngine.Random.Range(0f, 100f);
                        if (explosivedamage)
                        {
                            HEBonus = 1.2f;
                        }
                        if (Diceroll <= (BDArmorySettings.BD_DAMAGE_CHANCE * HEBonus))
                        {
                            aileron.actuatorSpeed    = 0;
                            aileron.authorityLimiter = 0;
                            aileron.ctrlSurfaceRange = 0;
                        }
                    }
                }
            }
            //Subsystems
            if (BDArmorySettings.BD_SUBSYSTEMS)
            {
                double Diceroll = UnityEngine.Random.Range(0, 100);
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BD Debug]: Subsystem DiceRoll: " + Diceroll + "; needs: " + damageChance);
                }
                if (Diceroll <= (damageChance) && part.GetDamagePercentage() < 0.95f)
                {
                    if (part.GetComponent <ModuleReactionWheel>() != null) //should have this be separate dice rolls, else a part with more than one of these will lose them all
                    {
                        ModuleReactionWheel SAS;                           //could have torque reduced per hit
                        SAS = part.GetComponent <ModuleReactionWheel>();
                        part.RemoveModule(SAS);
                    }
                    if (part.GetComponent <ModuleRadar>() != null)
                    {
                        ModuleRadar radar; //would need to mod detection curve to degrade performance on hit
                        radar = part.GetComponent <ModuleRadar>();
                        part.RemoveModule(radar);
                    }
                    if (part.GetComponent <ModuleAlternator>() != null)
                    {
                        ModuleAlternator alt; //damaging alternator is probably just petty. Could reduce output per hit
                        alt = part.GetComponent <ModuleAlternator>();
                        part.RemoveModule(alt);
                    }
                    if (part.GetComponent <ModuleAnimateGeneric>() != null)
                    {
                        ModuleAnimateGeneric anim;
                        anim = part.GetComponent <ModuleAnimateGeneric>(); // could reduce anim speed, open percent per hit
                        part.RemoveModule(anim);
                    }
                    if (part.GetComponent <ModuleDecouple>() != null)
                    {
                        ModuleDecouple stage;
                        stage = part.GetComponent <ModuleDecouple>(); //decouplers decouple
                        stage.Decouple();
                    }
                    if (part.GetComponent <ModuleECMJammer>() != null)
                    {
                        ModuleECMJammer ecm;
                        ecm = part.GetComponent <ModuleECMJammer>(); //could reduce ecm strngth/rcs modifier
                        part.RemoveModule(ecm);
                    }
                    if (part.GetComponent <ModuleGenerator>() != null)
                    {
                        ModuleGenerator gen;
                        gen = part.GetComponent <ModuleGenerator>();
                        part.RemoveModule(gen);
                    }
                    if (part.GetComponent <ModuleResourceConverter>() != null)
                    {
                        ModuleResourceConverter isru;
                        isru = part.GetComponent <ModuleResourceConverter>(); //could reduce efficiency, increase heat per hit
                        part.RemoveModule(isru);
                    }
                    if (part.GetComponent <ModuleResourceConverter>() != null)
                    {
                        ModuleTurret turret;
                        turret = part.GetComponent <ModuleTurret>(); //could reduce traverse speed, range per hit
                        part.RemoveModule(turret);
                    }
                    if (part.GetComponent <ModuleTargetingCamera>() != null)
                    {
                        ModuleTargetingCamera cam;
                        cam = part.GetComponent <ModuleTargetingCamera>(); // gimbal range??
                        part.RemoveModule(cam);
                    }
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BD DEBUG] " + part.name + "took subsystem damage");
                    }
                }
            }
            //Command parts
            if (BDArmorySettings.BD_COCKPITS && penetrationFactor > 1 && part.GetDamagePercentage() < 0.9f) //lets have this be triggered by penetrative damage, not blast splash
            {
                if (part.GetComponent <ModuleCommand>() != null)
                {
                    double ControlDiceRoll = UnityEngine.Random.Range(0, 100);
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BD Debug]: Command DiceRoll: " + ControlDiceRoll);
                    }
                    if (ControlDiceRoll <= (BDArmorySettings.BD_DAMAGE_CHANCE * 2))
                    {
                        using (List <Part> .Enumerator craftPart = part.vessel.parts.GetEnumerator())
                        {
                            using (List <BDModulePilotAI> .Enumerator control = part.vessel.FindPartModulesImplementing <BDModulePilotAI>().GetEnumerator())
                                while (control.MoveNext())
                                {
                                    if (control.Current == null)
                                    {
                                        continue;
                                    }
                                    control.Current.evasionThreshold += 10;    //pilot jitteriness increases
                                    control.Current.maxSteer         *= 0.9f;
                                    if (control.Current.steerDamping > 0.625f) //damage to controls
                                    {
                                        control.Current.steerDamping -= 0.125f;
                                    }
                                    if (control.Current.dynamicSteerDampingPitchFactor > 0.625f)
                                    {
                                        control.Current.dynamicSteerDampingPitchFactor -= 0.125f;
                                    }
                                    if (control.Current.dynamicSteerDampingRollFactor > 0.625f)
                                    {
                                        control.Current.dynamicSteerDampingRollFactor -= 0.125f;
                                    }
                                    if (control.Current.dynamicSteerDampingYawFactor > 0.625f)
                                    {
                                        control.Current.dynamicSteerDampingYawFactor -= 0.125f;
                                    }
                                }
                            //GuardRange reduction to sim canopy/sensor damage?
                            if (BDArmorySettings.DRAW_DEBUG_LABELS)
                            {
                                Debug.Log("[BD DEBUG] " + part.name + "took command damage");
                            }
                        }
                    }
                }
            }
            if (part.protoModuleCrew.Count > 0 && penetrationFactor > 1 && part.GetDamagePercentage() < 0.95f)
            {
                if (BDArmorySettings.BD_PILOT_KILLS)
                {
                    float PilotTAC   = Mathf.Clamp((BDArmorySettings.BD_DAMAGE_CHANCE / part.mass), 0.01f, 100); //larger cockpits = greater volume = less chance any hit will pass through a region of volume containing a pilot
                    float killchance = UnityEngine.Random.Range(0, 100);
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BD Debug]: Pilot TAC: " + PilotTAC + "; dice roll: " + killchance);
                    }
                    if (killchance <= PilotTAC) //add penetrationfactor threshold? hp threshold?
                    {
                        ProtoCrewMember crewMember = part.protoModuleCrew.FirstOrDefault(x => x != null);
                        if (crewMember != null)
                        {
                            crewMember.UnregisterExperienceTraits(part);
                            //crewMember.outDueToG = true; //implement temp KO to simulate wounding?
                            crewMember.Die();
                            if (part.IsKerbalEVA())
                            {
                                part.Die();
                            }
                            else
                            {
                                part.RemoveCrewmember(crewMember); // sadly, I wasn't able to get the K.I.A. portrait working
                            }
                            //Vessel.CrewWasModified(part.vessel);
                            //Debug.Log(crewMember.name + " was killed by damage to cabin!");
                            if (HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn)
                            {
                                crewMember.StartRespawnPeriod();
                            }
                            //ScreenMessages.PostScreenMessage(crewMember.name + " killed by damage to " + part.vessel.name + part.partName + ".", 5.0f, ScreenMessageStyle.UPPER_LEFT);
                            ScreenMessages.PostScreenMessage("Cockpit snipe! " + crewMember.name + " killed!", 5.0f, ScreenMessageStyle.UPPER_LEFT);
                        }
                    }
                }
            }
        }
Exemple #9
0
        private void ApplyDamage(Part hitPart, RaycastHit hit, float multiplier, float penetrationfactor)
        {
            //hitting a vessel Part
            //No struts, they cause weird bugs :) -BahamutoD
            if (hitPart == null)
            {
                return;
            }
            if (hitPart.partInfo.name.Contains("Strut"))
            {
                return;
            }

            // Add decals
            if (BDArmorySettings.BULLET_HITS)
            {
                BulletHitFX.CreateBulletHit(hitPart, hit.point, hit, hit.normal, hasRichocheted, caliber, penetrationfactor);
            }

            // Apply damage
            float damage;

            //if (explosive)
            //{
            //    damage = hitPart.AddBallisticDamage(bulletMass - tntMass, caliber, multiplier, penetrationfactor, bulletDmgMult, impactVelocity, hit, sourceVessel.GetName());
            //} //why? The mass of HE filler isn't going to have disapeared before the bullet hits something, and if it has, it means there isn't a bullet left to hit things
            //else
            //{
            damage = hitPart.AddBallisticDamage(bulletMass, caliber, multiplier, penetrationfactor, bulletDmgMult, impactVelocity);
            //}
            if (BDArmorySettings.BATTLEDAMAGE)
            {
                Misc.BattleDamageHandler.CheckDamageFX(hitPart, caliber, penetrationfactor, explosive, sourceVessel.GetName(), hit);
            }
            // Debug.Log("DEBUG Ballistic damage to " + hitPart + ": " + damage + ", calibre: " + caliber + ", multiplier: " + multiplier + ", pen: " + penetrationfactor);

            // Update scoring structures
            var aName = this.sourceVessel.GetName();
            var tName = hitPart.vessel.GetName();

            if (aName != null && tName != null && aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(aName) && BDACompetitionMode.Instance.Scores.ContainsKey(tName))
            {
                //Debug.Log("[BDArmory]: Weapon from " + aName + " damaged " + tName);

                if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                {
                    BDAScoreService.Instance.TrackHit(aName, tName, bullet.name, distanceTraveled);
                    BDAScoreService.Instance.TrackDamage(aName, tName, damage);
                }

                // update scoring structure on attacker
                {
                    var aData = BDACompetitionMode.Instance.Scores[aName];
                    aData.Score += 1;
                    // keep track of who shot who for point keeping

                    // competition logic for 'Pinata' mode - this means a pilot can't be named 'Pinata'
                    if (hitPart.vessel.GetName() == "Pinata")
                    {
                        aData.PinataHits++;
                    }
                }

                // update scoring structure on the defender.
                {
                    var tData = BDACompetitionMode.Instance.Scores[tName];
                    tData.lastPersonWhoHitMe = aName;
                    tData.lastHitTime        = Planetarium.GetUniversalTime();
                    tData.everyoneWhoHitMe.Add(aName);
                    // Track hits
                    if (tData.hitCounts.ContainsKey(aName))
                    {
                        ++tData.hitCounts[aName];
                    }
                    else
                    {
                        tData.hitCounts.Add(aName, 1);
                    }
                    // Track damage
                    if (tData.damageFromBullets.ContainsKey(aName))
                    {
                        tData.damageFromBullets[aName] += damage;
                    }
                    else
                    {
                        tData.damageFromBullets.Add(aName, damage);
                    }
                }
            }
        }
Exemple #10
0
        void FixedUpdate()
        {
            float distanceFromStartSqr = (transform.position - startPosition).sqrMagnitude;

            if (!gameObject.activeInHierarchy)
            {
                return;
            }
            flightTimeElapsed += TimeWarp.fixedDeltaTime; //calculate flight time for drag purposes

            if (bulletDrop && FlightGlobals.RefFrameIsRotating)
            {
                currentVelocity += FlightGlobals.getGeeForceAtPosition(transform.position) * TimeWarp.fixedDeltaTime;
            }
            if (dragType == BulletDragTypes.NumericalIntegration)
            {
                Vector3 dragAcc = currentVelocity * currentVelocity.magnitude *
                                  (float)
                                  FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(transform.position),
                                                              FlightGlobals.getExternalTemperature(transform.position));
                dragAcc *= 0.5f;
                dragAcc /= ballisticCoefficient;

                currentVelocity -= dragAcc * TimeWarp.fixedDeltaTime;
                //numerical integration; using Euler is silly, but let's go with it anyway
            }


            if (tracerLength == 0)
            {
                bulletTrail.SetPosition(0,
                                        transform.position +
                                        (currentVelocity * tracerDeltaFactor * TimeWarp.fixedDeltaTime / TimeWarp.CurrentRate) -
                                        (FlightGlobals.ActiveVessel.Velocity() * TimeWarp.fixedDeltaTime));
            }
            else
            {
                bulletTrail.SetPosition(0,
                                        transform.position + ((currentVelocity - sourceOriginalV).normalized * tracerLength));
            }
            if (fadeColor)
            {
                FadeColor();
                bulletTrail.material.SetColor("_TintColor", currentColor * tracerLuminance);
            }


            bulletTrail.SetPosition(1, transform.position);


            currPosition = gameObject.transform.position;

            if (distanceFromStartSqr > maxDistance * maxDistance)
            {
                //GameObject.Destroy(gameObject);
                KillBullet();
                return;
            }

            if (collisionEnabled)
            {
                float dist = initialSpeed * TimeWarp.fixedDeltaTime;

                Ray        ray = new Ray(prevPosition, currPosition - prevPosition);
                RaycastHit hit;
                try
                {
                    if (Physics.Raycast(ray, out hit, dist, 688129))
                    {
                        bool penetrated = true;
                        bool hitEva     = false;
                        Part hitPart    = null; //determine when bullet collides with a target
                        try
                        {
                            // Look for any Kerbal first. The part, KerbalEVA, is functionally similar to regular parts.
                            KerbalEVA eva = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>();
                            hitPart = eva ? eva.part : hit.collider.gameObject.GetComponentInParent <Part>();
                            hitEva  = eva;
                        }
                        catch (NullReferenceException)
                        {
                        }
                        // Need to make sure Kerbals don't get armor.
                        BDArmor armor = hitEva ? null : BDArmor.GetArmor(hit.collider, hitPart);
                        ArmorPenetration.BulletPenetrationData armorData = new ArmorPenetration.BulletPenetrationData(ray, hit);
                        ArmorPenetration.DoPenetrationRay(armorData, bullet.positiveCoefficient);
                        float penetration      = bullet.penetration.Evaluate(Mathf.Sqrt(distanceFromStartSqr)) / 1000;
                        bool  fulllyPenetrated = penetration * leftPenetration >
                                                 ((armor == null) ? 1f : armor.EquivalentThickness) * armorData.armorThickness;
                        Vector3 finalDirect = Vector3.Lerp(ray.direction, -hit.normal, bullet.positiveCoefficient);


                        if (fulllyPenetrated)
                        {
                            currentVelocity = finalDirect * currentVelocity.magnitude * leftPenetration;
                        }
                        else
                        {
                            currPosition = hit.point;
                            bulletTrail.SetPosition(1, currPosition);
                        }
                        float hitAngle = Vector3.Angle(currentVelocity, -hit.normal);

                        if (bulletType != PooledBulletTypes.Explosive) //dont do bullet damage if it is explosive
                        {
                            float impactVelocity = currentVelocity.magnitude;
                            if (dragType == BulletDragTypes.AnalyticEstimate)
                            {
                                float analyticDragVelAdjustment =
                                    (float)
                                    FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(currPosition),
                                                                FlightGlobals.getExternalTemperature(currPosition));
                                analyticDragVelAdjustment *= flightTimeElapsed * initialSpeed;
                                analyticDragVelAdjustment += 2 * ballisticCoefficient;

                                analyticDragVelAdjustment = 2 * ballisticCoefficient * initialSpeed / analyticDragVelAdjustment;
                                //velocity as a function of time under the assumption of a projectile only acted upon by drag with a constant drag area

                                analyticDragVelAdjustment = analyticDragVelAdjustment - initialSpeed;
                                //since the above was velocity as a function of time, but we need a difference in drag, subtract the initial velocity
                                //the above number should be negative...
                                impactVelocity += analyticDragVelAdjustment; //so add it to the impact velocity

                                if (impactVelocity < 0)
                                {
                                    impactVelocity = 0;
                                    //clamp the velocity to > 0, since it could drop below 0 if the bullet is fired upwards
                                }
                                //Debug.Log("flight time: " + flightTimeElapsed + " BC: " + ballisticCoefficient + "\ninit speed: " + initialSpeed + " vel diff: " + analyticDragVelAdjustment);
                            }

                            //hitting a vessel Part

                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                            /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE START//////////////////////////////////////////////////////////////
                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


                            if (hitPart != null) //see if it will ricochet of the part
                            {
                                penetrated = !RicochetOnPart(hitPart, hitAngle, impactVelocity);
                            }
                            else //see if it will ricochet off scenery
                            {
                                float reflectRandom = UnityEngine.Random.Range(-75f, 90f);
                                if (reflectRandom > 90 - hitAngle)
                                {
                                    penetrated = false;
                                }
                            }


                            if (hitPart != null && !hitPart.partInfo.name.Contains("Strut"))
                            //when a part is hit, execute damage code (ignores struts to keep those from being abused as armor)(no, because they caused weird bugs :) -BahamutoD)
                            {
                                float heatDamage = (mass / (hitPart.crashTolerance * hitPart.mass)) * impactVelocity *
                                                   impactVelocity * BDArmorySettings.DMG_MULTIPLIER *
                                                   bulletDmgMult
                                ;
                                //how much heat damage will be applied based on bullet mass, velocity, and part's impact tolerance and mass
                                if (!penetrated)
                                {
                                    heatDamage = heatDamage / 8;
                                }
                                if (fulllyPenetrated)
                                {
                                    heatDamage /= 8;
                                }
                                if (BDArmorySettings.INSTAKILL)
                                //instakill support, will be removed once mod becomes officially MP
                                {
                                    heatDamage = (float)hitPart.maxTemp + 100;
                                    //make heat damage equal to the part's max temperture, effectively instakilling any part it hits
                                }
                                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                                {
                                    Debug.Log("[BDArmory]: Hit! damage applied: " + heatDamage); //debugging stuff
                                }
                                if (hitPart.vessel != sourceVessel)
                                {
                                    hitPart.AddDamage(heatDamage);
                                }

                                float overKillHeatDamage = (float)(hitPart.temperature - hitPart.maxTemp);

                                if (overKillHeatDamage > 0)
                                //if the part is destroyed by overheating, we want to add the remaining heat to attached parts.  This prevents using tiny parts as armor
                                {
                                    overKillHeatDamage *= hitPart.crashTolerance; //reset to raw damage
                                    float numConnectedParts = hitPart.children.Count;
                                    if (hitPart.parent != null)
                                    {
                                        numConnectedParts++;
                                        overKillHeatDamage /= numConnectedParts;
                                        hitPart.parent.AddDamage(overKillHeatDamage /
                                                                 (hitPart.parent.crashTolerance * hitPart.parent.mass));

                                        for (int i = 0; i < hitPart.children.Count; i++)
                                        {
                                            hitPart.children[i].AddDamage(overKillHeatDamage /
                                                                          hitPart.children[i].crashTolerance);
                                        }
                                    }
                                    else
                                    {
                                        overKillHeatDamage /= numConnectedParts;
                                        for (int i = 0; i < hitPart.children.Count; i++)
                                        {
                                            hitPart.children[i].AddDamage(overKillHeatDamage /
                                                                          hitPart.children[i].crashTolerance);
                                        }
                                    }
                                }
                            }

                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                            /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE END////////////////////////////////////////////////////////////////
                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


                            //hitting a Building
                            DestructibleBuilding hitBuilding = null;
                            try
                            {
                                hitBuilding = hit.collider.gameObject.GetComponentUpwards <DestructibleBuilding>();
                            }
                            catch (NullReferenceException)
                            {
                            }
                            if (hitBuilding != null && hitBuilding.IsIntact)
                            {
                                float damageToBuilding = mass * initialSpeed * initialSpeed * BDArmorySettings.DMG_MULTIPLIER /
                                                         12000;
                                if (!penetrated)
                                {
                                    damageToBuilding = damageToBuilding / 8;
                                }
                                hitBuilding.AddDamage(damageToBuilding);
                                if (hitBuilding.Damage > hitBuilding.impactMomentumThreshold)
                                {
                                    hitBuilding.Demolish();
                                }
                                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                                {
                                    Debug.Log("[BDArmory]: bullet hit destructible building! Damage: " +
                                              (damageToBuilding).ToString("0.00") + ", total Damage: " + hitBuilding.Damage);
                                }
                            }
                        }

                        if (hitPart == null || (hitPart != null && hitPart.vessel != sourceVessel))
                        {
                            if (!penetrated && !hasBounced && !fulllyPenetrated)
                            {
                                //ricochet
                                hasBounced = true;
                                if (BDArmorySettings.BULLET_HITS)
                                {
                                    BulletHitFX.CreateBulletHit(hit.point, hit.normal, true);
                                }

                                tracerStartWidth /= 2;
                                tracerEndWidth   /= 2;

                                transform.position = hit.point;
                                currentVelocity    = Vector3.Reflect(currentVelocity, hit.normal);
                                currentVelocity    = (hitAngle / 150) * currentVelocity * 0.65f;

                                Vector3 randomDirection = UnityEngine.Random.rotation * Vector3.one;

                                currentVelocity = Vector3.RotateTowards(currentVelocity, randomDirection,
                                                                        UnityEngine.Random.Range(0f, 5f) * Mathf.Deg2Rad, 0);
                            }
                            else
                            {
                                if (bulletType == PooledBulletTypes.Explosive)
                                {
                                    ExplosionFX.CreateExplosion(hit.point - (ray.direction * 0.1f), radius, blastPower,
                                                                blastHeat, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath);
                                }
                                else if (BDArmorySettings.BULLET_HITS)
                                {
                                    BulletHitFX.CreateBulletHit(hit.point, hit.normal, false);
                                }


                                if (armor != null &&
                                    (penetration * leftPenetration > armor.outerArmorThickness / 1000 * armor.EquivalentThickness ||
                                     fulllyPenetrated))
                                {
                                    switch (armor.explodeMode)
                                    {
                                    case BDArmor.ExplodeMode.Always:
                                        armor.CreateExplosion(hitPart);
                                        break;

                                    case BDArmor.ExplodeMode.Dynamic:
                                        float probability = CalculateExplosionProbability(hitPart);
                                        if (probability > 0.1f)
                                        {
                                            armor.CreateExplosion(hitPart);
                                        }
                                        break;

                                    case BDArmor.ExplodeMode.Never:
                                        break;
                                    }
                                }
                                if (fulllyPenetrated)
                                {
                                    leftPenetration   -= armorData.armorThickness / penetration;
                                    transform.position = armorData.hitResultOut.point;
                                    flightTimeElapsed -= Time.fixedDeltaTime;
                                    prevPosition       = transform.position;
                                    FixedUpdate();
                                    return;
                                }
                                else
                                {
                                    KillBullet();
                                    return;
                                }
                            }
                        }
                    }
                } catch (NullReferenceException e) // Exception handling
                {
                    Debug.Log("[BDArmory]: Ran afoul of exception filter\n" + e.StackTrace);
                }
            }

            if (bulletType == PooledBulletTypes.Explosive && airDetonation && distanceFromStartSqr > detonationRange * detonationRange)
            {
                //detonate
                ExplosionFX.CreateExplosion(transform.position, radius, blastPower, blastHeat, sourceVessel,
                                            currentVelocity.normalized, explModelPath, explSoundPath);
                //GameObject.Destroy(gameObject); //destroy bullet on collision
                KillBullet();
                return;
            }


            prevPosition = currPosition;

            //move bullet
            transform.position += currentVelocity * Time.fixedDeltaTime;
        }
        void Detonate(Vector3 pos, bool missed)
        {
            if (!missed)
            {
                if (tntMass > 0)
                {
                    Vector3 direction = default(Vector3);
                    if (shaped)
                    {
                        direction = (pos + rb.velocity * Time.deltaTime).normalized;
                    }
                    if (gravitic)
                    {
                        using (var hitsEnu = Physics.OverlapSphere(transform.position, blastRadius, 557057).AsEnumerable().GetEnumerator())
                        {
                            while (hitsEnu.MoveNext())
                            {
                                if (hitsEnu.Current == null)
                                {
                                    continue;
                                }

                                Part partHit = hitsEnu.Current.GetComponentInParent <Part>();
                                if (partHit == null)
                                {
                                    continue;
                                }
                                if (ProjectileUtils.IsIgnoredPart(partHit))
                                {
                                    continue;                                         // Ignore ignored parts.
                                }
                                float distance = Vector3.Distance(transform.position, partHit.transform.position);
                                if (gravitic)
                                {
                                    if (partHit.mass > 0)
                                    {
                                        var ME = partHit.vessel.rootPart.FindModuleImplementing <ModuleMassAdjust>();
                                        if (ME == null)
                                        {
                                            ME = (ModuleMassAdjust)partHit.vessel.rootPart.AddModule("ModuleMassAdjust");
                                        }
                                        ME.massMod  += (massMod * (1 - (distance / blastRadius)));                             //this way craft at edge of blast might only get disabled instead of bricked
                                        ME.duration += (BDArmorySettings.WEAPON_FX_DURATION * (1 - (distance / blastRadius))); //can bypass EMP damage cap
                                    }
                                }
                            }
                        }
                    }
                    if (incendiary)
                    {
                        for (int f = 0; f < 20; f++) //throw 20 random raytraces out in a sphere and see what gets tagged
                        {
                            Ray        LoSRay = new Ray(transform.position, VectorUtils.GaussianDirectionDeviation(transform.forward, 170));
                            RaycastHit hit;
                            if (Physics.Raycast(LoSRay, out hit, blastRadius * 1.2f, 9076737)) // only add fires to parts in LoS of blast
                            {
                                KerbalEVA eva      = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>();
                                Part      p        = eva ? eva.part : hit.collider.gameObject.GetComponentInParent <Part>();
                                float     distance = Vector3.Distance(transform.position, hit.point);
                                if (p != null)
                                {
                                    BulletHitFX.AttachFire(hit, p, caliber, sourceVesselName, BDArmorySettings.WEAPON_FX_DURATION * (1 - (distance / blastRadius)), 1, false, true); //else apply fire to occluding part
                                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                                    {
                                        Debug.Log("[BDArmory.Rocket]: Applying fire to " + p.name + " at distance " + distance + "m, for " + BDArmorySettings.WEAPON_FX_DURATION * (1 - (distance / blastRadius)) + " seconds");
                                    }
                                    ;
                                }
                            }
                            if (BDArmorySettings.DRAW_DEBUG_LABELS)
                            {
                                Debug.Log("[Rocket] incendiary raytrace: " + hit.point.x + "; " + hit.point.y + "; " + hit.point.z);
                            }
                        }
                    }
                    if (concussion || EMP || choker)
                    {
                        using (var hitsEnu = Physics.OverlapSphere(transform.position, 25, 557057).AsEnumerable().GetEnumerator())
                        {
                            var craftHit = new HashSet <Vessel>();
                            while (hitsEnu.MoveNext())
                            {
                                if (hitsEnu.Current == null)
                                {
                                    continue;
                                }
                                if (hitsEnu.Current.gameObject == FlightGlobals.currentMainBody.gameObject)
                                {
                                    continue;                                                                         // Ignore terrain hits.
                                }
                                Part partHit = hitsEnu.Current.GetComponentInParent <Part>();
                                if (partHit == null)
                                {
                                    continue;
                                }
                                if (ProjectileUtils.IsIgnoredPart(partHit))
                                {
                                    continue;                                         // Ignore ignored parts.
                                }
                                if (craftHit.Contains(partHit.vessel))
                                {
                                    continue;                                    // Don't hit the same craft multiple times.
                                }
                                craftHit.Add(partHit.vessel);

                                float Distance = Vector3.Distance(partHit.transform.position, this.transform.position);
                                if (partHit != null)
                                {
                                    if (concussion && partHit.mass > 0)
                                    {
                                        partHit.rb.AddForceAtPosition((partHit.transform.position - this.transform.position).normalized * impulse, partHit.transform.position, ForceMode.Acceleration);
                                    }
                                    if (EMP)
                                    {
                                        var MDEC = partHit.vessel.rootPart.FindModuleImplementing <ModuleDrainEC>();
                                        if (MDEC == null)
                                        {
                                            MDEC = (ModuleDrainEC)partHit.vessel.rootPart.AddModule("ModuleDrainEC");
                                        }
                                        MDEC.incomingDamage += ((25 - Distance) * 5); //this way craft at edge of blast might only get disabled instead of bricked
                                        MDEC.softEMP         = false;                 //can bypass EMP damage cap
                                    }
                                    if (choker)
                                    {
                                        var ash = partHit.vessel.rootPart.FindModuleImplementing <ModuleDrainIntakes>();
                                        if (ash == null)
                                        {
                                            ash = (ModuleDrainIntakes)partHit.vessel.rootPart.AddModule("ModuleDrainIntakes");
                                        }
                                        ash.drainDuration += BDArmorySettings.WEAPON_FX_DURATION * (1 - (Distance / 25)); //reduce intake knockout time based on distance from epicenter
                                    }
                                }
                            }
                        }
                        ExplosionFx.CreateExplosion(pos, tntMass, explModelPath, explSoundPath, ExplosionSourceType.Bullet, caliber, null, sourceVesselName, null, direction, true);
                    }
                    else
                    {
                        ExplosionFx.CreateExplosion(pos, tntMass, explModelPath, explSoundPath, ExplosionSourceType.Bullet, caliber, null, sourceVesselName, null, direction);
                    }
                }
            } // needs to be Explosiontype Bullet since missile only returns Module MissileLauncher
            gameObject.SetActive(false);
        }