public void Update()
 {
     if (HighLogic.LoadedSceneIsFlight)
     {
         drainDuration -= Time.deltaTime;
         if (drainDuration <= 0)
         {
             using (var intake = VesselModuleRegistry.GetModules <ModuleResourceIntake>(vessel).GetEnumerator())
                 while (intake.MoveNext())
                 {
                     if (intake.Current == null)
                     {
                         continue;
                     }
                     intake.Current.intakeEnabled = true;
                 }
             part.RemoveModule(this);
         }
     }
     if (!initialized)
     {
         //Debug.Log("[BDArmory.ModuleDrainIntakes]: " + this.part.name + "choked!");
         initialized = true;
         using (var intake = VesselModuleRegistry.GetModules <ModuleResourceIntake>(vessel).GetEnumerator())
             while (intake.MoveNext())
             {
                 if (intake.Current == null)
                 {
                     continue;
                 }
                 intake.Current.intakeEnabled = false;
             }
     }
 }
        void UnslaveTurrets()
        {
            using (var mtc = VesselModuleRegistry.GetModules <ModuleTargetingCamera>(vessel).GetEnumerator())
                while (mtc.MoveNext())
                {
                    if (mtc.Current == null)
                    {
                        continue;
                    }
                    mtc.Current.slaveTurrets = false;
                }

            using (var rad = VesselModuleRegistry.GetModules <ModuleRadar>(vessel).GetEnumerator())
                while (rad.MoveNext())
                {
                    if (rad.Current == null)
                    {
                        continue;
                    }
                    rad.Current.slaveTurrets = false;
                }

            if (weaponManager)
            {
                weaponManager.slavingTurrets = false;
            }

            slaveTurrets = false;
        }
        public override void OnStart(StartState state)
        {
            if (HighLogic.LoadedSceneIsFlight)
            {
                part.explosionPotential        = 1.0f;
                part.OnJustAboutToBeDestroyed += DetonateIfPossible;
                part.force_activate();
                sourcevessel = vessel;
                var MF = VesselModuleRegistry.GetModule <MissileFire>(vessel, true);
                if (MF != null)
                {
                    sourcevessel = MF.vessel;             // grab the vessel the Weapon manager is on at start
                }
            }
            if (part.FindModuleImplementing <MissileLauncher>() == null)
            {
                isMissile = false;
            }
            GuiSetup();
            if (BDArmorySettings.ADVANCED_EDIT)
            {
                //Fields["tntMass"].guiActiveEditor = true;

                //((UI_FloatRange)Fields["tntMass"].uiControlEditor).minValue = 0f;
                //((UI_FloatRange)Fields["tntMass"].uiControlEditor).maxValue = 3000f;
                //((UI_FloatRange)Fields["tntMass"].uiControlEditor).stepIncrement = 5f;
            }

            CalculateBlast();
        }
        void LoadWingmen()
        {
            wingmen = new List <IBDAIControl>();

            if (savedWingmen == string.Empty)
            {
                return;
            }
            IEnumerator <string> wingIDs = savedWingmen.Split(new char[] { ',' }).AsEnumerable().GetEnumerator();

            while (wingIDs.MoveNext())
            {
                using (var vs = BDATargetManager.LoadedVessels.GetEnumerator())
                    while (vs.MoveNext())
                    {
                        if (vs.Current == null || !vs.Current.loaded || VesselModuleRegistry.ignoredVesselTypes.Contains(vs.Current.vesselType))
                        {
                            continue;
                        }

                        if (vs.Current.id.ToString() != wingIDs.Current)
                        {
                            continue;
                        }
                        var pilot = VesselModuleRegistry.GetIBDAIControl(vs.Current, true);
                        if (pilot != null)
                        {
                            wingmen.Add(pilot);
                        }
                    }
            }
            wingIDs.Dispose();
        }
