Пример #1
0
		/// <summary>
		/// Gets the dynamic launch parameters.
		/// </summary>
		/// <returns>The dynamic launch parameters.</returns>
		/// <param name="launcherVelocity">Launcher velocity.</param>
		/// <param name="targetVelocity">Target velocity.</param>
		public static MissileLaunchParams GetDynamicLaunchParams(MissileLauncher missile, Vector3 targetVelocity, Vector3 targetPosition)
		{
			Vector3 launcherVelocity = missile.vessel.srf_velocity;
			float launcherSpeed = (float)missile.vessel.srfSpeed;
			float minLaunchRange = missile.minStaticLaunchRange;
			float maxLaunchRange = missile.maxStaticLaunchRange;

			float rangeAddMin = 0;
			float rangeAddMax = 0;
			float relSpeed;

			Vector3 relV = targetVelocity - launcherVelocity;
			Vector3 vectorToTarget = targetPosition - missile.part.transform.position;
			Vector3 relVProjected = Vector3.Project(relV, vectorToTarget);
			relSpeed = -Mathf.Sign(Vector3.Dot(relVProjected, vectorToTarget)) * relVProjected.magnitude;
			

			rangeAddMin += relSpeed * 2;
			rangeAddMax += relSpeed * 8;
			rangeAddMin += launcherSpeed * 2;
			rangeAddMax += launcherSpeed * 2;

			double diffAlt = missile.vessel.altitude - FlightGlobals.getAltitudeAtPos(targetPosition);

			rangeAddMax += (float)diffAlt;

			float min = Mathf.Clamp(minLaunchRange + rangeAddMin, 0, 20000);
			float max = Mathf.Clamp(maxLaunchRange + rangeAddMax, min+100, 20000);

			return new MissileLaunchParams(min, max);
		}
Пример #2
0
        public static Vector3 DoAeroForces(MissileLauncher ml, Vector3 targetPosition, float liftArea, float steerMult, Vector3 previousTorque, float maxTorque, float maxAoA)
        {
            if(DefaultLiftCurve == null)
            {
                DefaultLiftCurve = new FloatCurve();
                DefaultLiftCurve.Add(0, .1f);
                DefaultLiftCurve.Add(8, .45f);
                DefaultLiftCurve.Add(19, 1);
                DefaultLiftCurve.Add(23, .9f);
                DefaultLiftCurve.Add(29, 0.85f);
                DefaultLiftCurve.Add(35, 0.65f);
                DefaultLiftCurve.Add(65, .6f);
                DefaultLiftCurve.Add(90, .7f);
            }

            if(DefaultDragCurve == null)
            {
                DefaultDragCurve = new FloatCurve();
                DefaultDragCurve.Add(0, 0.00225f);
                DefaultDragCurve.Add(5, .0035f);
                DefaultDragCurve.Add(15, .015f);
                DefaultDragCurve.Add(29, .025f);
                DefaultDragCurve.Add(55, .3f);
                DefaultDragCurve.Add(90, .5f);
            }

            FloatCurve liftCurve = DefaultLiftCurve;
            FloatCurve dragCurve = DefaultDragCurve;

            return DoAeroForces(ml, targetPosition, liftArea, steerMult, previousTorque, maxTorque, maxAoA, liftCurve, dragCurve);
        }
Пример #3
0
        public override void OnStart(PartModule.StartState state)
        {
            submunitions = new List<GameObject>();
            foreach(var sub in part.FindModelTransforms("submunition"))
            {
                submunitions.Add(sub.gameObject);
                if(HighLogic.LoadedSceneIsFlight)
                {
                    Rigidbody subRb = sub.gameObject.GetComponent<Rigidbody>();
                    if(!subRb)
                    {
                        subRb = sub.gameObject.AddComponent<Rigidbody>();
                    }
                    subRb.isKinematic = true;
                    subRb.mass = part.mass / part.FindModelTransforms("submunition").Length;
                }
                sub.gameObject.SetActive(false);
            }

            fairings = new List<GameObject>();
            foreach(var fairing in part.FindModelTransforms("fairing"))
            {
                fairings.Add(fairing.gameObject);
                if(HighLogic.LoadedSceneIsFlight)
                {
                    Rigidbody fairingRb = fairing.gameObject.GetComponent<Rigidbody>();
                    if(!fairingRb)
                    {
                        fairingRb = fairing.gameObject.AddComponent<Rigidbody>();
                    }
                    fairingRb.isKinematic = true;
                    fairingRb.mass = 0.05f;
                }
            }

            missileLauncher = part.GetComponent<MissileLauncher>();
            //missileLauncher.deployTime = deployDelay;
        }
