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(); }
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); }
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)); } }
/// <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(); } } } } } }
// [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; }
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); }
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; }
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>(); } }