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(); }
protected void UpdateWeaponManager() { weaponManager = VesselModuleRegistry.GetModule <MissileFire>(vessel); if (weaponManager != null) { weaponManager.AI = 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); } } }
/// <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; } } } } }
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(); } } } } } }
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; }
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); }
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."); }