Пример #4
0
		void FireCurrentMissile(bool checkClearance)
		{
			MissileLauncher ml = currentMissile;
			if(ml == null) return;

			if(checkClearance && (!CheckBombClearance(ml) || (ml.rotaryRail&&!ml.rotaryRail.readyMissile==ml)))
			{
				foreach(var otherMissile in vessel.FindPartModulesImplementing<MissileLauncher>())
				{
					if(otherMissile != ml && otherMissile.GetShortName() == ml.GetShortName() && CheckBombClearance(otherMissile))
					{
						currentMissile = otherMissile;
						selectedWeapon = otherMissile;
						FireCurrentMissile(false);
						return;
					}
				}
				currentMissile = ml;
				selectedWeapon = ml;
				return;
			}

			//Part partSym = FindSym(ml.part);
			if(ml.missileTurret)
			{
				ml.missileTurret.FireMissile(ml);
			}
			else if(ml.rotaryRail)
			{
				ml.rotaryRail.FireMissile(ml);
			}
			else
			{
				SendTargetDataToMissile(ml);
				ml.FireMissile();
			}

			if(guardMode)
			{
				if(ml.GetWeaponClass() == WeaponClasses.Bomb)
				{
					StartCoroutine(BombsAwayRoutine(ml));
				}
			}
			else
			{
				if(vesselRadarData && vesselRadarData.autoCycleLockOnFire)
				{
					vesselRadarData.CycleActiveLock();
				}
			}

			UpdateList();
		}
Пример #5
0
		private int IndexOfMissile(MissileLauncher ml)
		{
			if(missileCount == 0) return -1;

			for(int i = 0; i < missileCount; i++)
			{
				if(missileChildren[i] && missileChildren[i] == ml)
				{
					return i;
				}
			}

			return -1;
		}
Пример #6
0
		public void FireMissile(int missileIndex)
		{
			int nextRailIndex = 0;

			if(!readyToFire)
			{
				return;
			}

			if(missileIndex >= missileChildren.Length)
			{
				return;
			}

			if(missileIndex < missileCount && missileChildren != null && missileChildren[missileIndex] != null)
			{
				if(missileChildren[missileIndex] != readyMissile) return;

				PrepMissileForFire(missileIndex);

				if(weaponManager)
				{
					wm.SendTargetDataToMissile(missileChildren[missileIndex]);
				}

				string firedMissileName = missileChildren[missileIndex].part.name;

				missileChildren[missileIndex].FireMissile();

				rdyMissile = null;
				rdyToFire = false;
				//StartCoroutine(MissileRailRoutine(missileChildren[missileIndex]));

				nextRailIndex = Mathf.RoundToInt(Mathf.Repeat(missileToRailIndex[missileIndex] + 1, numberOfRails));

				UpdateMissileChildren();

				if(wm)
				{
					wm.UpdateList();
				}

				if(railToMissileIndex.ContainsKey(nextRailIndex) && railToMissileIndex[nextRailIndex] < missileCount && missileChildren[railToMissileIndex[nextRailIndex]].part.name == firedMissileName)
				{
					RotateToIndex(nextRailIndex, false);
				}
			}



			//StartCoroutine(RotateToIndexAtEndOfFrame(nextRailIndex, false));
		}
Пример #7
0
		IEnumerator RotateToIndexRoutine(int index, bool instant)
		{
			rdyToFire = false;
			rdyMissile = null;
			railIndex = index;

			/*
			MissileLauncher foundMissile = null;

			foreach(var mIndex in missileToRailIndex.Keys)
			{
				if(missileToRailIndex[mIndex] == index)
				{
					foundMissile = missileChildren[mIndex];
				}
			}
			nextMissile = foundMissile;
			*/



			yield return new WaitForSeconds(rotationDelay);

			Quaternion targetRot = Quaternion.Euler(0, 0, (float)index * -railAngle);

			if(instant)
			{
				for(int i = 0; i < rotationTransforms.Count; i++)
				{
					rotationTransforms[i].localRotation = targetRot;
				}

				UpdateMissilePositions();
				//yield break;
			}
			else
			{
				while(rotationTransforms[0].localRotation != targetRot)
				{
					for(int i = 0; i < rotationTransforms.Count; i++)
					{
						rotationTransforms[i].localRotation = Quaternion.RotateTowards(rotationTransforms[i].localRotation, targetRot, rotationSpeed * Time.fixedDeltaTime);
					}

					UpdateMissilePositions();
					yield return new WaitForFixedUpdate();
				}
			}
				
			if(nextMissile)
			{
				rdyMissile = nextMissile;
				rdyToFire = true;
				nextMissile = null;

				if(weaponManager)
				{
					if(wm.weaponIndex > 0 && wm.selectedWeapon.GetPart().name == rdyMissile.part.name)
					{
						wm.selectedWeapon = rdyMissile;
						wm.currentMissile = rdyMissile;
					}
				}
			}
		}
