コード例 #1
0
        void CleanJammerList()
        {
            vessel = GetComponent <Vessel>();

            if (!vessel)
            {
                Destroy(this);
            }
            jammers.RemoveAll(j => j == null);
            jammers.RemoveAll(j => j.vessel != vessel);

            using (var jam = VesselModuleRegistry.GetModules <ModuleECMJammer>(vessel).GetEnumerator())
                while (jam.MoveNext())
                {
                    if (jam.Current == null)
                    {
                        continue;
                    }
                    if (jam.Current.jammerEnabled)
                    {
                        AddJammer(jam.Current);
                    }
                }
            UpdateJammerStrength();
        }
コード例 #2
0
        void VesselChange(Vessel v)
        {
            if (!v.isActiveVessel)
            {
                return;
            }

            bool moduleFound = false;

            using (var mtc = VesselModuleRegistry.GetModules <ModuleTargetingCamera>(v).GetEnumerator())
                while (mtc.MoveNext())
                {
                    Debug.Log("[BDArmory.TargetingCamera]: Vessel switched to vessel with targeting camera.  Refreshing camera state.");

                    if (mtc.Current.cameraEnabled)
                    {
                        mtc.Current.DelayedEnable();
                    }
                    else
                    {
                        mtc.Current.DisableCamera();
                    }
                    moduleFound = true;
                }

            if (!moduleFound)
            {
                DisableCamera();
                ModuleTargetingCamera.windowIsOpen = false;
            }
        }
コード例 #3
0
        void Awake()
        {
            if (!vessel)
            {
                vessel = GetComponent <Vessel>();
            }

            if (!vessel)
            {
                //Debug.Log ("[BDArmory]: TargetInfo was added to a non-vessel");
                Destroy(this);
                return;
            }

            //destroy this if a target info is already attached to the vessel
            foreach (var otherInfo in vessel.gameObject.GetComponents <TargetInfo>())
            {
                if (otherInfo != this)
                {
                    Destroy(this);
                    return;
                }
            }

            Team = null;
            var mf = VesselModuleRegistry.GetMissileFire(vessel, true);

            if (mf != null)
            {
                Team          = mf.Team;
                weaponManager = mf;
            }
            else
            {
                var ml = VesselModuleRegistry.GetMissileBase(vessel, true);
                if (ml != null)
                {
                    isMissile         = true;
                    MissileBaseModule = ml;
                    Team = ml.Team;
                }
            }

            vessel.OnJustAboutToBeDestroyed += AboutToBeDestroyed;

            //add delegate to peace enable event
            BDArmorySetup.OnPeaceEnabled += OnPeaceEnabled;

            //lifeRoutine = StartCoroutine(LifetimeRoutine());              // TODO: CHECK BEHAVIOUR AND SIDE EFFECTS!

            if (!isMissile && Team != null)
            {
                GameEvents.onVesselPartCountChanged.Add(VesselModified);
                //massRoutine = StartCoroutine(MassRoutine());              // TODO: CHECK BEHAVIOUR AND SIDE EFFECTS!
            }
            UpdateTargetPartList();
            GameEvents.onVesselDestroy.Add(CleanFriendliesEngaging);
        }
コード例 #4
0
ファイル: Misc.cs プロジェクト: Geoplex-Official/BDArmory
 public static void ForceDeadVessel(Vessel v)
 {
     Debug.Log("[BDArmory.Misc]: GM Killed Vessel " + v.GetDisplayName());
     foreach (var missileFire in VesselModuleRegistry.GetModules <MissileFire>(v))
     {
         PartExploderSystem.AddPartToExplode(missileFire.part);
         ExplosionFx.CreateExplosion(missileFire.part.transform.position, 0.2f, explModelPath, explSoundPath, ExplosionSourceType.Missile, 0, missileFire.part);
     }
 }