Beispiel #5
0
 protected void UpdateWeaponManager()
 {
     weaponManager = VesselModuleRegistry.GetModule <MissileFire>(vessel);
     if (weaponManager != null)
     {
         weaponManager.AI = this;
     }
 }
        public override void OnStart(StartState state)
        {
            if (HighLogic.LoadedSceneIsFlight)
            {
                pingsData          = new TargetSignatureData[dataCount];
                pingWorldPositions = new Vector3[dataCount];
                TargetSignatureData.ResetTSDArray(ref pingsData);
                launchWarnings = new List <TargetSignatureData>();

                rwrIconLabelStyle                  = new GUIStyle();
                rwrIconLabelStyle.alignment        = TextAnchor.MiddleCenter;
                rwrIconLabelStyle.normal.textColor = Color.green;
                rwrIconLabelStyle.fontSize         = 12;
                rwrIconLabelStyle.border           = new RectOffset(0, 0, 0, 0);
                rwrIconLabelStyle.clipping         = TextClipping.Overflow;
                rwrIconLabelStyle.wordWrap         = false;
                rwrIconLabelStyle.fontStyle        = FontStyle.Bold;

                audioSource              = gameObject.AddComponent <AudioSource>();
                audioSource.minDistance  = 500;
                audioSource.maxDistance  = 1000;
                audioSource.spatialBlend = 1;
                audioSource.dopplerLevel = 0;
                audioSource.loop         = false;

                UpdateVolume();
                BDArmorySetup.OnVolumeChange += UpdateVolume;

                if (!WindowRectRWRInitialized)
                {
                    BDArmorySetup.WindowRectRwr = new Rect(BDArmorySetup.WindowRectRwr.x, BDArmorySetup.WindowRectRwr.y, RwrDisplayRect.height + BorderSize, RwrDisplayRect.height + BorderSize + HeaderSize);
                    // BDArmorySetup.WindowRectRwr = new Rect(40, Screen.height - RwrDisplayRect.height, RwrDisplayRect.height + BorderSize, RwrDisplayRect.height + BorderSize + HeaderSize);
                    WindowRectRWRInitialized = true;
                }

                using (var mf = VesselModuleRegistry.GetModules <MissileFire>(vessel).GetEnumerator())
                    while (mf.MoveNext())
                    {
                        if (mf.Current == null)
                        {
                            continue;
                        }
                        mf.Current.rwr = this; // Set the rwr on all weapon managers to this.
                        if (!weaponManager)
                        {
                            weaponManager = mf.Current; // Set the first found weapon manager as the one in control.
                        }
                    }
                //if (rwrEnabled) EnableRWR();
                EnableRWR();
            }
        }
        public void EnableRadar()
        {
            EnsureVesselRadarData();
            radarEnabled = true;

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

            if (mf != null && vesselRadarData != null)
            {
                vesselRadarData.weaponManager = mf;
            }
            UpdateToggleGuiName();
            vesselRadarData.AddRadar(this);
        }
Beispiel #8
0
 private void ConfigureKerbalEVA(KerbalEVA kerbalEVA)
 {
     chute = VesselModuleRegistry.GetModule <ModuleEvaChute>(kerbalEVA.vessel);
     if (chute != null)
     {
         chute.deploymentState = ModuleEvaChute.deploymentStates.STOWED;                                   // Make sure the chute is stowed.
     }
     if ((Versioning.version_major == 1 && Versioning.version_minor > 10) || Versioning.version_major > 1) // Introduced in 1.11
     {
         DisableConstructionMode(kerbalEVA);
         if (BDArmorySettings.KERBAL_SAFETY_INVENTORY == 2)
         {
             RemoveJetpack(kerbalEVA);
         }
     }
 }
        private void EnableVessel()
        {
            foreach (Part p in vessel.parts)
            {
                var engine   = p.FindModuleImplementing <ModuleEngines>();
                var engineFX = p.FindModuleImplementing <ModuleEnginesFX>();

                if (engine != null)
                {
                    engine.allowRestart = true;
                }
                if (engineFX != null)
                {
                    engineFX.allowRestart = true;
                }
                var command = p.FindModuleImplementing <ModuleCommand>();
                var weapon  = p.FindModuleImplementing <ModuleWeapon>();
                if (weapon != null)
                {
                    weapon.weaponState = ModuleWeapon.WeaponStates.Disabled; //allow weapons to be used again
                }
                if (command != null)
                {
                    command.minimumCrew /= 10; //more elegant than a dict storing every crew part's cap to restore to original amount
                }
                var AI = p.FindModuleImplementing <IBDAIControl>();
                if (AI != null)
                {
                    AI.ActivatePilot(); //It's Alive!
                }
                var WM = p.FindModuleImplementing <MissileFire>();
                if (WM != null)
                {
                    WM.guardMode   = true;
                    WM.debilitated = false;
                }
            }
            vessel.ActionGroups.ToggleGroup(KSPActionGroup.Custom10);                                         // restart engines
            if (!VesselModuleRegistry.GetModules <ModuleEngines>(vessel).Any(engine => engine.EngineIgnited)) // Find vessels that didn't activate their engines on AG10 and fire their next stage.
            {
                foreach (var engine in VesselModuleRegistry.GetModules <ModuleEngines>(vessel))
                {
                    engine.Activate();
                }
            }
            disabled = false;
        }
 void CheckAttached(Vessel v)
 {
     if (v != vessel || hasDetonated || goingCritical)
     {
         return;
     }
     VesselModuleRegistry.OnVesselModified(v);
     if (VesselModuleRegistry.GetModuleCount <MissileFire>(v) == 0)
     {
         if (BDArmorySettings.DRAW_DEBUG_LABELS)
         {
             Debug.Log("[BDArmory.NukeTest]: Nuclear engine on " + Sourcevessel + " has become detached.");
         }
         goingCritical = true;
         StartCoroutine(DelayedDetonation(0.5f));
     }
 }
