using System.Collections; using System.Collections.Generic; using Cielonos.MainGame.Characters; using Cielonos.MainGame.UI; using SLSUtilities.WwiseAssistance; using UnityEngine; namespace Cielonos.MainGame.Inventory.Collections { /// /// 在短时间内发射多枚随机选敌的高速追踪飞弹。 /// public class HummingbirdSwarmMissile : SupportEquipmentBase { private const string MissileVfxName = "Missile"; private const int MissileCount = 12; private const float LaunchDuration = 0.3f; private const float SearchRadius = 50f; private const float MissileLifeTime = 10f; private const float MissileSpeed = 30f; private const float MissileAngularSpeed = 360f; private const float InitialYawSpread = 90f; private const float InitialYawJitter = 8f; private const float InitialPitchSpread = 30f; private Transform _muzzle; public override void OnObtained() { base.OnObtained(); _muzzle = player.bodyPartsSc.AuxiliaryDrone.center; } public override void OnPress(List modifiers = default) { if (!functionSm.mainFunction.IsAvailable()) { PlayerCanvas.SupportEquipmentsUIArea[this].CanNotUseOutlineAnimation(); return; } if (GetRandomTarget() == null) { PlayerCanvas.SupportEquipmentsUIArea[this].NoTargetOutlineAnimation(); return; } StartCoroutine(LaunchSalvo()); functionSm.mainFunction.Execute(); PlayerCanvas.SupportEquipmentsUIArea[this].UseOutlineAnimation(); } private IEnumerator LaunchSalvo() { float launchInterval = MissileCount > 1 ? LaunchDuration / (MissileCount - 1) : 0f; for (int missileIndex = 0; missileIndex < MissileCount; missileIndex++) { Enemy target = GetRandomTarget(); if (target != null) { GenerateMissile(target, missileIndex); } if (missileIndex < MissileCount - 1) { yield return WaitForLocalTime(launchInterval); } } } private IEnumerator WaitForLocalTime(float duration) { float elapsed = 0f; while (elapsed < duration) { elapsed += player.selfTimeSm.DeltaTime; yield return null; } } private Enemy GetRandomTarget() { List candidates = CombatManager.EnemySm.Query(SearchRadius).Candidates(); if (candidates.Count == 0) { return null; } return candidates[Random.Range(0, candidates.Count)]; } private void GenerateMissile(Enemy target, int missileIndex) { AudioManager.Post(AK.EVENTS.HUMMINGBIRDSWARMMISSILE_SHOOT, _muzzle.gameObject); vfxData.SpawnMuzzleVFX(MissileVfxName, player, _muzzle); Projectile missile = vfxData.SpawnVFX(MissileVfxName, player, _muzzle) .GetComponentInChildren(); Vector3 targetDirection = (target.CenterPoint.position - missile.transform.position).normalized; Vector3 initialDirection = GetInitialDirection(targetDirection, missileIndex); missile.Initialize(player, this, false, 1, Fraction.Enemy) .SetAttackSubmodule(attackData[MissileVfxName]) .SetTimeSubmodule(MissileLifeTime) .SetHitSubmodule() .SetAdaptiveTraceMoveSubmodule(target, MissileSpeed, 0f, MissileAngularSpeed, 0f, initialDirection, autoConnect: false, autoDisconnect: false, detectRadius: SearchRadius) .SetRaycastSubmodule(default, 0.2f); missile.hitSm.AddHitSound(AK.EVENTS.HUMMINGBIRDSWARMMISSILE_HIT); } private Vector3 GetInitialDirection(Vector3 targetDirection, int missileIndex) { float distribution = MissileCount <= 1 ? 0f : Mathf.Lerp(-InitialYawSpread, InitialYawSpread, missileIndex / (float)(MissileCount - 1)); float yaw = distribution + Random.Range(-InitialYawJitter, InitialYawJitter); Vector3 direction = Quaternion.AngleAxis(yaw, Vector3.up) * targetDirection; Vector3 pitchAxis = Vector3.Cross(Vector3.up, direction).normalized; if (pitchAxis.sqrMagnitude > 0f) { float pitch = Random.Range(-InitialPitchSpread, InitialPitchSpread); direction = Quaternion.AngleAxis(pitch, pitchAxis) * direction; } return direction.normalized; } } }