コード例 #5
0
        public TargetSignatureData(Vessel v, float _signalStrength)
        {
            orbital = v.InOrbit();
            orbit   = v.orbit;

            timeAcquired = Time.time;
            vessel       = v;
            velocity     = v.Velocity();

            geoPos       = VectorUtils.WorldPositionToGeoCoords(v.CoM, v.mainBody);
            acceleration = v.acceleration_immediate;
            exists       = true;

            signalStrength = _signalStrength;

            targetInfo = v.gameObject.GetComponent <TargetInfo>();

            // vessel never been picked up on radar before: create new targetinfo record
            if (targetInfo == null)
            {
                targetInfo = v.gameObject.AddComponent <TargetInfo>();
            }

            Team = null;

            if (targetInfo)  // Always true, as we just set it?
            {
                Team = targetInfo.Team;
            }
            else
            {
                var mf = VesselModuleRegistry.GetMissileFire(v, true);
                if (mf != null)
                {
                    Team = mf.Team;
                }
            }

            vesselJammer = v.gameObject.GetComponent <VesselECMJInfo>();

            pingPosition  = Vector2.zero;
            lockedByRadar = null;
        }
コード例 #6
0
        // Begin methods used for prioritizing targets
        public float TargetPriRange(MissileFire myMf) // 1- Target range normalized with max weapon range
        {
            if (myMf == null)
            {
                return(0);
            }
            float thisDist    = (position - myMf.transform.position).magnitude;
            float maxWepRange = 0;

            using (var weapon = VesselModuleRegistry.GetModules <ModuleWeapon>(myMf.vessel).GetEnumerator())
                while (weapon.MoveNext())
                {
                    if (weapon.Current == null)
                    {
                        continue;
                    }
                    maxWepRange = (weapon.Current.GetEngagementRangeMax() > maxWepRange) ? weapon.Current.GetEngagementRangeMax() : maxWepRange;
                }
            float targetPriRange = 1 - Mathf.Clamp(thisDist / maxWepRange, 0, 1);

            return(targetPriRange);
        }
コード例 #7
0
        public float MaxThrust(Vessel v)
        {
            float maxThrust   = 0;
            float finalThrust = 0;

            using (var engines = VesselModuleRegistry.GetModules <ModuleEngines>(v).GetEnumerator())
                while (engines.MoveNext())
                {
                    if (engines.Current == null)
                    {
                        continue;
                    }
                    if (!engines.Current.EngineIgnited)
                    {
                        continue;
                    }

                    MultiModeEngine mme = engines.Current.part.FindModuleImplementing <MultiModeEngine>();
                    if (IsAfterBurnerEngine(mme))
                    {
                        mme.autoSwitch = false;
                    }

                    if (mme && mme.mode != engines.Current.engineID)
                    {
                        continue;
                    }
                    float engineThrust = engines.Current.maxThrust;
                    if (engines.Current.atmChangeFlow)
                    {
                        engineThrust *= engines.Current.flowMultiplier;
                    }
                    maxThrust += Mathf.Max(0f, engineThrust * (engines.Current.thrustPercentage / 100f)); // Don't include negative thrust percentage drives (Danny2462 drives) as they don't contribute to the thrust.

                    finalThrust += engines.Current.finalThrust;
                }
            return(maxThrust);
        }
コード例 #8
0
        private void UpdateList()
        {
            weaponManagers.Clear();

            using (List <Vessel> .Enumerator v = FlightGlobals.Vessels.GetEnumerator())
                while (v.MoveNext())
                {
                    if (v.Current == null || !v.Current.loaded || v.Current.packed)
                    {
                        continue;
                    }
                    if (VesselModuleRegistry.ignoredVesselTypes.Contains(v.Current.vesselType))
                    {
                        continue;
                    }
                    var wms = VesselModuleRegistry.GetMissileFire(v.Current, true);
                    if (wms != null)
                    {
                        if (!ColorAssignments.ContainsKey(wms.teamString))
                        {
                            float rnd = UnityEngine.Random.Range(0f, 100f);
                            ColorAssignments.Add(wms.Team.Name, Color.HSVToRGB((rnd / 100f), 1f, 1f));
                        }
                        if (weaponManagers.TryGetValue(wms.Team.Name, out var teamManagers))
                        {
                            teamManagers.Add(wms);
                        }
                        else
                        {
                            weaponManagers.Add(wms.Team.Name, new List <MissileFire> {
                                wms
                            });
                        }
                    }
                }
        }
