Пример #1
0
 public void SetThermal(Vessel sourceVessel)
 {
     // OLD:
     //thermal = BDArmorySetup.FLARE_THERMAL*UnityEngine.Random.Range(0.45f, 1.25f);
     // NEW: generate flare within spectrum of emitting vessel's heat signature
     thermal = BDATargetManager.GetVesselHeatSignature(sourceVessel) * UnityEngine.Random.Range(0.65f, 1.75f);
 }
Пример #2
0
        public void SetThermal(Vessel sourceVessel)
        {
            // OLD:
            //thermal = BDArmorySetup.FLARE_THERMAL*UnityEngine.Random.Range(0.45f, 1.25f);
            // NEW (1.9.1 and before): generate flare within spectrum of emitting vessel's heat signature
            //thermal = BDATargetManager.GetVesselHeatSignature(sourceVessel) * UnityEngine.Random.Range(0.65f, 1.75f);

            // NEW NEW: Dynamic min/max based on engine heat, with larger multiplier for colder engines, and smaller for naturally hot engines
            // since range of values are too small for smaller heat values, and flares tend to decay to even colder values, rendering them useless

            /* Alternate flare gen code, adjusts curve towards high end up to 5000K heat engines. Polynomial versions available.
             *
             * thermal = BDATargetManager.GetVesselHeatSignature(sourceVessel);
             * //float thermalMinMult = Mathf.Clamp(-0.166f * (float)Math.Log(thermal) + 1.9376f, 0.5f, 0.82f);
             * //float thermalMaxMult = Mathf.Clamp(0.3534f * (float)Math.Log(thermal) - 1.0251f, 1.35f, 2.0f);
             *
             * thermal *= UnityEngine.Random.Range(thermalMinMult, thermalMaxMult);
             *
             * if (BDArmorySettings.DRAW_DEBUG_LABELS)
             *  Debug.Log("[BDArmory]: New flare generated from " + sourceVessel.GetDisplayName() + ":" + BDATargetManager.GetVesselHeatSignature(sourceVessel).ToString("0.0") + ", heat: " + thermal.ToString("0.0") + " mult: " + thermalMinMult + "-" + thermalMaxMult);
             */

            // NEW (1.10 and later): generate flare within spectrum of emitting vessel's heat signature, but narrow range for low heats

            thermal = BDATargetManager.GetVesselHeatSignature(sourceVessel);
            // float minMult = Mathf.Clamp(-0.265f * Mathf.Log(sourceHeat) + 2.3f, 0.65f, 0.8f);
            float thermalMinMult = Mathf.Clamp(((0.00093f * thermal * thermal - 1.4457f * thermal + 1141.95f) / 1000f), 0.65f, 0.8f); // Equivalent to above, but uses polynomial for speed

            thermal *= UnityEngine.Random.Range(thermalMinMult, 1.75f - thermalMinMult + 0.65f);

            if (BDArmorySettings.DRAW_DEBUG_LABELS)
            {
                Debug.Log("[BDArmory]: New flare generated from " + sourceVessel.GetDisplayName() + ":" + BDATargetManager.GetVesselHeatSignature(sourceVessel).ToString("0.0") + ", heat: " + thermal.ToString("0.0"));
            }
        }
Пример #3
0
        protected void  AddTargetInfoToVessel()
        {
            TargetInfo info = vessel.gameObject.AddComponent <TargetInfo>();

            info.team              = BDATargetManager.BoolToTeam(Team);
            info.isMissile         = true;
            info.MissileBaseModule = this;
        }
Пример #4
0
 void OnDestroy()
 {
     //remove delegate from peace enable event
     BDArmorySetup.OnPeaceEnabled    -= OnPeaceEnabled;
     vessel.OnJustAboutToBeDestroyed -= AboutToBeDestroyed;
     GameEvents.onVesselPartCountChanged.Remove(VesselModified);
     GameEvents.onVesselDestroy.Remove(CleanFriendliesEngaging);
     BDATargetManager.RemoveTarget(this);
 }
