using Cielonos.MainGame.Buffs.Character; using Cielonos.MainGame.Characters; using SLSUtilities.General; using UnityEngine; namespace Cielonos.MainGame { /// /// 脉冲力的方向计算模式。 /// public enum ImpulseForceMode { /// 使用预设的固定力矢量。 Custom, /// 沿攻击区域 forward 方向施加力(投射物常用)。 Dynamic, /// 沿攻击区域 forward 方向施加力,但在计算时将竖直分量忽略(仅在水平面内施加力,适合地面攻击)。 FlattenedDynamic, /// 从攻击区域中心向外推开目标。 Repulsion, /// 将目标拉向攻击区域中心。 Suction, } /// /// 攻击区域的脉冲子模块:配置并向命中目标施加击退/击飞力。 /// 采用单构造函数 + 链式 With* 方法进行配置。 /// public class ImpulseSubmodule : AttackAreaSubmoduleBase { private ImpulseForceMode forceMode; private Vector3 customForce; private float dynamicStrength; private float strengthXZ; private float strengthY; private bool isLaunch; private bool isParabolic; private float impulseDuration; private AnimationCurve impulseCurve; private bool applyStun; private float stunDuration; private float gravityMultiplier = 1f; private float gravityDuration; // ──────────────────────────────────────────────────────────────────── // Constructor // ──────────────────────────────────────────────────────────────────── /// /// 创建一个新的 ImpulseSubmodule 实例。 /// /// 所属的攻击区域。 /// 脉冲持续时间(秒)。 /// 速度衰减曲线。null 使用默认 EaseOut。 public ImpulseSubmodule(AttackAreaBase attackArea, float duration, AnimationCurve curve) : base(attackArea) { this.impulseDuration = duration; this.impulseCurve = curve; } // ──────────────────────────────────────────────────────────────────── // Chain Configuration // ──────────────────────────────────────────────────────────────────── /// /// 设置为斥力模式:从攻击区域中心向外推开目标。 /// public ImpulseSubmodule WithRepulsion(float strengthXZ, float strengthY = 0) { this.forceMode = ImpulseForceMode.Repulsion; this.strengthXZ = strengthXZ; this.strengthY = strengthY; return this; } /// /// 设置为吸力模式:将目标拉向攻击区域中心。 /// public ImpulseSubmodule WithSuction(float strengthXZ, float strengthY = 0) { this.forceMode = ImpulseForceMode.Suction; this.strengthXZ = strengthXZ; this.strengthY = strengthY; return this; } /// /// 设置为自定义力矢量模式。 /// public ImpulseSubmodule WithCustomForce(Vector3 force) { this.forceMode = ImpulseForceMode.Custom; this.customForce = force; return this; } /// /// 设置为动态力模式:沿攻击区域 forward 方向施加指定强度的力。 /// public ImpulseSubmodule WithDynamicForce(float strength, bool isFlattened = true) { this.forceMode = isFlattened ? ImpulseForceMode.FlattenedDynamic : ImpulseForceMode.Dynamic; this.dynamicStrength = strength; return this; } /// /// 标记为击飞:无视抗性,自动附加眩晕。 /// parabolic 为 true 时使用物理弧线(距离击飞),为 false 时使用曲线衰减(空战浮空)。 /// /// 竖直方向的初始击飞强度。 /// 是否使用抛物线物理。默认 true。 public ImpulseSubmodule WithLaunch(float strengthY, bool parabolic = true) { this.isLaunch = true; this.strengthY = strengthY; this.isParabolic = parabolic; return this; } /// /// 标记击退时附加眩晕(击飞始终自动眩晕,无需此方法)。 /// /// 眩晕持续时间(秒)。0 表示跟随脉冲持续时间。 public ImpulseSubmodule WithStun(float duration = 0f) { this.applyStun = true; this.stunDuration = duration; return this; } /// /// 设置命中后的重力修正。通过 VerticalMoveModification Buff 实现。 /// multiplier 小于 1 使目标浮空(空战连击),大于 1 使目标加速坠落(Finisher)。 /// 当 multiplier 大于 1 时,会先清除目标身上已有的浮空 Buff,确保坠落生效。 /// /// 重力缩放倍率。0 = 完全浮空,1 = 正常,大于 1 = 加速坠落。 /// 重力修正持续时间(秒)。 public ImpulseSubmodule WithGravityModifier(float multiplier, float duration) { this.gravityMultiplier = multiplier; this.gravityDuration = duration; return this; } // ──────────────────────────────────────────────────────────────────── // Force Calculation & Application // ──────────────────────────────────────────────────────────────────── /// /// 根据当前力模式计算施加给目标的最终力矢量。 /// public Vector3 GetFinalForce(CharacterBase target) { return forceMode switch { ImpulseForceMode.Repulsion => (target.centerPoint.position - attackArea.topParent.position).Flatten().normalized * strengthXZ + Vector3.up * strengthY, ImpulseForceMode.Suction => (attackArea.topParent.position - target.centerPoint.position).Flatten().normalized * strengthXZ + Vector3.up * strengthY, ImpulseForceMode.Dynamic => attackArea.topParent.forward * dynamicStrength, ImpulseForceMode.FlattenedDynamic => attackArea.topParent.forward.Flatten().normalized * dynamicStrength, _ => customForce, }; } /// /// 对目标角色施加脉冲力。自动区分 Automata 和玩家的处理路径。 /// public void ApplyImpulse(CharacterBase target) { Vector3 force = GetFinalForce(target); if (target.movementSc is AutomataLandMovementSubcontroller automataSc) { automataSc.ApplyHitImpact(force, isLaunch, isParabolic, impulseDuration, impulseCurve, applyStun, stunDuration, gravityMultiplier, gravityDuration); } else { target.movementSc.impulseSm.ApplyImpulse(force, isLaunch, impulseDuration, impulseCurve, isParabolic); ApplyGravityModifier(target); } } /// /// 对非 Automata 目标(玩家等)施加重力修正 Buff。 /// private void ApplyGravityModifier(CharacterBase target) { if (gravityDuration <= 0f) return; if (gravityMultiplier > 1f) { ClearExistingGravityModifier(target); } new VerticalMoveModification(gravityDuration, gravityMultiplier).Apply(target); } /// /// 清除目标身上已有的 VerticalMoveModification Buff(Finisher 坠落前调用)。 /// private static void ClearExistingGravityModifier(CharacterBase target) { if (target.buffSm.TryGetBuff(out var existingBuff)) { existingBuff.Remove(); } } } }