Пример #8
0
		public void RotateToMissile(MissileLauncher ml)
		{
			if(missileCount == 0) return;
			if(!ml) return;

			if(readyMissile == ml) return;

			//rotate to this missile specifically
			for(int i = 0; i < missileChildren.Length; i++)
			{
				if(missileChildren[i] == ml)
				{
					RotateToIndex(missileToRailIndex[i], false);
					nextMissile = ml;
					return;
				}
			}
				
			//specific missile isnt here, but check if this type exists here

			if(readyMissile && readyMissile.part.name == ml.part.name) return; //current missile is correct type

			//look for missile type
			for(int i = 0; i < missileChildren.Length; i++)
			{
				if(missileChildren[i].GetShortName() == ml.GetShortName())
				{
					RotateToIndex(missileToRailIndex[i], false);
					nextMissile = missileChildren[i];
					return;
				}
			}
		}
Пример #9
0
        public static Vector3 GetAirToAirFireSolution(MissileLauncher missile, Vessel targetVessel)
        {
            if(!targetVessel)
            {
                return missile.transform.position + (missile.transform.forward*1000);
            }
            Vector3 targetPosition = targetVessel.transform.position;
            float leadTime = 0;
            float targetDistance = Vector3.Distance(targetVessel.transform.position, missile.transform.position);

            Vector3 simMissileVel = missile.optimumAirspeed * (targetPosition-missile.transform.position).normalized;
            leadTime = targetDistance/(float)(targetVessel.srf_velocity-simMissileVel).magnitude;
            leadTime = Mathf.Clamp (leadTime, 0f, 8f);
            targetPosition = targetPosition + (targetVessel.srf_velocity*leadTime);

            if(targetVessel && targetDistance < 800)
            {
                targetPosition += (Vector3)targetVessel.acceleration * 0.05f * leadTime * leadTime;
            }

            return targetPosition;
        }
Пример #10
0
 public void FireMissile(MissileLauncher ml)
 {
     int index = IndexOfMissile(ml);
     if(index >= 0)
     {
         Debug.Log("Firing missile index: " + index);
         FireMissile(index);
     }
     else
     {
         Debug.Log("Tried to fire a missile that doesn't exist or is not attached to the turret.");
     }
 }
Пример #11
0
        void SendTargetDataToMissile(MissileLauncher ml)
        {
            if(ml.targetingMode == MissileLauncher.TargetingModes.Laser && laserPointDetected)
            {
                ml.lockedCamera = foundCam;
            }
            else if(ml.targetingMode == MissileLauncher.TargetingModes.GPS)
            {
                ml.targetGPSCoords = designatedGPSCoords;
                ml.targetAcquired = true;
            }
            else if(ml.targetingMode == MissileLauncher.TargetingModes.Heat && heatTarget.exists)
            {
                ml.heatTarget = heatTarget;
            }
            else if(ml.targetingMode == MissileLauncher.TargetingModes.Radar && radar && radar.lockedTarget.exists)
            {
                ml.radarTarget = radar.lockedTarget;
                if(radar.linked && radar.linkedRadar.locked)
                {
                    ml.radar = radar.linkedRadar;
                }
                else
                {
                    ml.radar = radar;
                }
                radar.lastMissile = ml;

            }
            else if(ml.targetingMode == MissileLauncher.TargetingModes.AntiRad && antiRadTargetAcquired)
            {
                ml.targetAcquired = true;
                ml.targetGPSCoords = VectorUtils.WorldPositionToGeoCoords(antiRadiationTarget, vessel.mainBody);
            }
        }
Пример #12
0
        IEnumerator GuardMissileRoutine(MissileLauncher ml)
        {
            if(ml && !guardFiringMissile)
            {
                guardFiringMissile = true;

                if(BDArmorySettings.ALLOW_LEGACY_TARGETING)
                {
                    Debug.Log("Firing on target: " + guardTarget.GetName()+", (legacy targeting)");
                    ml.FireMissileOnTarget(guardTarget);
                    UpdateList();
                }
                else if(ml.targetingMode == MissileLauncher.TargetingModes.Radar && radar)
                {
                    if(!radar.locked || (radar.lockedTarget.predictedPosition - guardTarget.transform.position).sqrMagnitude > Mathf.Pow(40, 2))
                    {
                        radar.TryLockTarget(guardTarget.transform.position);
                        yield return new WaitForSeconds(Mathf.Clamp(2, 0.2f, targetScanInterval / 2));
                    }

                    if(guardTarget && radar.locked)
                    {
                        Debug.Log("Firing on target: " + guardTarget.GetName());
                        SendTargetDataToMissile(ml);
                        ml.FireMissile();
                        UpdateList();
                    }
                }
                else if(ml.targetingMode == MissileLauncher.TargetingModes.Heat)
                {
                    float attemptStartTime = Time.time;
                    while(ml && Time.time-attemptStartTime < targetScanInterval*0.75f && (!heatTarget.exists || (heatTarget.predictedPosition - guardTarget.transform.position).sqrMagnitude > Mathf.Pow(40, 2)))
                    {
                        yield return null;
                    }

                    //try uncaged IR lock with radar
                    if(guardTarget && !heatTarget.exists && radar && radar.radarEnabled)
                    {
                        if(!radar.locked || (radar.lockedTarget.predictedPosition - guardTarget.transform.position).sqrMagnitude > Mathf.Pow(40, 2))
                        {
                            radar.TryLockTarget(guardTarget.transform.position);
                            yield return new WaitForSeconds(Mathf.Clamp(1, 0.1f, (targetScanInterval*0.25f) / 2));
                        }
                    }

                    if(guardTarget && ml && heatTarget.exists)
                    {
                        Debug.Log("Firing on target: " + guardTarget.GetName());
                        SendTargetDataToMissile(ml);
                        ml.FireMissile();
                        UpdateList();
                    }
                }

                guardFiringMissile = false;
            }
        }
