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

288 lines
12 KiB
C#

using System.Collections.Generic;
using Cielonos.MainGame.Buffs.Character;
using Cielonos.MainGame.Characters;
using Cielonos.MainGame.Effects.Feedback;
using Lean.Pool;
using SLSUtilities.General;
using SLSUtilities.WwiseAssistance;
using UnityEngine;
namespace Cielonos.MainGame.Inventory.Collections
{
public partial class FutureWand
{
private readonly List<NormalArea> _activeSpinAreas = new List<NormalArea>();
private const float NormalBoltSpeed = 10f;
private const float CubicBoltSpeed = 15f;
private int _spinAreaUpgradeCount = 0;
/// <summary>
/// 召回当前在战场中飞旋的法盘区域。
/// </summary>
private void RecallAllSpinAreas()
{
for (int i = _activeSpinAreas.Count - 1; i >= 0; i--)
{
var area = _activeSpinAreas[i];
if (area == null)
{
_activeSpinAreas.RemoveAt(i);
continue;
}
if (area.moveSm is AttackAreaBase.BoomerangMoveSubmodule boomerangSm)
{
boomerangSm.TriggerReturn();
}
}
}
private void GenerateLightning(string vfxName, AttackUnit attackUnit, CharacterBase target, Vector3 position = default)
{
if (target == null && position == default) return;
vfxData.SpawnMuzzleVFX(vfxName, player, Muzzle);
NormalArea lightning = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
lightning.Initialize<NormalArea>(player, this, Fraction.Enemy)
.SetAttackSubmodule<NormalArea>(attackUnit)
.SetTimeSubmodule<NormalArea>(2f, 0.1f, 0.04f)
.SetHitSubmodule<NormalArea>();
lightning.eventSm.onHit.Add((enemy, hitPosition) =>
{
new LightningBuff().Apply(enemy, player, this);
feedbackSc.PlayFeedback("LightningHit");
});
Vector3 spawnPosition = target != null ? target.transform.position : position;
lightning.topParent.transform.position = spawnPosition;
AudioManager.Post(AK.EVENTS.FUTUREWAND_MEDIUMATTACKHIT, spawnPosition);
}
private void GenerateGroundArea(string vfxName, AttackUnit attackUnit)
{
vfxData.SpawnMuzzleVFX(vfxName, player, Muzzle);
NormalArea area = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
AudioManager.Post(AK.EVENTS.FUTUREWAND_GROUNDAREA, area.gameObject);
if (!_hasBlackHoleDisplacer)
{
area.Initialize<NormalArea>(player, this, Fraction.Enemy)
.SetAttackSubmodule<NormalArea>(attackUnit)
.SetTimeSubmodule<NormalArea>(3f, 0.2f, 0.8f)
.SetHitSubmodule<NormalArea>(0.1f, 4);
}
else
{
area.Initialize<NormalArea>(player, this, Fraction.Enemy);
ApplyBlackHoleDisplacer(area, attackUnit);
}
area.SetTractionSubmodule<NormalArea>(6f);
area.hitSm.AddHitSound(AK.EVENTS.FUTUREWAND_WEAKATTACKHIT);
int fusionStack = GetBaseFusionStack(attackUnit);
area.eventSm.onHit.Add((enemy, hitPosition) =>
{
new Fusion(fusionStack).Apply(enemy);
SubscribeFusionExplode(enemy);
});
}
private void GenerateUltimateBeam(string vfxName, AttackUnit attackUnit)
{
vfxData.SpawnMuzzleVFX(vfxName, player, Muzzle);
NormalArea area = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
area.Initialize<NormalArea>(player, this, Fraction.Enemy)
.SetAttackSubmodule<NormalArea>(attackUnit)
.SetTimeSubmodule<NormalArea>(5f, 0.6f, 0.04f)
.SetHitSubmodule<NormalArea>();
area.SetImpulseSubmodule().WithCustomForce(player.transform.forward * 15f);
area.hitSm.AddHitSound(AK.EVENTS.FUTUREWAND_MEDIUMATTACKHIT);
AudioManager.Post(AK.EVENTS.FUTUREWAND_ULTIMATEBEAMPOWERUP, area.gameObject);
area.AddScheduleAction(() =>
{
AudioManager.Post(AK.EVENTS.FUTUREWAND_ULTIMATEBEAMSHOOT);
feedbackSc.PlayFeedback("UltimateBeamShoot");
}, 0.6f);
}
private void GenerateTornado(string vfxName, AttackUnit attackUnit, CharacterBase target, float speed)
{
vfxData.SpawnMuzzleVFX(vfxName, player, Muzzle);
NormalArea area = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
area.Initialize<NormalArea>(player, this, Fraction.Enemy)
.SetAttackSubmodule<NormalArea>(attackUnit)
.SetTimeSubmodule<NormalArea>(2f, 0f, 1.5f)
.SetHitSubmodule<NormalArea>()
.SetLinearDirectionMoveModule<NormalArea>(player.transform.forward, speed, 0f, true, false, false)
//.SetAdaptiveTraceMoveSubmodule<NormalArea>(target, speed, 5f, 180f, 30f, player.transform.forward, detectRadius: 25f, stopWhenHit: true)
.SetTransformSubmodule<NormalArea>();
area.SetImpulseSubmodule(1f).WithDynamicForce(30f);
//(area.moveSm as TraceMoveSubmodule)?.WithKeepFlat(true);
AudioManager.Post(AK.EVENTS.FUTUREWAND_TORNADO);
area.hitSm.AddHitSound(AK.EVENTS.FUTUREWAND_WEAKATTACKHIT);
int fusionStack = GetBaseFusionStack(attackUnit);
area.eventSm.onHit.Add((enemy, hitPosition) =>
{
new Fusion(fusionStack).Apply(enemy);
SubscribeFusionExplode(enemy);
});
}
private void GenerateProjectile(string vfxName, AttackUnit attackUnit, CharacterBase target, bool hasMuzzleEffect = true, Transform muzzle = null)
{
float speed = vfxName == "CubicBolt" ? CubicBoltSpeed : NormalBoltSpeed;
if (hasMuzzleEffect)
{
muzzle ??= Muzzle;
vfxData.SpawnMuzzleVFX(vfxName, player, muzzle);
}
Projectile projectile = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<Projectile>();
Vector3 direction = player.transform.forward;
if (target != null)
{
direction = (target.CenterPoint.position - projectile.transform.position).normalized;
}
projectile.Initialize(player, this, false, 1, Fraction.Enemy)
.SetAttackSubmodule<Projectile>(attackUnit)
.SetTimeSubmodule<Projectile>(10f, 0f, 10f)
.SetHitSubmodule<Projectile>()
.SetAdaptiveTraceMoveSubmodule<Projectile>(target, speed, 5f, 180f, 30f, direction, detectRadius: 25f)
.SetRaycastSubmodule<Projectile>(default, 0.25f, 0.5f);
if (vfxName == "NormalBolt")
{
projectile.hitSm.AddHitSound(AK.EVENTS.FUTUREWAND_WEAKATTACKHIT);
projectile.SetImpulseSubmodule().WithDynamicForce(2f);
projectile.eventSm.onHit.Add((enemy, hitPosition)=>
{
feedbackSc.PlayFeedback("NormalBoltHit", rt =>
{
rt.Action<CameraPositionShakeAction>("Camera").amplitude = GetBoltHitShakeAmplitude(hitPosition, 0.035f, -0.035f, 0.04f);
});
});
AudioManager.Post(AK.EVENTS.FUTUREWAND_NORMALBOLTRELEASE, projectile.gameObject);
}
else if (vfxName == "CubicBolt")
{
projectile.hitSm.AddHitSound(AK.EVENTS.FUTUREWAND_MEDIUMATTACKHIT);
projectile.SetImpulseSubmodule().WithDynamicForce(4f);
projectile.eventSm.onHit.Add((enemy, hitPosition) =>
{
feedbackSc.PlayFeedback("CubicBoltHit", rt =>
{
rt.Action<CameraPositionShakeAction>("Camera").amplitude = GetBoltHitShakeAmplitude(hitPosition, 0.055f, -0.05f, 0.065f);
});
});
AudioManager.Post(AK.EVENTS.FUTUREWAND_CUBICBOLTRELEASE, projectile.gameObject);
}
int fusionStack = GetBaseFusionStack(attackUnit);
if (_hasFusionChargeCore)
{
fusionStack = ApplyFusionChargeCore(fusionStack, vfxName);
}
projectile.eventSm.onHit.Add((enemy, hitPosition) =>
{
new Fusion(fusionStack).Apply(enemy);
SubscribeFusionExplode(enemy);
if (_hasMissileSeparationMembrane)
{
TryGenerateMissileSeparation(projectile, vfxName, attackUnit, enemy, hitPosition, speed);
}
});
}
private Vector3 GetBoltHitShakeAmplitude(Vector3 hitPosition, float horizontalStrength, float verticalKick, float depthKick)
{
return FeedbackVectorUtility.ScreenHitPositionToAmplitude(
hitPosition,
MainGameManager.Player.viewSc.playerCamera,
horizontalStrength,
verticalKick,
depthKick);
}
private void GenerateSpinArea(string vfxName, AttackUnit attackUnit)
{
AttackUnit upgradedAttackUnit = attackUnit.Clone();
float damageMultiplier = 0.75f + _spinAreaUpgradeCount * 0.25f;
upgradedAttackUnit.startDamage *= damageMultiplier;
vfxData.SpawnMuzzleVFX(vfxName, player, Muzzle);
NormalArea area = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
area.Initialize<NormalArea>(player, this, Fraction.Enemy)
.SetAttackSubmodule<NormalArea>(upgradedAttackUnit)
.SetTimeSubmodule<NormalArea>(int.MaxValue, 0.5f, int.MaxValue, null, Shrink)
.SetHitSubmodule<NormalArea>(0.25f, int.MaxValue)
.SetBoomerangMoveSubmodule<NormalArea>(PrimaryTarget, 10f, 0f, 360f, 0f, player.transform.forward)
.SetTransformSubmodule<NormalArea>();
(area.moveSm as AttackAreaBase.BoomerangMoveSubmodule)
!.WithAutoReturn(2f + _spinAreaUpgradeCount * 3f)
.WithCatch(1.5f, Shrink)
.WithTargeting(true, 25f)
.WithKeepFlat(true)
.WithReturnParameters(20f, 10f, float.MaxValue, 0f);
area.transformSm.ApplyScaleMove(Vector3.zero, Vector3.one * 3, 0.5f, EaseType.OutQuad);
area.SetImpulseSubmodule().WithSuction(4f);
AudioManager.Post(AK.EVENTS.FUTUREWAND_SPINAREARELEASE);
area.hitSm.AddHitSound(AK.EVENTS.FUTUREWAND_WEAKATTACKHIT);
int fusionStack = GetBaseFusionStack(upgradedAttackUnit);
area.eventSm.onHit.Add((enemy, hitPosition) =>
{
new Fusion(fusionStack).Apply(enemy);
SubscribeFusionExplode(enemy);
});
_spinAreaUpgradeCount = 0;
_activeSpinAreas.Add(area);
return;
void Shrink()
{
if(area == null) return;
area.transformSm.Reset().ApplyScaleMove(Vector3.one * 3, Vector3.zero, 0.5f, EaseType.OutQuad);
area.AddScheduleAction(() => LeanPool.Despawn(area.topParent.gameObject), 0.5f);
_activeSpinAreas.Remove(area);
}
}
}
}
/*area.updateAction = () => // 消除敌方投射物
{
if (area.timeSm.enablingTimer > 3f)
{
return;
}
List<Projectile> toBeRemoved = new List<Projectile>();
foreach (Projectile projectile in CombatManager.AttackAreaSm.enemyAttackAreas.activeProjectiles)
{
if (area.areaCollider.IsPointInside(projectile.topParent.transform.position))
{
toBeRemoved.Add(projectile);
}
}
foreach (Projectile projectile in toBeRemoved)
{
projectile.Explode();
}
};*/