Пример #5
0
        IEnumerator GPSRoutine()
        {
            GetSatInfo();
            scanning    = true;
            targetCount = 0;

            ScreenMsg("Initializing Scan ......");
            yield return(new WaitForSeconds(1.5f));

            ScreenMsg("Initializing Scan ......");
            yield return(new WaitForSeconds(1.5f));

            ScreenMsg("Scanning in Progress ......");
            yield return(new WaitForSeconds(1.5f));

            ScreenMsg("Scanning in Progress ......");
            yield return(new WaitForSeconds(1.5f));

            ScreenMsg("Scanning in Progress ......");
            yield return(new WaitForSeconds(1.5f));

            foreach (Vessel v in FlightGlobals.Vessels)
            {
                if (v.LandedOrSplashed && !v.HoldPhysics)
                {
                    List <MissileFire> targets = new List <MissileFire>(200);
                    foreach (Part t in v.Parts)
                    {
                        targets.AddRange(t.FindModulesImplementing <MissileFire>());
                    }
                    foreach (MissileFire target in targets)
                    {
                        if (myTeam != target.team)
                        {
                            _altitude  = v.altitude;
                            _latitude  = v.latitude;
                            _longitude = v.longitude;

                            targetCount += 1;
                            ScreenMsg2("Retrieving GPS Coords for " + v.vesselName);
                            yield return(new WaitForSeconds(1.5f));

                            BDATargetManager.GPSTargets[BDATargetManager.BoolToTeam(myTeam)].Add(new GPSTargetInfo(getTargetCoords, v.vesselName));
                            ScreenMsg2(v.vesselName + " added to GPS Database");
                            yield return(new WaitForSeconds(1.5f));
                        }
                    }
                }
            }
            yield return(new WaitForSeconds(1.5f));

            ScreenMsg2("Scan Complete ... " + targetCount + " Targets added to GPS Database");
            scan     = false;
            scanning = false;
        }
Пример #6
0
 /// <summary>
 /// If guard mode is set but no target is selected, pick something
 /// </summary>
 protected virtual void GetGuardNonTarget()
 {
     if (weaponManager && weaponManager.guardMode && !targetVessel)
     {
         TargetInfo potentialTarget = BDATargetManager.GetLeastEngagedTarget(weaponManager);
         if (potentialTarget && potentialTarget.Vessel)
         {
             targetVessel = potentialTarget.Vessel;
         }
     }
 }
Пример #7
0
 void Update()
 {
     if (!vessel)
     {
         AboutToBeDestroyed();
     }
     else
     {
         if ((vessel.vesselType == VesselType.Debris) && (weaponManager == null))
         {
             BDATargetManager.RemoveTarget(this);
             Team = null;
         }
     }
 }
Пример #8
0
        protected void UpdateLaserTarget()
        {
            if (TargetAcquired)
            {
                if (lockedCamera && lockedCamera.groundStabilized && !lockedCamera.gimbalLimitReached && lockedCamera.surfaceDetected) //active laser target
                {
                    TargetPosition     = lockedCamera.groundTargetPosition;
                    TargetVelocity     = (TargetPosition - lastLaserPoint) / Time.fixedDeltaTime;
                    TargetAcceleration = Vector3.zero;
                    lastLaserPoint     = TargetPosition;

                    if (GuidanceMode == GuidanceModes.BeamRiding && TimeIndex > 0.25f && Vector3.Dot(GetForwardTransform(), part.transform.position - lockedCamera.transform.position) < 0)
                    {
                        TargetAcquired = false;
                        lockedCamera   = null;
                    }
                }
                else //lost active laser target, home on last known position
                {
                    if (CMSmoke.RaycastSmoke(new Ray(transform.position, lastLaserPoint - transform.position)))
                    {
                        //Debug.Log("Laser missileBase affected by smoke countermeasure");
                        float angle = VectorUtils.FullRangePerlinNoise(0.75f * Time.time, 10) * BDArmorySettings.SMOKE_DEFLECTION_FACTOR;
                        TargetPosition     = VectorUtils.RotatePointAround(lastLaserPoint, transform.position, VectorUtils.GetUpDirection(transform.position), angle);
                        TargetVelocity     = Vector3.zero;
                        TargetAcceleration = Vector3.zero;
                        lastLaserPoint     = TargetPosition;
                    }
                    else
                    {
                        TargetPosition = lastLaserPoint;
                    }
                }
            }
            else
            {
                ModuleTargetingCamera foundCam = null;
                bool parentOnly = (GuidanceMode == GuidanceModes.BeamRiding);
                foundCam = BDATargetManager.GetLaserTarget(this, parentOnly);
                if (foundCam != null && foundCam.cameraEnabled && foundCam.groundStabilized && BDATargetManager.CanSeePosition(foundCam.groundTargetPosition, vessel.transform.position, MissileReferenceTransform.position))
                {
                    Debug.Log("[BDArmory]: Laser guided missileBase actively found laser point. Enabling guidance.");
                    lockedCamera   = foundCam;
                    TargetAcquired = true;
                }
            }
        }