Пример #13
0
		/// <summary>
		/// Gets the laser target painter with the least angle off boresight. Set the missile as the reference transform.
		/// </summary>
		/// <returns>The laser target painter.</returns>
		/// <param name="referenceTransform">Reference transform.</param>
		/// <param name="maxBoreSight">Max bore sight.</param>
		public static ModuleTargetingCamera GetLaserTarget(MissileLauncher ml, bool parentOnly)
		{
			Transform referenceTransform = ml.transform;
			float maxOffBoresight = ml.maxOffBoresight;
			ModuleTargetingCamera finalCam = null;
			float smallestAngle = 360;
			foreach(var cam in ActiveLasers)
			{
				if(!cam)
				{
					continue;
				}

				if(parentOnly && !(cam.vessel == ml.vessel || cam.vessel == ml.sourceVessel))
				{
					continue;
				}


				if(cam.cameraEnabled && cam.groundStabilized && cam.surfaceDetected && !cam.gimbalLimitReached)
				{
					/*
					if(ml.guidanceMode == MissileLauncher.GuidanceModes.BeamRiding && Vector3.Dot(ml.transform.position - cam.transform.position, ml.transform.forward) < 0)
					{
						continue;
					}
					*/

					float angle = Vector3.Angle(referenceTransform.forward, cam.groundTargetPosition-referenceTransform.position);
					if(angle < maxOffBoresight && angle < smallestAngle && ml.CanSeePosition(cam.groundTargetPosition))
					{
						smallestAngle = angle;
						finalCam = cam;
					}
				}
			}
			return finalCam;
		}
Пример #14
0
		IEnumerator BombsAwayRoutine(MissileLauncher ml)
		{
			missilesAway++;
			float timeStart = Time.time;
			float timeLimit = 3;
			while(ml)
			{
				if(Time.time - timeStart < timeLimit)
				{
					yield return null;
				}
				else
				{
					break;
				}
			}
			missilesAway--;
		}
Пример #15
0
		IEnumerator MissileAwayRoutine(MissileLauncher ml)
		{
			missilesAway++;
			float missileThrustTime = ml.dropTime + ml.cruiseTime + ml.boostTime;
			float timeStart = Time.time;
			float timeLimit = Mathf.Max(missileThrustTime + 4, 10);
			while(ml)
			{
				if(ml.guidanceActive && Time.time-timeStart < timeLimit)
				{
					yield return null;
				}
				else
				{
					break;
				}
			}
			missilesAway--;
		}
