Files
Cielonos/Assets/Scripts/MainGame/Items/SupportEquipments/HummingbirdSwarmMissile.cs
SoulliesOfficial 39b43680a9 爆更
2026-07-18 03:16:20 -04:00

130 lines
4.9 KiB
C#

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
{
/// <summary>
/// 在短时间内发射多枚随机选敌的高速追踪飞弹。
/// </summary>
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<PlayerInputModifierType> 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<Enemy> 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<Projectile>();
Vector3 targetDirection = (target.CenterPoint.position - missile.transform.position).normalized;
Vector3 initialDirection = GetInitialDirection(targetDirection, missileIndex);
missile.Initialize(player, this, false, 1, Fraction.Enemy)
.SetAttackSubmodule<Projectile>(attackData[MissileVfxName])
.SetTimeSubmodule<Projectile>(MissileLifeTime)
.SetHitSubmodule<Projectile>()
.SetAdaptiveTraceMoveSubmodule<Projectile>(target, MissileSpeed, 0f, MissileAngularSpeed, 0f,
initialDirection, autoConnect: false, autoDisconnect: false, detectRadius: SearchRadius)
.SetRaycastSubmodule<Projectile>(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;
}
}
}