Пример #9
0
        public TargetSignatureData(Vessel v, float _signalStrength)
        {
            orbital = false;
            orbit   = null;

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

            geoPos       = VectorUtils.WorldPositionToGeoCoords(v.CoM, v.mainBody);
            acceleration = v.acceleration;
            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 = BDArmorySettings.BDATeams.None;

            if (targetInfo)
            {
                team = targetInfo.team;
                targetInfo.detectedTime = Time.time;
            }
            else
            {
                List <MissileFire> .Enumerator mf = v.FindPartModulesImplementing <MissileFire>().GetEnumerator();
                while (mf.MoveNext())
                {
                    team = BDATargetManager.BoolToTeam(mf.Current.team);
                    break;
                }
                mf.Dispose();
            }

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

            pingPosition  = Vector2.zero;
            lockedByRadar = null;
        }
Пример #10
0
        /// <summary>
        /// GPS
        /// </summary>
        ///
        private void SaveGPS()
        {
            List <MissileFire> wmParts = new List <MissileFire>(200);

            foreach (Part p in FlightGlobals.ActiveVessel.Parts)
            {
                wmParts.AddRange(p.FindModulesImplementing <MissileFire>());
            }
            foreach (MissileFire wmPart in wmParts)
            {
                var _latitude_  = double.Parse(_guiX);
                var _longitude_ = double.Parse(_guiY);
                var _altitude_  = double.Parse(_guiZ);
                _latitude  = _latitude_;
                _longitude = _longitude_;
                _altitude  = _altitude_;
                BDATargetManager.GPSTargets[BDATargetManager.BoolToTeam(wmPart.team)].Add(new GPSTargetInfo(getTargetCoords, "Saved GPS"));
                ScreenMsg("GPS Target Saved");
            }
        }
Пример #11
0
 void Update()
 {
     if (!vessel)
     {
         AboutToBeDestroyed();
     }
     else
     {
         if ((vessel.vesselType == VesselType.Debris) && (weaponManager == null))
         {
             BDATargetManager.RemoveTarget(this);
             Team = null;
         }
     }
     if (HighLogic.LoadedSceneIsFlight)
     {
         if (BDArmorySetup.windowSettingsEnabled)
         {
             UpdateTargetPartList();
         }
     }
 }
Пример #12
0
        protected void UpdateHeatTarget()
        {
            if (lockFailTimer > 1)
            {
                legacyTargetVessel = null;
                TargetAcquired     = false;
                return;
            }


            if (heatTarget.exists && lockFailTimer < 0)
            {
                lockFailTimer = 0;
            }
            if (lockFailTimer >= 0)
            {
                Ray lookRay = new Ray(transform.position, heatTarget.position + (heatTarget.velocity * Time.fixedDeltaTime) - transform.position);
                heatTarget = BDATargetManager.GetHeatTarget(SourceVessel, vessel, lookRay, lockedSensorFOV / 2, heatThreshold, allAspect, SourceVessel?.gameObject?.GetComponent <MissileFire>());

                if (heatTarget.exists)
                {
                    TargetAcquired     = true;
                    TargetPosition     = heatTarget.position + (2 * heatTarget.velocity * Time.fixedDeltaTime);
                    TargetVelocity     = heatTarget.velocity;
                    TargetAcceleration = heatTarget.acceleration;
                    lockFailTimer      = 0;
                }
                else
                {
                    TargetAcquired = false;
                    if (FlightGlobals.ready)
                    {
                        lockFailTimer += Time.fixedDeltaTime;
                    }
                }
            }
        }
Пример #13
0
 void AboutToBeDestroyed()
 {
     BDATargetManager.RemoveTarget(this);
     Destroy(this);
 }
