- HitBox 新增 OnBreakableHitConfirmed:命中 IBreakable 也发命中确认, 下劈打可破坏物同样弹跳;不走 OnHitConfirmed,灵力仍只来自敌人 - 新增 PogoBounceForce 配置(默认 15,略低于 JumpForce=18)+ PlayerMovement.PogoBounce(),弹跳高度独立可调、固定不可截断 - DownAttackState 增加 OnStateFixedUpdate:下劈期间保留完整空中 水平操控(含与 FallState 同款贴墙保护) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
105 lines
3.8 KiB
C#
105 lines
3.8 KiB
C#
using UnityEngine;
|
||
using BaseGames.Combat;
|
||
|
||
namespace BaseGames.Player.States
|
||
{
|
||
/// <summary>
|
||
/// 下劈(踩踏 Pogo)状态(架构 05_PlayerModule §2)。
|
||
/// 需解锁 AbilityType.DownSlash 才能进入;
|
||
/// 激活 HitBoxDown,着地或命中后弹跳。
|
||
/// </summary>
|
||
public class DownAttackState : PlayerStateBase
|
||
{
|
||
private bool _hasHitEnemy;
|
||
private bool _exited;
|
||
|
||
public DownAttackState(PlayerController owner) : base(owner) { }
|
||
|
||
public override void OnStateEnter()
|
||
{
|
||
_hasHitEnemy = false;
|
||
_exited = false;
|
||
|
||
if (Owner.Combat != null)
|
||
Owner.Combat.OnDownHitConfirmed += OnDownHitConfirmed;
|
||
|
||
var step = Owner.Weapon?.ActiveWeapon?.GetDirStep(AttackDirection.Down);
|
||
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.Down, s.hitBoxId));
|
||
events.Add(step.Value.hitBoxExit, () => Owner.Combat?.DisableAllWeaponHitBoxes());
|
||
}
|
||
else
|
||
{
|
||
Owner.Combat?.EnableWeaponHitBox(AttackDirection.Down);
|
||
OnClipEnd();
|
||
}
|
||
|
||
// 下劈为纯向下攻击:保持角色原有的自然下落,不额外施加向下俯冲位移
|
||
// (俯冲位移会让下劈手感变成下冲,命中弹跳逻辑见 OnDownHitConfirmed)
|
||
}
|
||
|
||
public override void OnStateExit()
|
||
{
|
||
_exited = true;
|
||
if (Owner.Combat != null)
|
||
Owner.Combat.OnDownHitConfirmed -= OnDownHitConfirmed;
|
||
Owner.Combat?.DisableAllWeaponHitBoxes();
|
||
}
|
||
|
||
private void OnDownHitConfirmed(BaseGames.Combat.DamageInfo _)
|
||
{
|
||
if (_hasHitEnemy) return;
|
||
_hasHitEnemy = true;
|
||
// Pogo 弹跳:命中后向上弹起(独立弹跳力,略矮于满跳),同时重置空中能力(等同落地效果)
|
||
Owner.ResetAirJumps();
|
||
Owner.GetState<DashState>()?.ResetDashCharge();
|
||
Move.PogoBounce();
|
||
}
|
||
|
||
public override void OnStateUpdate()
|
||
{
|
||
// 着地时回到 Idle / Run
|
||
if (Move.IsGrounded)
|
||
{
|
||
Owner.TransitionTo(Owner.GetState<IdleState>());
|
||
}
|
||
}
|
||
|
||
public override void OnStateFixedUpdate()
|
||
{
|
||
// 下劈期间保留完整空中水平操控(与 FallState 同款贴墙保护,防止压墙摩擦/卡角)
|
||
if (Mathf.Abs(Input.MoveInput.x) > 0.01f)
|
||
{
|
||
int inputDir = Input.MoveInput.x > 0 ? 1 : -1;
|
||
var wd = Owner.WallDetector;
|
||
bool currentFrameWall = inputDir > 0 ? Move.IsWallRight : Move.IsWallLeft;
|
||
if (currentFrameWall
|
||
|| (wd != null && (wd.IsTouchingWall && wd.WallDirection == inputDir
|
||
|| wd.HasPartialContact(inputDir))))
|
||
Move.ZeroHorizontalVelocity();
|
||
else
|
||
Move.Move(Input.MoveInput.x * Cfg.RunSpeed);
|
||
}
|
||
else
|
||
Move.ZeroHorizontalVelocity();
|
||
}
|
||
|
||
private void OnClipEnd()
|
||
{
|
||
if (_exited) return;
|
||
if (!Move.IsGrounded)
|
||
Owner.TransitionTo(Owner.GetState<FallState>());
|
||
else
|
||
Owner.TransitionTo(Owner.GetState<IdleState>());
|
||
}
|
||
}
|
||
}
|