Пример #16
0
		void Awake()
		{
			if(!vessel)
			{
				vessel = GetComponent<Vessel>();
			}
			if(!vessel)
			{
				Debug.Log ("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 = BDArmorySettings.BDATeams.None;

			bool foundMf = false;
			foreach(var mf in vessel.FindPartModulesImplementing<MissileFire>())
			{
				foundMf = true;
				team = BDATargetManager.BoolToTeam(mf.team);
				weaponManager = mf;
				break;
			}
			if(!foundMf)
			{
				foreach(var ml in vessel.FindPartModulesImplementing<MissileLauncher>())
				{
					isMissile = true;
					missileModule = ml;
					team = BDATargetManager.BoolToTeam(ml.team);
					break;
				}
			}
				
			if(team != BDArmorySettings.BDATeams.None)
			{
				if(!BDATargetManager.TargetDatabase[BDATargetManager.OtherTeam(team)].Contains(this))
				{
					BDATargetManager.TargetDatabase[BDATargetManager.OtherTeam(team)].Add(this);
				}
			}

			friendliesEngaging = new List<MissileFire>();

			vessel.OnJustAboutToBeDestroyed += AboutToBeDestroyed;
			lifeRoutine = StartCoroutine(LifetimeRoutine());
			//add delegate to peace enable event
			BDArmorySettings.OnPeaceEnabled += OnPeaceEnabled;

			if(!isMissile && team != BDArmorySettings.BDATeams.None)
			{
				massRoutine = StartCoroutine(MassRoutine());
			}
		}
Пример #17
0
        /// <summary>
        /// Gets the laser target painter with the least angle off boresight. Set the missile as the reference transform.
        /// </summary>
        /// <returns>The laser target painter.</returns>
        /// <param name="referenceTransform">Reference transform.</param>
        /// <param name="maxBoreSight">Max bore sight.</param>
        public static ModuleTargetingCamera GetLaserTarget(MissileLauncher ml)
        {
            Transform referenceTransform = ml.transform;
            float maxOffBoresight = ml.maxOffBoresight;
            ModuleTargetingCamera finalCam = null;
            float smallestAngle = 360;
            foreach(var cam in ActiveLasers)
            {
                if(!cam)
                {
                    continue;
                }

                if(cam.cameraEnabled && cam.groundStabilized && cam.surfaceDetected && !cam.gimbalLimitReached)
                {
                    float angle = Vector3.Angle(referenceTransform.forward, cam.groundTargetPosition-referenceTransform.position);
                    if(angle < maxOffBoresight && angle < smallestAngle && ml.CanSeePosition(cam.groundTargetPosition))
                    {
                        smallestAngle = angle;
                        finalCam = cam;
                    }
                }
            }
            return finalCam;
        }
Пример #18
0
        public void PrepMissileForFire(MissileLauncher ml)
        {
            int index = IndexOfMissile(ml);

            if(index >= 0)
            {
                PrepMissileForFire(index);
            }
            else
            {
                Debug.Log("Tried to prep a missile for firing that doesn't exist or is not attached to the turret.");
            }
        }
Пример #19
0
        public static Vector3 GetAirToAirFireSolution(MissileLauncher missile, Vector3 targetPosition, Vector3 targetVelocity)
        {
            float leadTime = 0;
            float targetDistance = Vector3.Distance(targetPosition, missile.transform.position);

            Vector3 simMissileVel = missile.optimumAirspeed * (targetPosition-missile.transform.position).normalized;
            leadTime = targetDistance/(targetVelocity-simMissileVel).magnitude;
            leadTime = Mathf.Clamp (leadTime, 0f, 8f);

            targetPosition = targetPosition + (targetVelocity*leadTime);

            return targetPosition;
        }
Пример #20
0
        IEnumerator MissileRailRoutine(MissileLauncher ml)
        {
            yield return null;
            Ray ray = new Ray(ml.transform.position, ml.missileReferenceTransform.forward);
            Vector3 localOrigin = turret.pitchTransform.InverseTransformPoint(ray.origin);
            Vector3 localDirection = turret.pitchTransform.InverseTransformDirection(ray.direction);
            float forwardSpeed = ml.decoupleSpeed;
            while(ml && Vector3.SqrMagnitude(ml.transform.position - ray.origin) < railLength*railLength)
            {
                float thrust = ml.timeIndex < ml.boostTime ? ml.thrust : ml.cruiseThrust;
                thrust = ml.timeIndex < ml.boostTime + ml.cruiseTime ? thrust : 0;
                float accel = thrust / ml.part.mass;
                forwardSpeed += accel * Time.fixedDeltaTime;

                ray.origin = turret.pitchTransform.TransformPoint(localOrigin);
                ray.direction = turret.pitchTransform.TransformDirection(localDirection);

                Vector3 projPos = Vector3.Project(ml.vessel.transform.position - ray.origin, ray.direction) + ray.origin;
                Vector3 railVel = part.rb.GetPointVelocity(projPos);
                //Vector3 projVel = Vector3.Project(ml.vessel.srf_velocity-railVel, ray.direction);

                ml.vessel.SetPosition(projPos);
                ml.vessel.SetWorldVelocity(railVel + (forwardSpeed*ray.direction));

                yield return new WaitForFixedUpdate();

                ray.origin = turret.pitchTransform.TransformPoint(localOrigin);
                ray.direction = turret.pitchTransform.TransformDirection(localDirection);
            }
        }
Пример #21
0
        public static Vector3 DoAeroForces(MissileLauncher ml, Vector3 targetPosition, float liftArea, float steerMult, Vector3 previousTorque, float maxTorque, float maxAoA, FloatCurve liftCurve, FloatCurve dragCurve)
        {
            Rigidbody rb = ml.part.rb;
            double airDensity = ml.vessel.atmDensity;
            double airSpeed = ml.vessel.srfSpeed;
            Vector3d velocity = ml.vessel.srf_velocity;

            //temp values
            Vector3 CoL = new Vector3(0, 0, -1f);
            float liftMultiplier = BDArmorySettings.GLOBAL_LIFT_MULTIPLIER;
            float dragMultiplier = BDArmorySettings.GLOBAL_DRAG_MULTIPLIER;

            //lift
            float AoA = Mathf.Clamp(Vector3.Angle(ml.transform.forward, velocity.normalized), 0, 90);
            if(AoA > 0)
            {
                double liftForce = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * liftMultiplier * liftCurve.Evaluate(AoA);
                Vector3 forceDirection = Vector3.ProjectOnPlane(-velocity, ml.transform.forward).normalized;
                rb.AddForceAtPosition((float)liftForce * forceDirection, ml.transform.TransformPoint(CoL));
            }

            //drag
            if(airSpeed > 0)
            {
                double dragForce = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * dragMultiplier * dragCurve.Evaluate(AoA);
                rb.AddForceAtPosition((float)dragForce * -velocity.normalized, ml.transform.TransformPoint(CoL));
            }

            //guidance
            if(airSpeed > 1)
            {
                Vector3 targetDirection;
                float targetAngle;
                if(AoA < maxAoA)
                {
                    targetDirection = (targetPosition - ml.transform.position);
                    targetAngle = Vector3.Angle(velocity.normalized, targetDirection) * 4;
                }
                else
                {
                    targetDirection = velocity.normalized;
                    targetAngle = AoA;
                }

                Vector3 torqueDirection = -Vector3.Cross(targetDirection, velocity.normalized).normalized;
                torqueDirection = ml.transform.InverseTransformDirection(torqueDirection);

                float torque = Mathf.Clamp(targetAngle * steerMult, 0, maxTorque);
                Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, torqueDirection*torque, 0.86f), Vector3.forward);

                rb.AddRelativeTorque(finalTorque);

                return finalTorque;

            }
            else
            {
                Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, Vector3.zero, 0.25f), Vector3.forward);
                rb.AddRelativeTorque(finalTorque);
                return finalTorque;
            }
        }