Пример #14
0
        void OnEnable()
        {
            // OLD:
            //thermal = BDArmorySettings.FLARE_THERMAL*UnityEngine.Random.Range(0.45f, 1.25f);
            // NEW: generate flare within spectrum of emitting vessel's heat signature
            thermal      = BDATargetManager.GetVesselHeatSignature(sourceVessel) * UnityEngine.Random.Range(0.65f, 1.75f);
            startThermal = thermal;
            minThermal   = startThermal * 0.3f;

            if (gaplessEmitters == null || pEmitters == null)
            {
                gaplessEmitters = new List <BDAGaplessParticleEmitter>();

                pEmitters = new List <KSPParticleEmitter>();

                IEnumerator <KSPParticleEmitter> pe = gameObject.GetComponentsInChildren <KSPParticleEmitter>().Cast <KSPParticleEmitter>().GetEnumerator();
                while (pe.MoveNext())
                {
                    if (pe.Current == null)
                    {
                        continue;
                    }
                    if (pe.Current.useWorldSpace)
                    {
                        BDAGaplessParticleEmitter gpe = pe.Current.gameObject.AddComponent <BDAGaplessParticleEmitter>();
                        gaplessEmitters.Add(gpe);
                        gpe.emit = true;
                    }
                    else
                    {
                        EffectBehaviour.AddParticleEmitter(pe.Current);
                        pEmitters.Add(pe.Current);
                        pe.Current.emit = true;
                    }
                }
                pe.Dispose();
            }
            List <BDAGaplessParticleEmitter> .Enumerator gEmitter = gaplessEmitters.GetEnumerator();
            while (gEmitter.MoveNext())
            {
                if (gEmitter.Current == null)
                {
                    continue;
                }
                gEmitter.Current.emit = true;
            }
            gEmitter.Dispose();

            List <KSPParticleEmitter> .Enumerator pEmitter = pEmitters.GetEnumerator();
            while (pEmitter.MoveNext())
            {
                if (pEmitter.Current == null)
                {
                    continue;
                }
                pEmitter.Current.emit = true;
            }
            pEmitter.Dispose();

            BDArmorySettings.numberOfParticleEmitters++;


            if (lights == null)
            {
                lights = gameObject.GetComponentsInChildren <Light>();
            }

            IEnumerator <Light> lgt = lights.AsEnumerable().GetEnumerator();

            while (lgt.MoveNext())
            {
                if (lgt.Current == null)
                {
                    continue;
                }
                lgt.Current.enabled = true;
            }
            lgt.Dispose();
            startTime = Time.time;

            //ksp force applier
            //gameObject.AddComponent<KSPForceApplier>().drag = 0.4f;


            BDArmorySettings.Flares.Add(this);

            if (sourceVessel != null)
            {
                relativePos = transform.position - sourceVessel.transform.position;
            }

            upDirection = VectorUtils.GetUpDirection(transform.position);

            velocity = startVelocity;
        }
