130 lines
4.9 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|