Beispiel #11
0
 /// <summary>
 /// If guard mode off, and UI target is of the opposing team, set it as target
 /// </summary>
 protected void GetNonGuardTarget()
 {
     if (weaponManager != null && !weaponManager.guardMode)
     {
         if (vessel.targetObject != null)
         {
             var nonGuardTargetVessel = vessel.targetObject.GetVessel();
             if (nonGuardTargetVessel != null)
             {
                 var targetWeaponManager = VesselModuleRegistry.GetModule <MissileFire>(nonGuardTargetVessel);
                 if (targetWeaponManager != null && weaponManager.Team.IsEnemy(targetWeaponManager.Team))
                 {
                     targetVessel = (Vessel)vessel.targetObject;
                 }
             }
         }
     }
 }
        void RefreshFriendlies()
        {
            if (!weaponManager)
            {
                return;
            }
            friendlies = new List <IBDAIControl>();
            using (var vs = BDATargetManager.LoadedVessels.GetEnumerator())
                while (vs.MoveNext())
                {
                    if (vs.Current == null)
                    {
                        continue;
                    }
                    if (!vs.Current.loaded || vs.Current == vessel || VesselModuleRegistry.ignoredVesselTypes.Contains(vs.Current.vesselType))
                    {
                        continue;
                    }

                    IBDAIControl pilot = VesselModuleRegistry.GetIBDAIControl(vs.Current, true);
                    if (pilot == null)
                    {
                        continue;
                    }
                    MissileFire wm = VesselModuleRegistry.GetMissileFire(vs.Current, true);
                    if (wm == null || wm.Team != weaponManager.Team)
                    {
                        continue;
                    }
                    friendlies.Add(pilot);
                }

            //TEMPORARY
            wingmen = new List <IBDAIControl>();
            using (var fs = friendlies.GetEnumerator())
                while (fs.MoveNext())
                {
                    if (fs.Current == null)
                    {
                        continue;
                    }
                    wingmen.Add(fs.Current);
                }
        }
        public void Fire()
        {
            GameObject target = null;

            if (vessel.targetObject != null)
            {
                target = vessel.targetObject.GetVessel().gameObject;
            }

            part.decouple(0);

            foreach (BDModularGuidance bdmm in VesselModuleRegistry.GetModules <BDModularGuidance>(vessel))
            {
                bdmm.HasFired = true;
                //bdmm.target = target;
            }
            // foreach (BDExplosivePart bde in VesselModuleRegistry.GetModules<BDExplosivePart>(vessel))
            // {
            //     //bde.target = target;
            // }
        }
        void CommandButton(CommandFunction func, string buttonLabel, ref float buttonLine, float startY, float margin,
                           float buttonGap, float buttonWidth, float buttonHeight, bool sendToWingmen, bool pressed, object data)
        {
            float yPos = startY + margin + ((buttonHeight + buttonGap) * buttonLine);

            if (GUI.Button(new Rect(margin, yPos, buttonWidth, buttonHeight), buttonLabel,
                           pressed ? BDArmorySetup.BDGuiSkin.box : BDArmorySetup.BDGuiSkin.button))
            {
                if (sendToWingmen)
                {
                    if (wingmen.Count > 0)
                    {
                        List <int> .Enumerator index = focusIndexes.GetEnumerator();
                        while (index.MoveNext())
                        {
                            func(wingmen[index.Current], index.Current, data);
                        }
                        index.Dispose();
                    }

                    if (commandSelf)
                    {
                        using (var ai = VesselModuleRegistry.GetModules <IBDAIControl>(vessel).GetEnumerator())
                            while (ai.MoveNext())
                            {
                                func(ai.Current, -1, data); // Note: this commands *all* AIs on the vessel.
                            }
                    }
                }
                else
                {
                    func(null, -1, null);
                }
            }

            buttonLine++;
        }
 public override void OnFixedUpdate()
 {
     base.OnFixedUpdate();
     if (HighLogic.LoadedSceneIsFlight)
     {
         if (!isMissile)
         {
             if (IFF_On)
             {
                 updateTimer -= Time.fixedDeltaTime;
                 if (updateTimer < 0)
                 {
                     GetTeamID();        //have this only called once a sec
                     updateTimer = 1.0f; //next update in half a sec only
                 }
             }
             if (manualOverride) // don't call proximity code if a missile/MMG, use theirs
             {
                 if (Armed)
                 {
                     if (VesselModuleRegistry.GetModule <MissileFire>(vessel) == null)
                     {
                         if (sourcevessel != null && sourcevessel != part.vessel)
                         {
                             distanceFromStart = Vector3.Distance(part.vessel.transform.position, sourcevessel.transform.position);
                         }
                     }
                     if (Checkproximity(distanceFromStart))
                     {
                         Detonate();
                     }
                 }
             }
         }
     }
 }
