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();
}
}
}
}