158 lines
6.2 KiB
C#
158 lines
6.2 KiB
C#
using System.Collections.Generic;
|
||
using Cielonos.MainGame.Buffs.Character;
|
||
using Cielonos.MainGame.Characters;
|
||
using SLSUtilities.General;
|
||
using UnityEngine;
|
||
|
||
namespace Cielonos.MainGame.Inventory.Collections
|
||
{
|
||
public partial class FutureWand
|
||
{
|
||
private bool _hasMissileSeparationMembrane;
|
||
private bool _hasBlackHoleDisplacer;
|
||
private bool _hasStellarRingQuickcaster;
|
||
private bool _hasCubicScatterIndexer;
|
||
private bool _hasFusionChargeCore;
|
||
private bool _hasSigilBreakWedge;
|
||
private bool _hasLightningConcentrator;
|
||
|
||
private const int StellarRingQuickcasterSpinAreaUpgradeLevel = 1;
|
||
private const int FusionChargeCoreExtraFusionStack = 1;
|
||
private const float SigilBreakWedgeExtraStanceDepletion = 30f;
|
||
|
||
protected override void OnExtendersChanged()
|
||
{
|
||
CacheExtenderFlags();
|
||
}
|
||
|
||
private void CacheExtenderFlags()
|
||
{
|
||
_hasMissileSeparationMembrane = HasExtender<MissileSeparationMembrane>();
|
||
_hasBlackHoleDisplacer = HasExtender<BlackHoleDisplacer>();
|
||
_hasStellarRingQuickcaster = HasExtender<StellarRingQuickcaster>();
|
||
_hasCubicScatterIndexer = HasExtender<CubicScatterIndexer>();
|
||
_hasFusionChargeCore = HasExtender<FusionChargeCore>();
|
||
_hasSigilBreakWedge = HasExtender<SigilBreakWedge>();
|
||
_hasLightningConcentrator = HasExtender<LightningConcentrator>();
|
||
functionSm?["Lightning"]?.SetRuntimeTag(
|
||
nameof(LightningConcentrator),
|
||
FunctionData.FunctionUnit.DisruptionTag,
|
||
_hasLightningConcentrator);
|
||
}
|
||
|
||
private AttackUnit ApplyLightningConcentrator(AttackUnit source)
|
||
{
|
||
if (!_hasLightningConcentrator) return source;
|
||
|
||
// AttackData 已把基础倍率结算进 startDamage;clone 后只修改本次 Lightning。
|
||
AttackUnit modified = source.Clone();
|
||
modified.startDamage *= 2f;
|
||
modified.damageDeviation *= 2f;
|
||
modified.breakthroughType = Breakthrough.Type.Disruption;
|
||
return modified;
|
||
}
|
||
|
||
private bool PlayStellarRingQuickcasterSpinArea()
|
||
{
|
||
if (!functionSm["SpinArea"].IsAvailable() || !fullBodyFuncAnimSm.CheckPlayability()) return false;
|
||
|
||
RecallAllSpinAreas();
|
||
//StopSpinAreaCharge(true);
|
||
RefreshPrimaryTarget();
|
||
_spinAreaUpgradeCount = StellarRingQuickcasterSpinAreaUpgradeLevel;
|
||
if (PlayReleaseSpinArea()) return true;
|
||
|
||
_spinAreaUpgradeCount = 0;
|
||
return false;
|
||
}
|
||
|
||
private List<Enemy> GetCubicScatterIndexerTargets(int targetCount, float radius = DefaultTargetingRadius)
|
||
{
|
||
List<Enemy> targets = GetCurrentTargets(targetCount, radius);
|
||
if (targets.Count <= 0 || targets.Count >= targetCount)
|
||
{
|
||
return targets;
|
||
}
|
||
|
||
List<Enemy> scatteredTargets = new List<Enemy>(targetCount);
|
||
scatteredTargets.AddRange(targets);
|
||
while (scatteredTargets.Count < targetCount)
|
||
{
|
||
targets.TryGetRandom(out Enemy randomTarget);
|
||
scatteredTargets.Add(randomTarget);
|
||
}
|
||
|
||
return scatteredTargets;
|
||
}
|
||
|
||
private int GetBaseFusionStack(AttackUnit attackUnit)
|
||
{
|
||
return attackUnit.GetSubmodule<AttackUnit.ParameterSubmodule>()?.GetParameter<int>("Buff_Fusion_Stack") ?? 0;
|
||
}
|
||
|
||
private int ApplyFusionChargeCore(int fusionStack, string vfxName)
|
||
{
|
||
if (vfxName is not ("NormalBolt" or "CubicBolt")) return fusionStack;
|
||
return fusionStack + FusionChargeCoreExtraFusionStack;
|
||
}
|
||
|
||
private void ApplySigilBreakWedge(Fusion fusion)
|
||
{
|
||
if (fusion?.attachedCharacter == null) return;
|
||
|
||
Attack.Context context = new Attack.Context(
|
||
player,
|
||
fusion.attachedCharacter,
|
||
nameof(SigilBreakWedge),
|
||
fusion.attachedCharacter.CenterPosition);
|
||
Attack.Value value = new Attack.Value(
|
||
false, 0f,
|
||
SigilBreakWedgeExtraStanceDepletion,
|
||
Attack.Type.Energy,
|
||
breakthroughType: Breakthrough.Type.None);
|
||
Attack.Result result = new Attack.Result(context, value);
|
||
fusion.attachedCharacter.TakeDepletion(result);
|
||
}
|
||
|
||
private void ApplyBlackHoleDisplacer(NormalArea area, AttackUnit attackUnit)
|
||
{
|
||
area.SetAttackSubmodule<NormalArea>(attackUnit)
|
||
.SetTimeSubmodule<NormalArea>(3f, 0.1f, 0.9f)
|
||
.SetHitSubmodule<NormalArea>(0.1f, 8)
|
||
.SetLinearDirectionMoveModule<NormalArea>(player.transform.forward, 25f, -50f, false, false, false);
|
||
}
|
||
|
||
private void TryGenerateMissileSeparation(
|
||
Projectile sourceProjectile,
|
||
string vfxName,
|
||
AttackUnit attackUnit,
|
||
CharacterBase hitCharacter,
|
||
Vector3 hitPosition,
|
||
float speed)
|
||
{
|
||
if (sourceProjectile.tags.Contains("Separation")) return;
|
||
|
||
List<Enemy> nearbyEnemies = CombatManager.EnemySm.Query(25f)
|
||
.From(hitPosition)
|
||
.Exclude(hitCharacter as Enemy)
|
||
.Candidates();
|
||
if (nearbyEnemies.Count <= 0) return;
|
||
|
||
Projectile separation = vfxData
|
||
.SpawnVFX(vfxName, player, hitPosition, Quaternion.identity)
|
||
.GetComponentInChildren<Projectile>();
|
||
nearbyEnemies.TryGetRandom(out Enemy randomTarget);
|
||
Vector3 separationDirection = (randomTarget.CenterPoint.position - hitPosition).normalized;
|
||
|
||
separation.Initialize(player, this, false, 1, Fraction.Enemy)
|
||
.SetAttackSubmodule<Projectile>(attackUnit)
|
||
.SetTimeSubmodule<Projectile>(10f)
|
||
.SetHitSubmodule<Projectile>()
|
||
.SetLinearDirectionMoveModule<Projectile>(separationDirection, speed, 5f);
|
||
separation.tags.Add("Separation");
|
||
separation.hitSm.AddCheckedObject(hitCharacter.gameObject);
|
||
separation.SetRaycastSubmodule<Projectile>(default, 0.25f, 0.5f);
|
||
}
|
||
}
|
||
}
|