Пример #15
0
        IEnumerator DogfightCompetitionModeRoutine(float distance)
        {
            competitionStarting = true;
            competitionStatus   = "Competition: Pilots are taking off.";
            Dictionary <BDArmorySetup.BDATeams, List <IBDAIControl> > pilots =
                new Dictionary <BDArmorySetup.BDATeams, List <IBDAIControl> >();

            pilots.Add(BDArmorySetup.BDATeams.A, new List <IBDAIControl>());
            pilots.Add(BDArmorySetup.BDATeams.B, new List <IBDAIControl>());
            List <Vessel> .Enumerator loadedVessels = BDATargetManager.LoadedVessels.GetEnumerator();
            while (loadedVessels.MoveNext())
            {
                if (loadedVessels.Current == null)
                {
                    continue;
                }
                if (!loadedVessels.Current.loaded)
                {
                    continue;
                }
                IBDAIControl pilot = null;
                IEnumerator <IBDAIControl> ePilots = loadedVessels.Current.FindPartModulesImplementing <IBDAIControl>().AsEnumerable().GetEnumerator();
                while (ePilots.MoveNext())
                {
                    pilot = ePilots.Current;
                    break;
                }
                ePilots.Dispose();
                if (pilot == null || !pilot.weaponManager)
                {
                    continue;
                }

                pilots[BDATargetManager.BoolToTeam(pilot.weaponManager.team)].Add(pilot);
                pilot.CommandTakeOff();
                if (pilot.weaponManager.guardMode)
                {
                    pilot.weaponManager.ToggleGuardMode();
                }
            }
            loadedVessels.Dispose();

            //clear target database so pilots don't attack yet
            BDATargetManager.ClearDatabase();

            if (pilots[BDArmorySetup.BDATeams.A].Count == 0 || pilots[BDArmorySetup.BDATeams.B].Count == 0)
            {
                Debug.Log("[BDArmory]: Unable to start competition mode - one or more teams is empty");
                competitionStatus = "Competition: Failed!  One or more teams is empty.";
                yield return(new WaitForSeconds(2));

                competitionStarting = false;
                yield break;
            }

            IBDAIControl aLeader = pilots[BDArmorySetup.BDATeams.A][0];
            IBDAIControl bLeader = pilots[BDArmorySetup.BDATeams.B][0];

            aLeader.weaponManager.wingCommander.CommandAllFollow();
            bLeader.weaponManager.wingCommander.CommandAllFollow();


            //wait till the leaders are ready to engage (airborne for PilotAI)
            while (aLeader != null && bLeader != null && (!aLeader.CanEngage() || !bLeader.CanEngage()))
            {
                yield return(null);
            }

            if (aLeader == null || bLeader == null)
            {
                StopCompetition();
            }

            competitionStatus = "Competition: Sending pilots to start position.";
            Vector3 aDirection =
                Vector3.ProjectOnPlane(aLeader.vessel.CoM - bLeader.vessel.CoM, aLeader.vessel.upAxis).normalized;
            Vector3 bDirection =
                Vector3.ProjectOnPlane(bLeader.vessel.CoM - aLeader.vessel.CoM, bLeader.vessel.upAxis).normalized;

            Vector3 center       = (aLeader.vessel.CoM + bLeader.vessel.CoM) / 2f;
            Vector3 aDestination = center + (aDirection * (distance + 1250f));
            Vector3 bDestination = center + (bDirection * (distance + 1250f));

            aDestination = VectorUtils.WorldPositionToGeoCoords(aDestination, FlightGlobals.currentMainBody);
            bDestination = VectorUtils.WorldPositionToGeoCoords(bDestination, FlightGlobals.currentMainBody);

            aLeader.CommandFlyTo(aDestination);
            bLeader.CommandFlyTo(bDestination);

            Vector3 centerGPS = VectorUtils.WorldPositionToGeoCoords(center, FlightGlobals.currentMainBody);

            //wait till everyone is in position
            bool waiting = true;

            while (waiting)
            {
                waiting = false;

                if (aLeader == null || bLeader == null)
                {
                    StopCompetition();
                }

                if (Vector3.Distance(aLeader.transform.position, bLeader.transform.position) < distance * 1.95f)
                {
                    waiting = true;
                }
                else
                {
                    Dictionary <BDArmorySetup.BDATeams, List <IBDAIControl> > .KeyCollection.Enumerator keys = pilots.Keys.GetEnumerator();
                    while (keys.MoveNext())
                    {
                        List <IBDAIControl> .Enumerator ePilots = pilots[keys.Current].GetEnumerator();
                        while (ePilots.MoveNext())
                        {
                            if (ePilots.Current == null)
                            {
                                continue;
                            }
                            if (ePilots.Current.currentCommand != PilotCommands.Follow ||
                                !(Vector3.ProjectOnPlane(
                                      ePilots.Current.vessel.CoM - ePilots.Current.commandLeader.vessel.CoM,
                                      VectorUtils.GetUpDirection(ePilots.Current.commandLeader.vessel.transform.position)
                                      ).sqrMagnitude > 1000f * 1000f))
                            {
                                continue;
                            }
                            competitionStatus = "Competition: Waiting for teams to get in position.";
                            waiting           = true;
                        }
                        ePilots.Dispose();
                    }
                    keys.Dispose();
                }

                yield return(null);
            }

            //start the match
            Dictionary <BDArmorySetup.BDATeams, List <IBDAIControl> > .KeyCollection.Enumerator pKeys = pilots.Keys.GetEnumerator();
            while (pKeys.MoveNext())
            {
                List <IBDAIControl> .Enumerator pPilots = pilots[pKeys.Current].GetEnumerator();
                while (pPilots.MoveNext())
                {
                    if (pPilots.Current == null)
                    {
                        continue;
                    }

                    //enable guard mode
                    if (!pPilots.Current.weaponManager.guardMode)
                    {
                        pPilots.Current.weaponManager.ToggleGuardMode();
                    }

                    //report all vessels
                    if (BDATargetManager.BoolToTeam(pPilots.Current.weaponManager.team) == BDArmorySetup.BDATeams.B)
                    {
                        BDATargetManager.ReportVessel(pPilots.Current.vessel, aLeader.weaponManager);
                    }
                    else
                    {
                        BDATargetManager.ReportVessel(pPilots.Current.vessel, bLeader.weaponManager);
                    }

                    //release command
                    pPilots.Current.ReleaseCommand();
                    pPilots.Current.CommandAttack(centerGPS);
                }
            }
            pKeys.Dispose();
            competitionStatus = "Competition starting!  Good luck!";
            yield return(new WaitForSeconds(2));

            competitionStarting = false;
        }