コード例 #9
0
        void OnGUI()
        {
            if ((HighLogic.LoadedSceneIsFlight && BDArmorySetup.GAME_UI_ENABLED && !MapView.MapIsEnabled && BDTISettings.TEAMICONS) || HighLogic.LoadedSceneIsFlight && !BDArmorySetup.GAME_UI_ENABLED && !MapView.MapIsEnabled && BDTISettings.TEAMICONS && BDTISettings.PERSISTANT)
            {
                Texture icon;
                float   size = 40;

                using (List <Vessel> .Enumerator v = FlightGlobals.Vessels.GetEnumerator())
                    while (v.MoveNext())
                    {
                        if (v.Current == null)
                        {
                            continue;
                        }
                        if (!v.Current.loaded || v.Current.packed || v.Current.isActiveVessel)
                        {
                            continue;
                        }
                        if (VesselModuleRegistry.ignoredVesselTypes.Contains(v.Current.vesselType))
                        {
                            continue;
                        }

                        if (BDTISettings.MISSILES)
                        {
                            using (var ml = VesselModuleRegistry.GetModules <MissileBase>(v.Current).GetEnumerator())
                                while (ml.MoveNext())
                                {
                                    if (ml.Current == null)
                                    {
                                        continue;
                                    }
                                    if (ml.Current.MissileState != MissileBase.MissileStates.Idle && ml.Current.MissileState != MissileBase.MissileStates.Drop)
                                    {
                                        Vector3 sPos = FlightGlobals.ActiveVessel.vesselTransform.position;
                                        Vector3 tPos = v.Current.vesselTransform.position;
                                        Vector3 Dist = (tPos - sPos);
                                        Vector2 guiPos;
                                        string  UIdist;
                                        string  UoM;
                                        if (Dist.magnitude > 100)
                                        {
                                            if ((Dist.magnitude / 1000) >= 1)
                                            {
                                                UoM    = "km";
                                                UIdist = (Dist.magnitude / 1000).ToString("0.00");
                                            }
                                            else
                                            {
                                                UoM    = "m";
                                                UIdist = Dist.magnitude.ToString("0.0");
                                            }
                                            BDGUIUtils.DrawTextureOnWorldPos(v.Current.CoM, BDTISetup.Instance.TextureIconMissile, new Vector2(20, 20), 0);
                                            if (BDGUIUtils.WorldToGUIPos(ml.Current.vessel.CoM, out guiPos))
                                            {
                                                Rect distRect = new Rect((guiPos.x - 12), (guiPos.y + 10), 100, 32);
                                                GUI.Label(distRect, UIdist + UoM, mIStyle);
                                            }
                                        }
                                    }
                                }
                        }
                        if (BDTISettings.DEBRIS)
                        {
                            if (v.Current.vesselType != VesselType.Debris && !v.Current.isActiveVessel)
                            {
                                continue;
                            }
                            if (v.Current.LandedOrSplashed)
                            {
                                continue;
                            }
                            {
                                Vector3 sPos = FlightGlobals.ActiveVessel.vesselTransform.position;
                                Vector3 tPos = v.Current.vesselTransform.position;
                                Vector3 Dist = (tPos - sPos);
                                if (Dist.magnitude > 100)
                                {
                                    BDGUIUtils.DrawTextureOnWorldPos(v.Current.CoM, BDTISetup.Instance.TextureIconDebris, new Vector2(20, 20), 0);
                                }
                            }
                        }
                    }
                int Teamcount = 0;
                using (var teamManagers = BDTISetup.Instance.weaponManagers.GetEnumerator())
                    while (teamManagers.MoveNext())
                    {
                        Teamcount++;
                        using (var wm = teamManagers.Current.Value.GetEnumerator())
                            while (wm.MoveNext())
                            {
                                if (wm.Current == null)
                                {
                                    continue;
                                }
                                Teamcolor = BDTISetup.Instance.ColorAssignments[wm.Current.Team.Name];
                                IconUIStyle.normal.textColor = Teamcolor;
                                if (wm.Current.vessel.isActiveVessel)
                                {
                                    if (BDTISettings.THREATICON)
                                    {
                                        if (wm.Current.currentTarget == null)
                                        {
                                            continue;
                                        }
                                        Vector3 sPos   = FlightGlobals.ActiveVessel.CoM;
                                        Vector3 tPos   = (wm.Current.currentTarget.Vessel.CoM);
                                        Vector3 RelPos = (tPos - sPos);
                                        if (RelPos.magnitude >= 100)
                                        {
                                            DrawThreatIndicator(wm.Current.vessel.CoM, wm.Current.currentTarget.Vessel.CoM, Teamcolor);
                                        }
                                    }
                                }
                                else
                                {
                                    Vector3 selfPos      = FlightGlobals.ActiveVessel.CoM;
                                    Vector3 targetPos    = (wm.Current.vessel.CoM);
                                    Vector3 targetRelPos = (targetPos - selfPos);
                                    Vector2 guiPos;
                                    float   distance;
                                    string  UIdist;
                                    string  UoM;
                                    string  vName;
                                    string  selectedWeapon = String.Empty;
                                    string  AIstate        = String.Empty;
                                    distance = targetRelPos.magnitude;
                                    if (distance >= 100)
                                    {
                                        if ((distance / 1000) >= 1)
                                        {
                                            UoM    = "km";
                                            UIdist = (distance / 1000).ToString("0.00");
                                        }
                                        else
                                        {
                                            UoM    = "m";
                                            UIdist = distance.ToString("0.0");
                                        }
                                        if ((wm.Current.vessel.vesselType == VesselType.Ship && !wm.Current.vessel.Splashed) || wm.Current.vessel.vesselType == VesselType.Plane)
                                        {
                                            icon = BDTISetup.Instance.TextureIconPlane;
                                        }
                                        else if (wm.Current.vessel.vesselType == VesselType.Base || wm.Current.vessel.vesselType == VesselType.Lander)
                                        {
                                            icon = BDTISetup.Instance.TextureIconBase;
                                        }
                                        else if (wm.Current.vessel.vesselType == VesselType.Rover)
                                        {
                                            icon = BDTISetup.Instance.TextureIconRover;
                                        }
                                        else if (wm.Current.vessel.vesselType == VesselType.Probe)
                                        {
                                            icon = BDTISetup.Instance.TextureIconProbe;
                                        }
                                        else if (wm.Current.vessel.vesselType == VesselType.Ship && wm.Current.vessel.Splashed)
                                        {
                                            icon = BDTISetup.Instance.TextureIconShip;
                                            if (wm.Current.vessel.vesselType == VesselType.Ship && wm.Current.vessel.altitude < -10)
                                            {
                                                icon = BDTISetup.Instance.TextureIconSub;
                                            }
                                        }
                                        else if (wm.Current.vessel.vesselType == VesselType.Debris)
                                        {
                                            icon = BDTISetup.Instance.TextureIconDebris;
                                            size = 20;
                                            IconUIStyle.normal.textColor = XKCDColors.Grey;
                                            Teamcolor = XKCDColors.Grey;
                                        }
                                        else
                                        {
                                            icon = BDTISetup.Instance.TextureIconGeneric;
                                        }
                                        DrawOnScreenIcon(wm.Current.vessel.CoM, icon, new Vector2((size * BDTISettings.ICONSCALE), (size * BDTISettings.ICONSCALE)), Teamcolor, true);
                                        if (BDTISettings.THREATICON)
                                        {
                                            if (wm.Current.currentTarget != null)
                                            {
                                                if (!wm.Current.currentTarget.Vessel.isActiveVessel)
                                                {
                                                    DrawThreatIndicator(wm.Current.vessel.CoM, wm.Current.currentTarget.Vessel.CoM, Teamcolor);
                                                }
                                            }
                                        }
                                        if (BDGUIUtils.WorldToGUIPos(wm.Current.vessel.CoM, out guiPos))
                                        {
                                            if (BDTISettings.VESSELNAMES)
                                            {
                                                vName = wm.Current.vessel.vesselName;
                                                Rect nameRect = new Rect((guiPos.x + (24 * BDTISettings.ICONSCALE)), guiPos.y - 4, 100, 32);
                                                GUI.Label(nameRect, vName, IconUIStyle);
                                            }
                                            if (BDTISettings.TEAMNAMES)
                                            {
                                                Rect teamRect = new Rect((guiPos.x + (16 * BDTISettings.ICONSCALE)), (guiPos.y - (19 * BDTISettings.ICONSCALE)), 100, 32);
                                                GUI.Label(teamRect, "Team: " + $"{wm.Current.Team.Name}", IconUIStyle);
                                            }

                                            if (BDTISettings.SCORE)
                                            {
                                                BDArmory.Control.ScoringData scoreData = null;
                                                int Score = 0;

                                                if (BDACompetitionMode.Instance.Scores.ContainsKey(wm.Current.vessel.vesselName))
                                                {
                                                    scoreData = BDACompetitionMode.Instance.Scores[wm.Current.vessel.vesselName];
                                                    Score     = scoreData.Score;
                                                }
                                                if (VesselSpawner.Instance.vesselsSpawningContinuously)
                                                {
                                                    if (VesselSpawner.Instance.continuousSpawningScores.ContainsKey(wm.Current.vessel.vesselName))
                                                    {
                                                        Score += VesselSpawner.Instance.continuousSpawningScores[wm.Current.vessel.vesselName].cumulativeHits;
                                                    }
                                                }

                                                Rect scoreRect = new Rect((guiPos.x + (16 * BDTISettings.ICONSCALE)), (guiPos.y + (14 * BDTISettings.ICONSCALE)), 100, 32);
                                                GUI.Label(scoreRect, "Score: " + Score, IconUIStyle);
                                            }
                                            if (BDTISettings.HEALTHBAR)
                                            {
                                                double hpPercent = 1;
                                                hpPercent = Mathf.Clamp((1 - ((wm.Current.totalHP - wm.Current.vessel.parts.Count) / wm.Current.totalHP)), 0, 1);
                                                if (hpPercent > 0)
                                                {
                                                    Rect barRect    = new Rect((guiPos.x - (32 * BDTISettings.ICONSCALE)), (guiPos.y + (30 * BDTISettings.ICONSCALE)), (64 * BDTISettings.ICONSCALE), 12);
                                                    Rect healthRect = new Rect((guiPos.x - (30 * BDTISettings.ICONSCALE)), (guiPos.y + (32 * BDTISettings.ICONSCALE)), (60 * (float)hpPercent * BDTISettings.ICONSCALE), 8);
                                                    //GUI.Label(healthRect, "Team: " + $"{wm.Current.Team.Name}", IconUIStyle);
                                                    BDGUIUtils.DrawRectangle(barRect, XKCDColors.Grey);
                                                    BDGUIUtils.DrawRectangle(healthRect, Color.HSVToRGB((85f * (float)hpPercent) / 255, 1f, 1f));
                                                }
                                                Rect distRect = new Rect((guiPos.x - 12), (guiPos.y + (45 * BDTISettings.ICONSCALE)), 100, 32);
                                                GUI.Label(distRect, UIdist + UoM, IconUIStyle);
                                            }
                                            else
                                            {
                                                Rect distRect = new Rect((guiPos.x - 12), (guiPos.y + (20 * BDTISettings.ICONSCALE)), 100, 32);
                                                GUI.Label(distRect, UIdist + UoM, IconUIStyle);
                                            }
                                            if (BDTISettings.TELEMETRY)
                                            {
                                                selectedWeapon = "Using: " + wm.Current.selectedWeaponString;
                                                AIstate        = "No AI";
                                                if (wm.Current.AI != null)
                                                {
                                                    AIstate = "Pilot " + wm.Current.AI.currentStatus;
                                                }
                                                Rect telemetryRect = new Rect((guiPos.x + (32 * BDTISettings.ICONSCALE)), guiPos.y + 32, 200, 32);
                                                GUI.Label(telemetryRect, selectedWeapon, IconUIStyle);
                                                Rect telemetryRect2 = new Rect((guiPos.x + (32 * BDTISettings.ICONSCALE)), guiPos.y + 48, 200, 32);
                                                GUI.Label(telemetryRect2, AIstate, IconUIStyle);
                                                if (wm.Current.isFlaring || wm.Current.isChaffing || wm.Current.isECMJamming)
                                                {
                                                    Rect telemetryRect3 = new Rect((guiPos.x + (32 * BDTISettings.ICONSCALE)), guiPos.y + 64, 200, 32);
                                                    GUI.Label(telemetryRect3, "Deploying Counter-Measures", IconUIStyle);
                                                }
                                                Rect SpeedRect = new Rect((guiPos.x - (96 * BDTISettings.ICONSCALE)), guiPos.y + 64, 100, 32);
                                                GUI.Label(SpeedRect, "Speed: " + wm.Current.vessel.speed.ToString("0.0") + "m/s", IconUIStyle);
                                                Rect RAltRect = new Rect((guiPos.x - (96 * BDTISettings.ICONSCALE)), guiPos.y + 80, 100, 32);
                                                GUI.Label(RAltRect, "Alt: " + wm.Current.vessel.altitude.ToString("0.0") + "m", IconUIStyle);
                                                Rect ThrottleRect = new Rect((guiPos.x - (96 * BDTISettings.ICONSCALE)), guiPos.y + 96, 100, 32);
                                                GUI.Label(ThrottleRect, "Throttle: " + Mathf.CeilToInt(wm.Current.vessel.ctrlState.mainThrottle * 100) + "%", IconUIStyle);
                                            }
                                        }
                                    }
                                }
                            }
                    }
            }
        }