Пример #22
0
        public bool ContainsMissileOfType(MissileLauncher ml)
        {
            if(!ml) return false;
            if(missileCount == 0) return false;

            for(int i = 0; i < missileCount; i++)
            {
                if((missileChildren[i]) && missileChildren[i].part.name == ml.part.name)
                {
                    return true;
                }
            }
            return false;
        }
Пример #23
0
		void RotateToIndex(int index, bool instant)
		{
			//Debug.Log("Rotary rail is rotating to index: " + index);

			if(rotationRoutine != null)
			{
				StopCoroutine(rotationRoutine);
			}

			// if(railIndex == index && readyToFire) return;

			if(missileCount > 0)
			{
				if(railToMissileIndex.ContainsKey(index))
				{
					nextMissile = missileChildren[railToMissileIndex[index]];
				}
			}
			else
			{
				nextMissile = null;
			}

			if(!nextMissile && missileCount > 0)
			{
				RotateToIndex(Mathf.RoundToInt(Mathf.Repeat(index + 1, numberOfRails)), instant);
				return;
			}

			rotationRoutine = StartCoroutine(RotateToIndexRoutine(index, instant));
		}
Пример #24
0
        bool CheckBombClearance(MissileLauncher ml)
        {
            if(!BDArmorySettings.BOMB_CLEARANCE_CHECK) return true;

            if(ml.part.ShieldedFromAirstream)
            {
                return false;
            }

            if(ml.dropTime > 0.3f)
            {
                //debug lines
                LineRenderer lr = null;
                if(BDArmorySettings.DRAW_DEBUG_LINES && BDArmorySettings.DRAW_AIMERS)
                {
                    lr = GetComponent<LineRenderer>();
                    if(!lr)
                    {
                        lr = gameObject.AddComponent<LineRenderer>();
                    }
                    lr.enabled = true;
                    lr.SetWidth(.1f, .1f);
                }
                else
                {
                    if(gameObject.GetComponent<LineRenderer>())
                    {
                        gameObject.GetComponent<LineRenderer>().enabled = false;
                    }
                }

                float radius = 0.28f / 2;
                float time = ml.dropTime;
                Vector3 direction = ((ml.decoupleForward ? ml.transform.forward : -ml.transform.up) * ml.decoupleSpeed * time) + ((FlightGlobals.getGeeForceAtPosition(transform.position) - vessel.acceleration) * 0.5f * time*time);
                Vector3 crossAxis = Vector3.Cross(direction, ml.transform.forward).normalized;

                float rayDistance;
                if(ml.thrust == 0 || ml.cruiseThrust == 0)
                {
                    rayDistance = 8;
                }
                else
                {
                    //distance till engine starts based on grav accel and vessel accel
                    rayDistance = direction.magnitude;
                }

                Ray[] rays = new Ray[] {
                    new Ray(ml.transform.position - (radius * crossAxis), direction),
                    new Ray(ml.transform.position + (radius * crossAxis), direction),
                    new Ray(ml.transform.position, direction)
                };

                if(lr)
                {
                    lr.useWorldSpace = false;
                    lr.SetVertexCount(4);
                    lr.SetPosition(0, transform.InverseTransformPoint(rays[0].origin));
                    lr.SetPosition(1, transform.InverseTransformPoint(rays[0].GetPoint(rayDistance)));
                    lr.SetPosition(2, transform.InverseTransformPoint(rays[1].GetPoint(rayDistance)));
                    lr.SetPosition(3, transform.InverseTransformPoint(rays[1].origin));
                }

                for(int i = 0; i < rays.Length; i++)
                {
                    RaycastHit[] hits = Physics.RaycastAll(rays[i], rayDistance, 557057);
                    for(int h = 0; h < hits.Length; h++)
                    {
                        Part p = hits[h].collider.GetComponentInParent<Part>();

                        if((p != null && p != ml.part) || p == null) return false;
                    }
                }

                return true;
            }
            else
            {
                //forward check for no-drop missiles
                if(Physics.Raycast(new Ray(ml.transform.position, ml.transform.forward), 50, 557057))
                {
                    return false;
                }
            }

            return true;
        }