Пример #16
0
 /// <summary>
 /// If guard mode is set but no target is selected, pick something
 /// </summary>
 protected virtual void GetGuardNonTarget()
 {
     if (weaponManager && weaponManager.guardMode && !targetVessel)
     {
         // select target based on competition style
         TargetInfo potentialTarget = BDArmorySettings.DEFAULT_FFA_TARGETING ? BDATargetManager.GetClosestTargetWithBiasAndHysteresis(weaponManager) : BDATargetManager.GetLeastEngagedTarget(weaponManager);
         if (potentialTarget && potentialTarget.Vessel)
         {
             targetVessel = potentialTarget.Vessel;
         }
     }
 }
Пример #17
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
            IEnumerator otherInfo = vessel.gameObject.GetComponents <TargetInfo>().GetEnumerator();

            while (otherInfo.MoveNext())
            {
                if ((object)otherInfo.Current != this)
                {
                    Destroy(this);
                    return;
                }
            }

            team = BDArmorySetup.BDATeams.None;
            bool foundMf = false;

            List <MissileFire> .Enumerator mf = vessel.FindPartModulesImplementing <MissileFire>().GetEnumerator();
            while (mf.MoveNext())
            {
                foundMf       = true;
                team          = BDATargetManager.BoolToTeam(mf.Current.team);
                weaponManager = mf.Current;
                break;
            }
            mf.Dispose();

            if (!foundMf)
            {
                List <MissileBase> .Enumerator ml = vessel.FindPartModulesImplementing <MissileBase>().GetEnumerator();
                while (ml.MoveNext())
                {
                    isMissile         = true;
                    MissileBaseModule = ml.Current;
                    team = BDATargetManager.BoolToTeam(ml.Current.Team);
                    break;
                }
                ml.Dispose();
            }

            if (team != BDArmorySetup.BDATeams.None)
            {
                BDATargetManager.AddTarget(this);
            }

            friendliesEngaging = new List <MissileFire>();

            vessel.OnJustAboutToBeDestroyed += AboutToBeDestroyed;

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

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

            if (!isMissile && team != BDArmorySetup.BDATeams.None)
            {
                GameEvents.onVesselPartCountChanged.Add(VesselModified);
                //massRoutine = StartCoroutine(MassRoutine());              // TODO: CHECK BEHAVIOUR AND SIDE EFFECTS!
            }
        }
