288 lines
12 KiB
C#
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();
|
|
}
|
|
};*/
|