Пример #25
0
		public void PrepMissileForFire(MissileLauncher ml)
		{
			if(ml != readyMissile)
			{
				//Debug.Log("Rotary rail tried prepping a missile for fire, but it is not in firing position");
				return;
			}

			int index = IndexOfMissile(ml);

			if(index >= 0)
			{
				PrepMissileForFire(index);
			}
			else
			{
				//Debug.Log("Tried to prep a missile for firing that doesn't exist or is not attached to the turret.");
			}
		}
Пример #26
0
        //give distance parameter
        IEnumerator WarningSoundRoutine(float distance, MissileLauncher ml)
        {
            if(distance < 4000)
            {
                warningSounding = true;
                BDArmorySettings.Instance.missileWarningTime = Time.time;
                BDArmorySettings.Instance.missileWarning = true;
                warningAudioSource.pitch = distance < 800 ? 1.45f : 1f;
                warningAudioSource.PlayOneShot(warningSound);

                float waitTime = distance < 800 ? .25f : 1.5f;

                yield return new WaitForSeconds(waitTime);

                if(ml.vessel && CanSeeTarget(ml.vessel))
                {
                    BDATargetManager.ReportVessel(ml.vessel, this);
                }
            }
            warningSounding = false;
        }
Пример #27
0
		public void FireMissile(MissileLauncher ml)
		{
			if(!readyToFire || ml != readyMissile)
			{
				return;
			}

		
			int index = IndexOfMissile(ml);
			if(index >= 0)
			{
				//Debug.Log("Firing missile index: " + index);
				FireMissile(index);
			}
			else
			{
				//Debug.Log("Tried to fire a missile that doesn't exist or is not attached to the rail.");
			}
		}
Пример #28
0
        //take distance parameter
        public void MissileWarning(float distance, MissileLauncher ml)
        {
            if(vessel.isActiveVessel && !warningSounding)
            {
                StartCoroutine(WarningSoundRoutine(distance, ml));
            }

            missileIsIncoming = true;
            incomingMissileDistance = distance;
        }
Пример #29
0
        public void SendTargetDataToMissile(MissileLauncher ml)
        {
            if(ml.targetingMode == MissileLauncher.TargetingModes.Laser && laserPointDetected)
            {
                ml.lockedCamera = foundCam;
            }
            else if(ml.targetingMode == MissileLauncher.TargetingModes.GPS)
            {
                if(BDArmorySettings.ALLOW_LEGACY_TARGETING)
                {
                    if(vessel.targetObject != null && vessel.targetObject.GetVessel() != null)
                    {
                        ml.targetAcquired = true;
                        ml.legacyTargetVessel = vessel.targetObject.GetVessel();
                    }
                }
                else if(designatedGPSCoords != Vector3d.zero)
                {
                    ml.targetGPSCoords = designatedGPSCoords;
                    ml.targetAcquired = true;
                }
            }
            else if(ml.targetingMode == MissileLauncher.TargetingModes.Heat && heatTarget.exists)
            {
                ml.heatTarget = heatTarget;
                heatTarget = TargetSignatureData.noTarget;
            }
            else if(ml.targetingMode == MissileLauncher.TargetingModes.Radar && radar && radar.lockedTarget.exists)
            {
                ml.radarTarget = radar.lockedTarget;
                if(radar.linked && radar.linkedRadar.locked)
                {
                    ml.radar = radar.linkedRadar;
                }
                else
                {
                    ml.radar = radar;
                }
                radar.lastMissile = ml;

            }
            else if(ml.targetingMode == MissileLauncher.TargetingModes.AntiRad && antiRadTargetAcquired)
            {
                ml.targetAcquired = true;
                ml.targetGPSCoords = VectorUtils.WorldPositionToGeoCoords(antiRadiationTarget, vessel.mainBody);
            }
        }