Пример #18
0
        IEnumerator DogfightCompetitionModeRoutine(float distance)
        {
            competitionStarting = true;
            competitionStatus   = "Competition: Pilots are taking off.";
            var pilots = new Dictionary <BDTeam, List <IBDAIControl> >();

            using (var loadedVessels = BDATargetManager.LoadedVessels.GetEnumerator())
                while (loadedVessels.MoveNext())
                {
                    if (loadedVessels.Current == null || !loadedVessels.Current.loaded)
                    {
                        continue;
                    }
                    IBDAIControl pilot = loadedVessels.Current.FindPartModuleImplementing <IBDAIControl>();
                    if (pilot == null || !pilot.weaponManager || pilot.weaponManager.Team.Neutral)
                    {
                        continue;
                    }

                    if (!pilots.TryGetValue(pilot.weaponManager.Team, out List <IBDAIControl> teamPilots))
                    {
                        teamPilots = new List <IBDAIControl>();
                        pilots.Add(pilot.weaponManager.Team, teamPilots);
                    }
                    teamPilots.Add(pilot);
                    pilot.CommandTakeOff();
                    if (pilot.weaponManager.guardMode)
                    {
                        pilot.weaponManager.ToggleGuardMode();
                    }
                }

            //clear target database so pilots don't attack yet
            BDATargetManager.ClearDatabase();

            if (pilots.Count < 2)
            {
                Debug.Log("[BDArmory]: Unable to start competition mode - one or more teams is empty");
                competitionStatus = "Competition: Failed!  One or more teams is empty.";
                yield return(new WaitForSeconds(2));

                competitionStarting = false;
                yield break;
            }

            var leaders = new List <IBDAIControl>();

            using (var pilotList = pilots.GetEnumerator())
                while (pilotList.MoveNext())
                {
                    leaders.Add(pilotList.Current.Value[0]);
                    pilotList.Current.Value[0].weaponManager.wingCommander.CommandAllFollow();
                }

            //wait till the leaders are ready to engage (airborne for PilotAI)
            bool ready = false;

            while (!ready)
            {
                ready = true;
                using (var leader = leaders.GetEnumerator())
                    while (leader.MoveNext())
                    {
                        if (leader.Current != null && !leader.Current.CanEngage())
                        {
                            ready = false;
                            yield return(null);

                            break;
                        }
                    }
            }

            using (var leader = leaders.GetEnumerator())
                while (leader.MoveNext())
                {
                    if (leader.Current == null)
                    {
                        StopCompetition();
                    }
                }

            competitionStatus = "Competition: Sending pilots to start position.";
            Vector3 center = Vector3.zero;

            using (var leader = leaders.GetEnumerator())
                while (leader.MoveNext())
                {
                    center += leader.Current.vessel.CoM;
                }
            center /= leaders.Count;
            Vector3 startDirection = Vector3.ProjectOnPlane(leaders[0].vessel.CoM - center, VectorUtils.GetUpDirection(center)).normalized;

            startDirection *= (distance * leaders.Count / 4) + 1250f;
            Quaternion directionStep = Quaternion.AngleAxis(360f / leaders.Count, VectorUtils.GetUpDirection(center));

            for (var i = 0; i < leaders.Count; ++i)
            {
                leaders[i].CommandFlyTo(VectorUtils.WorldPositionToGeoCoords(startDirection, FlightGlobals.currentMainBody));
                startDirection = directionStep * startDirection;
            }

            Vector3 centerGPS = VectorUtils.WorldPositionToGeoCoords(center, FlightGlobals.currentMainBody);

            //wait till everyone is in position
            competitionStatus = "Competition: Waiting for teams to get in position.";
            bool waiting     = true;
            var  sqrDistance = distance * distance;

            while (waiting)
            {
                waiting = false;

                using (var leader = leaders.GetEnumerator())
                    while (leader.MoveNext())
                    {
                        if (leader.Current == null)
                        {
                            StopCompetition();
                        }

                        using (var otherLeader = leaders.GetEnumerator())
                            while (otherLeader.MoveNext())
                            {
                                if (leader.Current == otherLeader.Current)
                                {
                                    continue;
                                }
                                if ((leader.Current.transform.position - otherLeader.Current.transform.position).sqrMagnitude < sqrDistance)
                                {
                                    waiting = true;
                                }
                            }

                        // Increase the distance for large teams
                        var sqrTeamDistance = (800 + 100 * pilots[leader.Current.weaponManager.Team].Count) * (800 + 100 * pilots[leader.Current.weaponManager.Team].Count);
                        using (var pilot = pilots[leader.Current.weaponManager.Team].GetEnumerator())
                            while (pilot.MoveNext())
                            {
                                if (pilot.Current != null &&
                                    pilot.Current.currentCommand == PilotCommands.Follow &&
                                    (pilot.Current.vessel.CoM - pilot.Current.commandLeader.vessel.CoM).sqrMagnitude > 1000f * 1000f)
                                {
                                    waiting = true;
                                }
                            }

                        if (waiting)
                        {
                            break;
                        }
                    }

                yield return(null);
            }

            //start the match
            using (var teamPilots = pilots.GetEnumerator())
                while (teamPilots.MoveNext())
                {
                    using (var pilot = teamPilots.Current.Value.GetEnumerator())
                        while (pilot.MoveNext())
                        {
                            if (pilot.Current == null)
                            {
                                continue;
                            }

                            if (!pilot.Current.weaponManager.guardMode)
                            {
                                pilot.Current.weaponManager.ToggleGuardMode();
                            }

                            using (var leader = leaders.GetEnumerator())
                                while (leader.MoveNext())
                                {
                                    BDATargetManager.ReportVessel(pilot.Current.vessel, leader.Current.weaponManager);
                                }

                            pilot.Current.ReleaseCommand();
                            pilot.Current.CommandAttack(centerGPS);
                        }
                }

            competitionStatus = "Competition starting!  Good luck!";
            yield return(new WaitForSeconds(2));

            competitionStarting = false;
        }