Beispiel #16
0
        // [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "#LOC_BDArmory_EjectOnImpendingDoom", // Eject if doomed
        //     groupName = "pilotAI_Ejection", groupDisplayName = "#LOC_BDArmory_PilotAI_Ejection", groupStartCollapsed = true),
        //     UI_FloatRange(minValue = 0f, maxValue = 1f, stepIncrement = 0.02f, scene = UI_Scene.All)]
        // public float ejectOnImpendingDoom = 0.2f; // Time to impact at which to eject.
        #endregion

        /// <summary>
        /// Begin managing a crew member in a part.
        /// </summary>
        /// <param name="crew">The proto crew member.</param>
        /// <param name="part">The part.</param>
        public IEnumerator Configure(ProtoCrewMember crew, Part part)
        {
            if (crew == null)
            {
                Debug.LogError("[BDArmory.KerbalSafety]: Cannot manage null crew.");
                Destroy(this);
                yield break;
            }
            if (part == null)
            {
                Debug.LogError("[BDArmory.KerbalSafety]: Crew cannot exist outside of a part.");
                Destroy(this);
                yield break;
            }
            while (part.vessel != null && (!part.vessel.loaded || part.vessel.packed))
            {
                yield return(new WaitForFixedUpdate());                                                                       // Wait for the vessel to be loaded. (Avoids kerbals not being registered in seats.)
            }
            if (part.vessel == null)
            {
                yield break;
            }
            kerbalName = crew.displayName;
            this.crew  = crew;
            switch (BDArmorySettings.KERBAL_SAFETY_INVENTORY)
            {
            case 1:
                this.crew.ResetInventory(true);     // Reset the inventory to the default of a chute and a jetpack.
                break;

            case 2:
                this.crew.ResetInventory(false);     // Reset the inventory to just a chute.
                break;
            }
            this.part = part;
            if (part.IsKerbalEVA())
            {
                this.kerbalEVA = part.GetComponent <KerbalEVA>();
                if (kerbalEVA.IsSeated())
                {
                    bool found = false;
                    foreach (var s in VesselModuleRegistry.GetModules <KerbalSeat>(part.vessel))
                    {
                        if (s.Occupant == part)
                        {
                            seat  = s;
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        Debug.LogWarning("[BDArmory.KerbalSafety]: Failed to find the kerbal seat that " + kerbalName + " occupies.");
                        yield break;
                    }
                }
                else // Free-falling EVA kerbal.
                {
                    ejected = true;
                    StartCoroutine(DelayedChuteDeployment());
                    StartCoroutine(RecoverWhenPossible());
                }
                ConfigureKerbalEVA(kerbalEVA);
            }
            AddHandlers();
            KerbalSafetyManager.Instance.kerbals.Add(kerbalName, this);
            if (BDArmorySettings.DRAW_DEBUG_LABELS)
            {
                Debug.Log("[BDArmory.KerbalSafety]: Managing the safety of " + kerbalName + (ejected ? " on EVA" : " in " + part.vessel.vesselName) + ".");
            }
            OnVesselModified(part.vessel); // Immediately check the vessel.
        }
        private void GetTeamID()
        {
            var weaponManager = VesselModuleRegistry.GetModule <MissileFire>(sourcevessel);

            IFFID = weaponManager != null ? weaponManager.teamString : null;
        }
Beispiel #18
0
        public IEnumerator PerformanceTest()
        {
            var wait = new WaitForSeconds(0.1f);

            {
                // Note: this test has significant GC allocations due to the allocation of an intermediate list.
                int count     = 0;
                int iters     = 100000;
                var startTime = Time.realtimeSinceStartup;
                for (int i = 0; i < iters; ++i)
                {
                    foreach (var mf in FlightGlobals.ActiveVessel.FindPartModulesImplementing <MissileFire>())
                    {
                        ++count;
                    }
                }
                Debug.Log($"DEBUG {FlightGlobals.ActiveVessel} has {count / iters} weapon managers, checked at {iters / (Time.realtimeSinceStartup - startTime)}/s via vessel.FindPartModulesImplementing<MissileFire>()");
            }
            yield return(wait);

            {
                int count     = 0;
                int iters     = 100000;
                var startTime = Time.realtimeSinceStartup;
                for (int i = 0; i < iters; ++i)
                {
                    if (FlightGlobals.ActiveVessel.FindPartModuleImplementing <MissileFire>() != null)
                    {
                        ++count;
                    }
                }
                Debug.Log($"DEBUG {FlightGlobals.ActiveVessel} has {count / iters} weapon managers, checked at {iters / (Time.realtimeSinceStartup - startTime)}/s via vessel.FindPartModuleImplementing<MissileFire>()");
            }
            yield return(wait);

            {
                int count     = 0;
                int iters     = 10000000;
                var startTime = Time.realtimeSinceStartup;
                for (int i = 0; i < iters; ++i)
                {
                    foreach (var mf in VesselModuleRegistry.GetModules <MissileFire>(FlightGlobals.ActiveVessel))
                    {
                        ++count;
                    }
                }
                Debug.Log($"DEBUG {FlightGlobals.ActiveVessel} has {count / iters} weapon managers, checked at {iters / (Time.realtimeSinceStartup - startTime)}/s via VesselModuleRegistry.GetModules<MissileFire>(vessel)");
            }
            yield return(wait);

            {
                int count     = 0;
                int iters     = 10000000;
                var startTime = Time.realtimeSinceStartup;
                for (int i = 0; i < iters; ++i)
                {
                    foreach (var mf in VesselModuleRegistry.GetMissileFires(FlightGlobals.ActiveVessel))
                    {
                        ++count;
                    }
                }
                Debug.Log($"DEBUG {FlightGlobals.ActiveVessel} has {count / iters} weapon managers, checked at {iters / (Time.realtimeSinceStartup - startTime)}/s via VesselModuleRegistry.GetMissileFires(vessel)");
            }
            yield return(wait);

            {
                int count     = 0;
                int iters     = 10000000;
                var startTime = Time.realtimeSinceStartup;
                for (int i = 0; i < iters; ++i)
                {
                    if (VesselModuleRegistry.GetModule <MissileFire>(FlightGlobals.ActiveVessel) != null)
                    {
                        ++count;
                    }
                }
                Debug.Log($"DEBUG {FlightGlobals.ActiveVessel} has {count / iters} weapon managers, checked at {iters / (Time.realtimeSinceStartup - startTime)}/s via VesselModuleRegistry.GetModule<MissileFire>(vessel)");
            }
            yield return(wait);

            {
                int count     = 0;
                int iters     = 10000000;
                var startTime = Time.realtimeSinceStartup;
                for (int i = 0; i < iters; ++i)
                {
                    if (VesselModuleRegistry.GetModule <MissileFire>(FlightGlobals.ActiveVessel, true) != null)
                    {
                        ++count;
                    }
                }
                Debug.Log($"DEBUG {FlightGlobals.ActiveVessel} has {count / iters} weapon managers, checked at {iters / (Time.realtimeSinceStartup - startTime)}/s via VesselModuleRegistry.GetModule<MissileFire>(vessel, true)");
            }
            yield return(wait);

            {
                int count     = 0;
                int iters     = 10000000;
                var startTime = Time.realtimeSinceStartup;
                for (int i = 0; i < iters; ++i)
                {
                    if (VesselModuleRegistry.GetMissileFire(FlightGlobals.ActiveVessel) != null)
                    {
                        ++count;
                    }
                }
                Debug.Log($"DEBUG {FlightGlobals.ActiveVessel} has {count / iters} weapon managers, checked at {iters / (Time.realtimeSinceStartup - startTime)}/s via VesselModuleRegistry.GetMissileFire(vessel)");
            }
            yield return(wait);

            {
                int count     = 0;
                int iters     = 10000000;
                var startTime = Time.realtimeSinceStartup;
                for (int i = 0; i < iters; ++i)
                {
                    if (VesselModuleRegistry.GetMissileFire(FlightGlobals.ActiveVessel, true) != null)
                    {
                        ++count;
                    }
                }
                Debug.Log($"DEBUG {FlightGlobals.ActiveVessel} has {count / iters} weapon managers, checked at {iters / (Time.realtimeSinceStartup - startTime)}/s via VesselModuleRegistry.GetMissileFire(vessel, true)");
            }
            BDACompetitionMode.Instance.competitionStatus.Add("VesselModuleRegistry performance test complete.");
        }
        private bool Checkproximity(float distanceFromStart)
        {
            bool detonate = false;

            if (distanceFromStart < blastRadius)
            {
                return(detonate = false);
            }

            using (var hitsEnu = Physics.OverlapSphere(transform.position, detonationRange, 557057).AsEnumerable().GetEnumerator())
            {
                while (hitsEnu.MoveNext())
                {
                    if (hitsEnu.Current == null)
                    {
                        continue;
                    }

                    Part partHit = hitsEnu.Current.GetComponentInParent <Part>();
                    if (partHit == null || partHit.vessel == null)
                    {
                        continue;
                    }
                    if (ProjectileUtils.IsIgnoredPart(partHit))
                    {
                        continue;                                         // Ignore ignored parts.
                    }
                    if (partHit.vessel == vessel || partHit.vessel == sourcevessel)
                    {
                        continue;
                    }
                    if (partHit.vessel.vesselType == VesselType.Debris)
                    {
                        continue;
                    }
                    if (sourcevessel != null && partHit.vessel.vesselName.Contains(sourcevessel.vesselName))
                    {
                        continue;
                    }
                    var weaponManager = VesselModuleRegistry.GetModule <MissileFire>(partHit.vessel);
                    if (IFF_On && (weaponManager == null || weaponManager.teamString == IFFID))
                    {
                        continue;
                    }
                    if (detonateAtMinimumDistance)
                    {
                        var distance          = Vector3.Distance(partHit.transform.position + partHit.CoMOffset, transform.position);
                        var predictedDistance = Vector3.Distance(AIUtils.PredictPosition(partHit.transform.position + partHit.CoMOffset, partHit.vessel.Velocity(), partHit.vessel.acceleration, Time.fixedDeltaTime), AIUtils.PredictPosition(transform.position, vessel.Velocity(), vessel.acceleration, Time.fixedDeltaTime));
                        if (distance > predictedDistance && distance > Time.fixedDeltaTime * (float)vessel.srfSpeed) // If we're closing and not going to hit within the next update, then wait.
                        {
                            return(detonate = false);
                        }
                    }
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BDArmory.BDExplosivePart]: Proxifuze triggered by " + partHit.partName + " from " + partHit.vessel.vesselName);
                    }
                    return(detonate = true);
                }
            }
            return(detonate);
        }