Пример #30
0
		public void UpdateList()
		{
			weaponTypes.Clear();

			foreach(IBDWeapon weapon in vessel.FindPartModulesImplementing<IBDWeapon>())
			{
				string weaponName = weapon.GetShortName();
				bool alreadyAdded = false;
				foreach(var weap in weaponTypes)
				{
					if(weap.GetShortName() == weaponName)
					{
						alreadyAdded = true;
						break;
					}
				}

				//dont add empty rocket pods
				if(weapon.GetWeaponClass() == WeaponClasses.Rocket && weapon.GetPart().FindModuleImplementing<RocketLauncher>().GetRocketResource().amount < 1)
				{
					continue;
				}

				if(!alreadyAdded)
				{
					weaponTypes.Add(weapon);
				}
			}
			
			//weaponTypes.Sort();
			weaponTypes = weaponTypes.OrderBy(w => w.GetShortName()).ToList();
			
			List<IBDWeapon> tempList = new List<IBDWeapon>();
			tempList.Add (null);
			tempList.AddRange(weaponTypes);
			
			weaponArray = tempList.ToArray();
			
			if(weaponIndex >= weaponArray.Length)
			{
				hasSingleFired = true;
				triggerTimer = 0;
				
			}

			weaponIndex = Mathf.Clamp(weaponIndex, 0, weaponArray.Length - 1);

			if(selectedWeapon == null || selectedWeapon.GetPart() == null || selectedWeapon.GetPart().vessel!=vessel || GetWeaponName(selectedWeapon) != GetWeaponName(weaponArray[weaponIndex]))
			{
				selectedWeapon = weaponArray[weaponIndex];

				if(vessel.isActiveVessel && Time.time - startTime > 1)
				{
					hasSingleFired = true;
				}

				if(vessel.isActiveVessel && weaponIndex!=0)
				{
					DisplaySelectedWeaponMessage();
				}
			}

			if(weaponIndex == 0)
			{
				selectedWeapon = null;
				hasSingleFired = true;
			}

			MissileLauncher aMl = GetAsymMissile();
			if(aMl)
			{
				//Debug.Log("setting asym missile: " + aMl.part.name);
				selectedWeapon = aMl;
				currentMissile = aMl;
			}

			MissileLauncher rMl = GetRotaryReadyMissile();
			if(rMl)
			{
				//Debug.Log("setting rotary ready missile: " + rMl.part.name);
				selectedWeapon = rMl;
				currentMissile = rMl;
			}

			if(selectedWeapon != null && (selectedWeapon.GetWeaponClass() == WeaponClasses.Bomb || selectedWeapon.GetWeaponClass() == WeaponClasses.Missile))
			{
				//Debug.Log("=====selected weapon: " + selectedWeapon.GetPart().name);
				if(!currentMissile || currentMissile.part.name != selectedWeapon.GetPart().name)
				{
					currentMissile = selectedWeapon.GetPart().FindModuleImplementing<MissileLauncher>();
				}
			}
			else
			{
				currentMissile = null;
			}

			//selectedWeapon = weaponArray[weaponIndex];

			//bomb stuff
			if(selectedWeapon != null && selectedWeapon.GetWeaponClass() == WeaponClasses.Bomb)
			{
				bombPart = selectedWeapon.GetPart();
			}
			else
			{
				bombPart = null;
			}

            //gun ripple stuff
			if(selectedWeapon != null && selectedWeapon.GetWeaponClass() == WeaponClasses.Gun && currentGun.roundsPerMinute < 1500)
            {
                float counter = 0;
                float weaponRPM = 0;
				gunRippleIndex = 0;
				rippleGunCount = 0;
                List<ModuleWeapon> tempListModuleWeapon = vessel.FindPartModulesImplementing<ModuleWeapon>();
                foreach (ModuleWeapon weapon in tempListModuleWeapon)
                {
                    if (selectedWeapon.GetShortName() == weapon.GetShortName())
                    {
						weapon.rippleIndex = Mathf.RoundToInt(counter);
                        weaponRPM = weapon.roundsPerMinute;
						++counter;
						rippleGunCount++;
                    }
                }
				gunRippleRpm = weaponRPM * counter;
                float timeDelayPerGun = 60f / (weaponRPM * counter);    //number of seconds between each gun firing; will reduce with increasing RPM or number of guns
                foreach (ModuleWeapon weapon in tempListModuleWeapon)
                {
                    if (selectedWeapon.GetShortName() == weapon.GetShortName())
                    {
                        weapon.initialFireDelay = timeDelayPerGun;        //set the time delay for moving to next index
                    }
                }

                RippleOption ro;        //ripplesetup and stuff
                if (rippleDictionary.ContainsKey(selectedWeapon.GetShortName()))
                {
                    ro = rippleDictionary[selectedWeapon.GetShortName()];
                }
                else
                {
					ro = new RippleOption(currentGun.useRippleFire, 650);       //take from gun's persistant value
                    rippleDictionary.Add(selectedWeapon.GetShortName(), ro);
                }

                foreach (ModuleWeapon w in vessel.FindPartModulesImplementing<ModuleWeapon>())
                {
                    if (w.GetShortName() == selectedWeapon.GetShortName())
                        w.useRippleFire = ro.rippleFire;
                }
            }

			//rocket
			FindNextRocket(null);
		
			ToggleTurret();
			SetMissileTurrets();
			SetRocketTurrets();
			SetRotaryRails();
		}