コード例 #10
0
        float MaxEngineAccel(float requestAccel, out float dragAccel)
        {
            float maxThrust   = 0;
            float finalThrust = 0;

            multiModeEngines.Clear();

            using (var engines = VesselModuleRegistry.GetModules <ModuleEngines>(vessel).GetEnumerator())
                while (engines.MoveNext())
                {
                    if (engines.Current == null)
                    {
                        continue;
                    }
                    if (!engines.Current.EngineIgnited)
                    {
                        continue;
                    }

                    MultiModeEngine mme = engines.Current.part.FindModuleImplementing <MultiModeEngine>();
                    if (IsAfterBurnerEngine(mme))
                    {
                        multiModeEngines.Add(mme);
                        mme.autoSwitch = false;
                    }

                    if (mme && mme.mode != engines.Current.engineID)
                    {
                        continue;
                    }
                    float engineThrust = engines.Current.maxThrust;
                    if (engines.Current.atmChangeFlow)
                    {
                        engineThrust *= engines.Current.flowMultiplier;
                    }
                    maxThrust += Mathf.Max(0f, engineThrust * (engines.Current.thrustPercentage / 100f)); // Don't include negative thrust percentage drives (Danny2462 drives) as they don't contribute to the thrust.

                    finalThrust += engines.Current.finalThrust;
                }

            debugThrust = maxThrust;

            float vesselMass = vessel.GetTotalMass();

            float accel = maxThrust / vesselMass; // This assumes that all thrust is in the same direction.

            //estimate drag
            float   estimatedCurrentAccel = finalThrust / vesselMass - GravAccel();
            Vector3 vesselAccelProjected  = Vector3.Project(vessel.acceleration_immediate, vessel.velocityD.normalized);
            float   actualCurrentAccel    = vesselAccelProjected.magnitude * Mathf.Sign(Vector3.Dot(vesselAccelProjected, vessel.velocityD.normalized));
            float   accelError            = (actualCurrentAccel - estimatedCurrentAccel); // /2 -- why divide by 2 here?

            dragAccel = accelError;

            possibleAccel += accel; // This assumes that the acceleration from engines is in the same direction as the original possibleAccel.

            //use multimode afterburner for extra accel if lacking
            using (List <MultiModeEngine> .Enumerator mmes = multiModeEngines.GetEnumerator())
                while (mmes.MoveNext())
                {
                    if (mmes.Current == null)
                    {
                        continue;
                    }
                    if (allowAfterburner && accel < requestAccel * 0.2f)
                    {
                        if (mmes.Current.runningPrimary)
                        {
                            mmes.Current.Events["ModeEvent"].Invoke();
                        }
                    }
                    else if (!allowAfterburner || accel > requestAccel * 1.5f)
                    {
                        if (!mmes.Current.runningPrimary)
                        {
                            mmes.Current.Events["ModeEvent"].Invoke();
                        }
                    }
                }
            return(accel);
        }