Beispiel #20
0
        void PilotLogic()
        {
            // check for collisions, but not every frame
            if (collisionDetectionTicker == 0)
            {
                collisionDetectionTicker = 20;
                float predictMult = Mathf.Clamp(10 / MaxDrift, 1, 10);

                dodgeVector = null;

                using (var vs = BDATargetManager.LoadedVessels.GetEnumerator())
                    while (vs.MoveNext())
                    {
                        if (vs.Current == null || vs.Current == vessel || vs.Current.GetTotalMass() < AvoidMass)
                        {
                            continue;
                        }
                        if (!VesselModuleRegistry.ignoredVesselTypes.Contains(vs.Current.vesselType))
                        {
                            var ibdaiControl = VesselModuleRegistry.GetModule <IBDAIControl>(vs.Current);
                            if (!vs.Current.LandedOrSplashed || (ibdaiControl != null && ibdaiControl.commandLeader != null && ibdaiControl.commandLeader.vessel == vessel))
                            {
                                continue;
                            }
                        }
                        dodgeVector = PredictCollisionWithVessel(vs.Current, 5f * predictMult, 0.5f);
                        if (dodgeVector != null)
                        {
                            break;
                        }
                    }
            }
            else
            {
                collisionDetectionTicker--;
            }

            // avoid collisions if any are found
            if (dodgeVector != null)
            {
                targetVelocity  = PoweredSteering ? MaxSpeed : CruiseSpeed;
                targetDirection = (Vector3)dodgeVector;
                SetStatus($"Avoiding Collision");
                leftPath = true;
                return;
            }

            // if bypass target is no longer relevant, remove it
            if (bypassTarget != null && ((bypassTarget != targetVessel && bypassTarget != (commandLeader != null ? commandLeader.vessel : null)) ||
                                         (VectorUtils.GetWorldSurfacePostion(bypassTargetPos, vessel.mainBody) - bypassTarget.CoM).sqrMagnitude > 500000))
            {
                bypassTarget = null;
            }

            if (bypassTarget == null)
            {
                // check for enemy targets and engage
                // not checking for guard mode, because if guard mode is off now you can select a target manually and if it is of opposing team, the AI will try to engage while you can man the turrets
                if (weaponManager && targetVessel != null && !BDArmorySettings.PEACE_MODE)
                {
                    leftPath = true;
                    if (collisionDetectionTicker == 5)
                    {
                        checkBypass(targetVessel);
                    }

                    Vector3 vecToTarget = targetVessel.CoM - vessel.CoM;
                    float   distance    = vecToTarget.magnitude;
                    // lead the target a bit, where 1km/s is a ballpark estimate of the average bullet velocity
                    float shotSpeed = 1000f;
                    if ((weaponManager != null ? weaponManager.selectedWeapon : null) is ModuleWeapon wep)
                    {
                        shotSpeed = wep.bulletVelocity;
                    }
                    vecToTarget = targetVessel.PredictPosition(distance / shotSpeed) - vessel.CoM;

                    if (BroadsideAttack)
                    {
                        Vector3 sideVector = Vector3.Cross(vecToTarget, upDir); //find a vector perpendicular to direction to target
                        if (collisionDetectionTicker == 10 &&
                            !pathingMatrix.TraversableStraightLine(
                                VectorUtils.WorldPositionToGeoCoords(vessel.CoM, vessel.mainBody),
                                VectorUtils.WorldPositionToGeoCoords(vessel.PredictPosition(10), vessel.mainBody),
                                vessel.mainBody, SurfaceType, MaxSlopeAngle, AvoidMass))
                        {
                            sideSlipDirection = -Math.Sign(Vector3.Dot(vesselTransform.up, sideVector)); // switch sides if we're running ashore
                        }
                        sideVector *= sideSlipDirection;

                        float sidestep = distance >= MaxEngagementRange?Mathf.Clamp01((MaxEngagementRange - distance) / (CruiseSpeed *Mathf.Clamp(90 / MaxDrift, 0, 10)) + 1) * AttackAngleAtMaxRange / 90 : // direct to target to attackAngle degrees if over maxrange
                                         (distance <= MinEngagementRange ? 1.5f - distance / (MinEngagementRange * 2) :                                                                                      // 90 to 135 degrees if closer than minrange
                                          (MaxEngagementRange - distance) / (MaxEngagementRange - MinEngagementRange) * (1 - AttackAngleAtMaxRange / 90) + AttackAngleAtMaxRange / 90);                      // attackAngle to 90 degrees from maxrange to minrange

                        targetDirection = Vector3.LerpUnclamped(vecToTarget.normalized, sideVector.normalized, sidestep);                                                                                    // interpolate between the side vector and target direction vector based on sidestep
                        targetVelocity  = MaxSpeed;
                        DebugLine($"Broadside attack angle {sidestep}");
                    }
                    else // just point at target and go
                    {
                        if ((targetVessel.horizontalSrfSpeed < 10 || Vector3.Dot(Vector3.ProjectOnPlane(targetVessel.srf_vel_direction, upDir), vessel.up) < 0) && //if target is stationary or we're facing in opposite directions
                            (distance < MinEngagementRange || (distance < (MinEngagementRange * 3 + MaxEngagementRange) / 4 && //and too close together
                                                               extendingTarget != null && targetVessel != null && extendingTarget == targetVessel)))
                        {
                            extendingTarget = targetVessel;
                            // not sure if this part is very smart, potential for improvement
                            targetDirection = -vecToTarget; //extend
                            targetVelocity  = MaxSpeed;
                            SetStatus($"Extending");
                            return;
                        }
                        else
                        {
                            extendingTarget = null;
                            targetDirection = Vector3.ProjectOnPlane(vecToTarget, upDir);
                            if (Vector3.Dot(targetDirection, vesselTransform.up) < 0)
                            {
                                targetVelocity = PoweredSteering ? MaxSpeed : 0; // if facing away from target
                            }
                            else if (distance >= MaxEngagementRange || distance <= MinEngagementRange)
                            {
                                targetVelocity = MaxSpeed;
                            }
                            else
                            {
                                targetVelocity = CruiseSpeed / 10 + (MaxSpeed - CruiseSpeed / 10) * (distance - MinEngagementRange) / (MaxEngagementRange - MinEngagementRange); //slow down if inside engagement range to extend shooting opportunities
                                if (weaponManager != null && weaponManager.selectedWeapon != null)
                                {
                                    switch (weaponManager.selectedWeapon.GetWeaponClass())
                                    {
                                    case WeaponClasses.Gun:
                                    case WeaponClasses.Rocket:
                                    case WeaponClasses.DefenseLaser:
                                        var gun = (ModuleWeapon)weaponManager.selectedWeapon;
                                        if ((gun.yawRange == 0 || gun.maxPitch == gun.minPitch) && gun.FiringSolutionVector != null)
                                        {
                                            aimingMode = true;
                                            if (Vector3.Angle((Vector3)gun.FiringSolutionVector, vessel.transform.up) < 20)
                                            {
                                                targetDirection = (Vector3)gun.FiringSolutionVector;
                                            }
                                        }
                                        break;
                                    }
                                }
                            }
                            targetVelocity = Mathf.Clamp(targetVelocity, PoweredSteering ? CruiseSpeed / 5 : 0, MaxSpeed); // maintain a bit of speed if using powered steering
                        }
                    }
                    SetStatus($"Engaging target");
                    return;
                }

                // follow
                if (command == PilotCommands.Follow)
                {
                    leftPath = true;
                    if (collisionDetectionTicker == 5)
                    {
                        checkBypass(commandLeader.vessel);
                    }

                    Vector3 targetPosition = GetFormationPosition();
                    Vector3 targetDistance = targetPosition - vesselTransform.position;
                    if (Vector3.Dot(targetDistance, vesselTransform.up) < 0 &&
                        Vector3.ProjectOnPlane(targetDistance, upDir).sqrMagnitude < 250f * 250f &&
                        Vector3.Angle(vesselTransform.up, commandLeader.vessel.srf_velocity) < 0.8f)
                    {
                        targetDirection = Vector3.RotateTowards(Vector3.ProjectOnPlane(commandLeader.vessel.srf_vel_direction, upDir), targetDistance, 0.2f, 0);
                    }
                    else
                    {
                        targetDirection = Vector3.ProjectOnPlane(targetDistance, upDir);
                    }
                    targetVelocity = (float)(commandLeader.vessel.horizontalSrfSpeed + (vesselTransform.position - targetPosition).magnitude / 15);
                    if (Vector3.Dot(targetDirection, vesselTransform.up) < 0 && !PoweredSteering)
                    {
                        targetVelocity = 0;
                    }
                    SetStatus($"Following");
                    return;
                }
            }

            // goto
            if (leftPath && bypassTarget == null)
            {
                Pathfind(finalPositionGeo);
                leftPath = false;
            }

            const float targetRadius = 250f;

            targetDirection = Vector3.ProjectOnPlane(assignedPositionWorld - vesselTransform.position, upDir);

            if (targetDirection.sqrMagnitude > targetRadius * targetRadius)
            {
                if (bypassTarget != null)
                {
                    targetVelocity = MaxSpeed;
                }
                else if (waypoints.Count > 1)
                {
                    targetVelocity = command == PilotCommands.Attack ? MaxSpeed : CruiseSpeed;
                }
                else
                {
                    targetVelocity = Mathf.Clamp((targetDirection.magnitude - targetRadius / 2) / 5f,
                                                 0, command == PilotCommands.Attack ? MaxSpeed : CruiseSpeed);
                }

                if (Vector3.Dot(targetDirection, vesselTransform.up) < 0 && !PoweredSteering)
                {
                    targetVelocity = 0;
                }
                SetStatus(bypassTarget ? "Repositioning" : "Moving");
                return;
            }

            cycleWaypoint();

            SetStatus($"Not doing anything in particular");
            targetDirection = vesselTransform.up;
        }
