using UnityEngine; using BaseGames.Combat; namespace BaseGames.Player.States { /// /// 空中攻击状态(架构 05_PlayerModule §2)。 /// HitBox 时间由 ComboStepConfig.hitBoxEnter/Exit 驱动;结束后按 recoveryTime 延迟取消窗口。 /// public class AirAttackState : PlayerStateBase { private float _recoveryEndTime; public AirAttackState(PlayerController owner) : base(owner) { } public override void OnStateEnter() { var step = Owner.Weapon?.ActiveWeapon?.GetDirStep(AttackDirection.Air); float spd = Stats?.AnimatorSpeedMultiplier ?? 1f; if (step?.clip?.Clip != null) { var animState = Anim.Play(step.Value.clip); animState.Speed *= spd; var events = animState.Events(this); events.OnEnd = OnClipEnd; var s = step.Value; events.Add(s.hitBoxEnter, () => Owner.Combat?.EnableWeaponHitBox(AttackDirection.Air, s.hitBoxId)); events.Add(s.hitBoxExit, () => Owner.Combat?.DisableAllWeaponHitBoxes()); } else { Owner.Combat?.EnableWeaponHitBox(AttackDirection.Air); OnClipEnd(); } } public override void OnStateExit() { Owner.Combat?.DisableAllWeaponHitBoxes(); Move?.SetCancelWindowOpen(false); } public override void OnStateUpdate() { if (Time.time >= _recoveryEndTime) Move.SetCancelWindowOpen(true); } private void OnClipEnd() { Owner.Combat?.DisableAllWeaponHitBoxes(); var step = Owner.Weapon?.ActiveWeapon?.GetDirStep(AttackDirection.Air); float spd = Stats?.AnimatorSpeedMultiplier ?? 1f; float recovery = (step?.recoveryTime ?? 0.05f) / spd; _recoveryEndTime = Time.time + recovery; Move.SetCancelWindowOpen(false); Owner.TransitionTo(Owner.GetState()); } } }