コード例 #11
0
        public static void CheckDamageFX(Part part, float caliber, float penetrationFactor, bool explosivedamage, bool incendiary, string attacker, RaycastHit hitLoc)
        {
            if (!BDArmorySettings.BATTLEDAMAGE || BDArmorySettings.PAINTBALL_MODE)
            {
                return;
            }
            if (ProjectileUtils.IsIgnoredPart(part))
            {
                return;                                                                                                                                         // Ignore ignored parts.
            }
            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.5f)
                        {
                            return;
                        }
                    }
                    if (penetrationFactor > 1.2)
                    {
                        if (alreadyburning != null)
                        {
                            BulletHitFX.AttachFire(hitLoc, part, caliber, attacker);
                        }
                        else
                        {
                            BulletHitFX.AttachLeak(hitLoc, part, caliber, explosivedamage, incendiary, 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.33;
                        }
                        if (incendiary)
                        {
                            Diceroll *= 0.66;
                        }
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BDArmory.BattleDamageHandler]: Battery Dice Roll: " + Diceroll);
                        }
                        if (Diceroll <= BDArmorySettings.BD_DAMAGE_CHANCE)
                        {
                            BulletHitFX.AttachFire(hitLoc, part, caliber, attacker);
                        }
                    }
                }
            }
            //AmmoBins
            if (BDArmorySettings.BD_AMMOBINS && 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)
                {
                    ammo.SourceVessel = attacker; //moving this here so shots that destroy ammoboxes outright still report attacker if 'Ammo Explodes When Destroyed' is enabled
                    if (penetrationFactor > 1.2)
                    {
                        double Diceroll = UnityEngine.Random.Range(0, 100);
                        if (incendiary)
                        {
                            Diceroll *= 0.66;
                        }
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BDArmory.BattleDamageHandler]: Ammo TAC DiceRoll: " + Diceroll + "; needs: " + damageChance);
                        }
                        if (Diceroll <= (damageChance) && part.GetDamagePercentage() < 0.95f)
                        {
                            ammo.DetonateIfPossible();
                        }
                    }
                    if (!ammo.hasDetonated) //hit didn't destroy box
                    {
                        ammo.SourceVessel = ammo.vessel.GetName();
                    }
                }
            }
            //Propulsaion Damage
            if (BDArmorySettings.BD_PROPULSION)
            {
                if (part.isEngine() && part.GetDamagePercentage() < 0.95f) //first hit's free
                {
                    foreach (var engine in part.GetComponentsInChildren <ModuleEngines>())
                    {
                        bool isSRB      = false;
                        bool SRBFuelled = false;
                        if (!engine.allowShutdown && engine.throttleLocked)
                        {
                            isSRB = true;
                            using (IEnumerator <PartResource> resources = part.Resources.GetEnumerator())
                                while (resources.MoveNext())
                                {
                                    if (resources.Current == null)
                                    {
                                        continue;
                                    }
                                    if (resources.Current.resourceName.Contains("SolidFuel"))
                                    {
                                        if (resources.Current.amount > 1d)
                                        {
                                            SRBFuelled = true;
                                        }
                                    }
                                }
                        }
                        if (engine.thrustPercentage > BDArmorySettings.BD_PROP_FLOOR) //engines take thrust damage per hit
                        {
                            //AP does bonus damage
                            engine.thrustPercentage -= (((1 - part.GetDamagePercentage()) * (penetrationFactor / 2)) * BDArmorySettings.BD_PROP_DAM_RATE) * 10; //convert from damagepercent to thrustpercent
                            Mathf.Clamp(engine.thrustPercentage, BDArmorySettings.BD_PROP_FLOOR, 100);                                                          //even heavily damaged engines will still put out something
                            if (BDArmorySettings.DRAW_DEBUG_LABELS)
                            {
                                Debug.Log("[BDArmory.BattleDamageHandler]: engine thrust: " + engine.thrustPercentage);
                            }
                            engine.PlayFlameoutFX(true);

                            /*
                             * 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 && !isSRB) //engine isn't a srb
                            {
                                BulletHitFX.AttachLeak(hitLoc, part, caliber, explosivedamage, incendiary, attacker);
                            }
                        }
                        if (part.GetDamagePercentage() < 0.50f || (part.GetDamagePercentage() < 0.625f && penetrationFactor > 2))
                        {
                            var alreadyburning = part.GetComponentInChildren <FireFX>();
                            if (isSRB) //srbs are steel tubes full of explosives; treat differently
                            {
                                if ((explosivedamage || incendiary) && SRBFuelled)
                                {
                                    BulletHitFX.AttachFire(hitLoc, part, caliber, attacker);
                                }
                            }
                            else
                            {
                                if (alreadyburning == null)
                                {
                                    BulletHitFX.AttachFire(hitLoc, part, caliber, attacker, -1, 1, true);
                                }
                            }
                        }
                        if (part.GetDamagePercentage() < (BDArmorySettings.BD_PROP_FLAMEOUT / 100))
                        {
                            if (engine.EngineIgnited)
                            {
                                if (isSRB) //SRB is lit, and casing integrity fails due to damage; boom
                                {
                                    var Rupture = (ModuleCASE)part.AddModule("ModuleCASE");
                                    Rupture.CASELevel = 0;
                                    Rupture.DetonateIfPossible();
                                }
                                else
                                {
                                    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;
                        }
                        if (incendiary)
                        {
                            HEBonus = 1.1f;
                        }
                        intake.intakeSpeed *= (1 - (((1 - part.GetDamagePercentage()) * HEBonus) * (BDArmorySettings.BD_PROP_DAM_RATE / 2))); //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.0005f, 99999);                                                         //even shredded intake ducting will still get some air to engines
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BDArmory.BattleDamageHandler]: 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.4;
                        }
                        if (incendiary)
                        {
                            HEBonus = 1.25;
                        }
                        //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("[BDArmory.BattleDamageHandler]: Gimbal DiceRoll: " + Diceroll);
                        }
                        if (Diceroll <= (BDArmorySettings.BD_DAMAGE_CHANCE * HEBonus))
                        {
                            gimbal.enabled     = false;
                            gimbal.gimbalRange = 0;
                            if (incendiary)
                            {
                                BulletHitFX.AttachFire(hitLoc, part, caliber, attacker, 20);
                            }
                        }
                    }
                }
            }
            //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("[BDArmory.BattleDamageHandler]: " + 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 (incendiary)
                        {
                            HEBonus = 1.1f;
                        }
                        if (Diceroll <= (BDArmorySettings.BD_DAMAGE_CHANCE * HEBonus))
                        {
                            aileron.actuatorSpeed    = 0;
                            aileron.authorityLimiter = 0;
                            aileron.ctrlSurfaceRange = 0;
                            if (incendiary)
                            {
                                BulletHitFX.AttachFire(hitLoc, part, caliber, attacker, 10);
                            }
                        }
                    }
                }
            }
            //Subsystems
            if (BDArmorySettings.BD_SUBSYSTEMS)
            {
                double Diceroll = UnityEngine.Random.Range(0, 100);
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BDArmory.BattleDamageHandler]: 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("[BDArmory.BattleDamageHandler]: " + part.name + "took subsystem damage");
                    }
                    if (Diceroll <= (damageChance * 2))
                    {
                        if (incendiary)
                        {
                            BulletHitFX.AttachFire(hitLoc, part, caliber, attacker, 20);
                        }
                    }
                }
            }
            //Command parts
            if (BDArmorySettings.BD_COCKPITS && penetrationFactor > 1.2f && 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("[BDArmory.BattleDamageHandler]: Command DiceRoll: " + ControlDiceRoll);
                    }
                    if (ControlDiceRoll <= (BDArmorySettings.BD_DAMAGE_CHANCE * 2))
                    {
                        using (List <Part> .Enumerator craftPart = part.vessel.parts.GetEnumerator())
                        {
                            using (var control = VesselModuleRegistry.GetModules <BDModulePilotAI>(part.vessel).GetEnumerator()) // FIXME should this be IBDAIControl?
                                while (control.MoveNext())
                                {
                                    if (control.Current == null)
                                    {
                                        continue;
                                    }
                                    control.Current.evasionThreshold += 5;     //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("[BDArmory.BattleDamageHandler]: " + part.name + "took command damage");
                            }
                        }
                    }
                }
            }
            if (part.protoModuleCrew.Count > 0 && penetrationFactor > 1.5f && 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("[BDArmory.BattleDamageHandler]: 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("[BDArmory.BattleDamageHandler]: " + 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 on " + part.vessel.GetName() + "! " + crewMember.name + " killed!", 5.0f, ScreenMessageStyle.UPPER_LEFT);
                            BDACompetitionMode.Instance.OnVesselModified(part.vessel);
                        }
                    }
                }
            }
        }