Beispiel #21
0
        void Awake()
        {
            if (Instance != null)
            {
                Destroy(Instance);
            }
            Instance = this;

            if (registry == null)
            {
                registry = new Dictionary <Vessel, Dictionary <Type, List <UnityEngine.Object> > >();
            }
            if (registryMissileFire == null)
            {
                registryMissileFire = new Dictionary <Vessel, List <MissileFire> >();
            }
            if (registryMissileBase == null)
            {
                registryMissileBase = new Dictionary <Vessel, List <MissileBase> >();
            }
            if (registryModuleWeapon == null)
            {
                registryModuleWeapon = new Dictionary <Vessel, List <ModuleWeapon> >();
            }
            if (registryIBDWeapon == null)
            {
                registryIBDWeapon = new Dictionary <Vessel, List <IBDWeapon> >();
            }
            if (registryModuleEngines == null)
            {
                registryModuleEngines = new Dictionary <Vessel, List <ModuleEngines> >();
            }
            if (registryBDModulePilotAI == null)
            {
                registryBDModulePilotAI = new Dictionary <Vessel, List <BDModulePilotAI> >();
            }
            if (registryIBDAIControl == null)
            {
                registryIBDAIControl = new Dictionary <Vessel, List <IBDAIControl> >();
            }
            if (registryModuleCommand == null)
            {
                registryModuleCommand = new Dictionary <Vessel, List <ModuleCommand> >();
            }
            if (registryKerbalSeat == null)
            {
                registryKerbalSeat = new Dictionary <Vessel, List <KerbalSeat> >();
            }
            if (registryKerbalEVA == null)
            {
                registryKerbalEVA = new Dictionary <Vessel, List <KerbalEVA> >();
            }

            if (updateModuleCallbacks == null)
            {
                updateModuleCallbacks = new Dictionary <Type, System.Reflection.MethodInfo>();
            }
            if (vesselPartCounts == null)
            {
                vesselPartCounts = new Dictionary <Vessel, int>();
            }
        }