using UnityEngine;
using System.Linq;
using Animancer;
using BaseGames.Core.Events;
using BaseGames.Input;
using BaseGames.Combat;
using BaseGames.Parry;
using BaseGames.Skills;
namespace BaseGames.Player.States
{
///
/// 玩家主控制器(协调器)。位于 Player/States/ 程序集,以便引用所有具体状态类型。
/// 实现 IDamageable + IPoiseSource(架构 06_CombatModule §13)。
/// 依赖注入:同节点组件由 RequireComponent + Awake 自动获取;跨节点引用通过 [SerializeField] 绑定。
///
[DefaultExecutionOrder(-100)]
[RequireComponent(typeof(InputBuffer))]
[RequireComponent(typeof(PlayerMovement))]
[RequireComponent(typeof(PlayerStats))]
[RequireComponent(typeof(AnimancerComponent))]
public class PlayerController : MonoBehaviour, IDamageable, IPoiseSource
{
// ── 同节点组件(由 RequireComponent 保证存在,Awake 中自动获取)─────
private PlayerMovement _movement;
private PlayerStats _stats;
private AnimancerComponent _animancer;
// ── 配置 SO ───────────────────────────────────────────────────────────
[Header("配置")]
[SerializeField] private PlayerMovementConfigSO _movementConfig;
[SerializeField] private PlayerAnimationConfigSO _animConfig;
[SerializeField] private InputReaderSO _inputReader;
[SerializeField] private PlayerStatsSO _statsConfig;
[SerializeField] private FormConfigSO _formConfig;
// ── 战斗组件 ──────────────────────────────────────────────────────────
[Header("战斗")]
[SerializeField] private PlayerCombat _combat;
[SerializeField] private FormController _formController;
[SerializeField] private WeaponManager _weaponManager;
[SerializeField] private SkillManager _skillManager;
[SerializeField] private SpringSystem _springSystem;
[SerializeField] private ParrySystem _parrySystem;
[SerializeField] private HurtBox _hurtBox;
[SerializeField] private ShieldComponent _shield;
[SerializeField] private PlayerWallDetector _wallDetector;
// ── 事件频道 ──────────────────────────────────────────────────────────
[Header("事件频道")]
[SerializeField] private VoidEventChannelSO _onPlayerDied;
[SerializeField] private IntEventChannelSO _onHPChanged; ///
/// Start() 时广播玩家 Transform(EnemyBase / ProjectileManager 等订阅此频道)。
/// 替代每个敌人在 Awake 中独立 FindWithTag 的 O(n) 全场景扫描。
///
[SerializeField] private TransformEventChannelSO _onPlayerSpawned;
// ── 运行时 ────────────────────────────────────────────────────────────
private InputBuffer _inputBuffer;
private bool _missingDependencyLogged;
private bool _dependenciesReady;
#if UNITY_EDITOR
[Header("调试")]
[SerializeField] private bool _debugValidateTransitions = true;
#endif
// Overlay Layer(Layer 1):供 SpringState / SoulSkill 等叠加层动画使用
// Base Layer(Layer 0):移动/攻击/受伤/死亡等全身状态动画
private AnimancerLayer _overlayLayer;
// ── 状态实例 ──────────────────────────────────────────────────────────
private PlayerStateBase _currentState;
private readonly System.Collections.Generic.Dictionary _states = new();
// ── IDamageable 实现 ──────────────────────────────────────────────────
public bool IsInvincible => _stats != null && _stats.IsInvincible;
public int Defense => 0;
public void TakeDamage(DamageInfo info)
{
if (_stats == null) return;
_stats.TakeDamage(info.FinalDamage);
// 当前状态标记为无敌(如冲刺)则跳过受击硬直
if (_currentState?.IsInvincible == true) return;
if (_stats.IsAlive)
{
GetState()?.Initialize(info);
TransitionTo(GetState());
}
else
{
TransitionTo(GetState());
_onPlayerDied?.Raise();
}
}
// ── IPoiseSource 实现(架构 06_CombatModule §13)─────────────────────
///
/// 玩家不拥有霸体,始终返回 。
/// 设计决策:类似 Hollow Knight,玩家依靠走位和弹反规避伤害,而非硬吃。
/// 若未来需要临时霸体(如特定技能动作),请通过独立的覆盖标记实现,
/// 而非在此处引入状态,以保持接口语义清晰。
///
public PoiseLevel GetCurrentPoiseLevel() => PoiseLevel.None;
// ── 公开属性(供状态类访问)──────────────────────────────────────────
public PlayerMovement Movement => _movement;
public PlayerStats Stats => _stats;
public AnimancerComponent Animancer => _animancer;
public PlayerMovementConfigSO MovConfig => _movementConfig;
public PlayerAnimationConfigSO AnimConfig => _animConfig;
public InputReaderSO Input => _inputReader;
public InputBuffer Buffer => _inputBuffer;
public PlayerCombat Combat => _combat;
public FormController Form => _formController;
public WeaponManager Weapon => _weaponManager;
public SkillManager Skill => _skillManager;
public SpringSystem Spring => _springSystem;
public ParrySystem Parry => _parrySystem;
public HurtBox HurtBox => _hurtBox;
public ShieldComponent Shield => _shield;
public PlayerWallDetector WallDetector => _wallDetector;
public bool IsGrounded => _movement != null && _movement.IsGrounded;
public int FacingDirection => _movement != null ? _movement.FacingDirection : 1;
// ── Overlay Layer API(供 SpringState / SoulSkill 等叠加动画使用)─────
///
/// 在 Overlay Layer(Layer 1)播放动画,叠加于当前 Base Layer 动画之上。
/// 适用于灵泉使用、魂技能等需要与移动动画并行的上半身动作。
///
public AnimancerState PlayOnOverlay(AnimationClip clip)
=> _overlayLayer?.Play(clip);
/// 停止 Overlay Layer 动画,淡出回 Base Layer。
public void StopOverlay(float fadeDuration = 0.1f)
=> _overlayLayer?.StartFade(0f, fadeDuration);
// ── Unity Lifecycle ───────────────────────────────────────────────────
private void Awake()
{
Debug.Assert(_movementConfig != null, "[PlayerController] _movementConfig 未赋值,请在 Inspector 中指定 PlayerMovementConfigSO。", this);
ResolveDependencies();
// 初始化 Animancer 双层动画:Layer 0 = Base(全身状态),Layer 1 = Overlay(叠加层)
if (_animancer != null)
{
// 确保 Layer 1 存在;AnimancerComponent 默认只有 Layer 0
while (_animancer.Layers.Count <= 1)
_animancer.Layers.Add();
_overlayLayer = _animancer.Layers[1];
}
// 注入 HurtBox 依赖
if (_hurtBox != null)
{
if (_shield != null) _hurtBox.SetShieldable(_shield);
if (_parrySystem != null) _hurtBox.SetParrySystem(_parrySystem);
_hurtBox.SetPoiseSource(this);
}
InitializeStates();
// 订阅 ParrySystem C# 事件
if (_parrySystem != null)
{
_parrySystem.OnParryActivated += OnParryActivated;
_parrySystem.OnParryConsumed += OnParryConsumedHandler;
}
}
private void OnDestroy()
{
if (_parrySystem != null)
{
_parrySystem.OnParryActivated -= OnParryActivated;
_parrySystem.OnParryConsumed -= OnParryConsumedHandler;
}
}
/// 弹反输入激活时由 ParrySystem 触发 → 转换到 ParryState。
private void OnParryActivated()
{
if (_states.ContainsKey(typeof(ParryState)))
TransitionTo(GetState());
}
/// 弹反命中成功时由 ParrySystem 触发 → 发放灵力并恢复护盾。
private void OnParryConsumedHandler(BaseGames.Parry.ParryInfo info)
{
_stats?.AddSoul(info.SoulGained);
_shield?.OnParrySuccess();
}
private void Start()
{
if (!HasRequiredStateDependencies())
return;
// 广播玩家 Transform:EnemyBase / ProjectileManager 等订阅者将通过事件接收引用
// (必须在 Start 中调用,确保所有 Awake/OnEnable 订阅已就绪)
_onPlayerSpawned?.Raise(transform);
TransitionTo(GetState());
}
private void Update()
{
if (!HasRequiredStateDependencies())
return;
// 冲刺冷却计时
GetState()?.TickCooldown(Time.deltaTime);
_currentState?.OnStateUpdate();
}
private void FixedUpdate()
{
_currentState?.OnStateFixedUpdate();
}
private void LateUpdate()
{
_movement?.UpdateFacing();
}
// ── 状态机 ────────────────────────────────────────────────────────────
public void TransitionTo(PlayerStateBase newState)
{
#if UNITY_EDITOR
if (_debugValidateTransitions && _currentState != null && newState != null)
{
var allowed = _currentState.ValidTransitions;
if (allowed.Count > 0 && !allowed.Contains(newState.GetType()))
Debug.LogWarning(
$"[PlayerController] 非预期转换: {_currentState.GetType().Name} → {newState.GetType().Name}",
this);
}
#endif
_currentState?.OnStateExit();
_currentState = newState;
_currentState?.OnStateEnter();
}
private void InitializeStates()
{
_states[typeof(IdleState)] = new IdleState(this);
_states[typeof(RunState)] = new RunState(this);
_states[typeof(JumpState)] = new JumpState(this);
_states[typeof(FallState)] = new FallState(this);
_states[typeof(AttackState)] = new AttackState(this);
_states[typeof(DashState)] = new DashState(this);
_states[typeof(AerialDashState)] = new AerialDashState(this);
_states[typeof(WallSlideState)] = new WallSlideState(this);
_states[typeof(WallJumpState)] = new WallJumpState(this);
_states[typeof(AirAttackState)] = new AirAttackState(this);
_states[typeof(DownAttackState)] = new DownAttackState(this);
_states[typeof(UpAttackState)] = new UpAttackState(this);
_states[typeof(HurtState)] = new HurtState(this);
_states[typeof(DeadState)] = new DeadState(this);
_states[typeof(SpringState)] = new SpringState(this);
_states[typeof(ParryState)] = new ParryState(this);
_states[typeof(SwimState)] = new SwimState(this);
}
///
/// 按类型获取状态实例。未注册时返回 null(供可选状态调用方安全使用)。
///
public T GetState() where T : PlayerStateBase
=> _states.TryGetValue(typeof(T), out var s) ? (T)s : null;
private void ResolveDependencies()
{
if (_movement == null)
_movement = GetComponent();
if (_stats == null)
_stats = GetComponent();
if (_animancer == null)
_animancer = GetComponent();
if (_inputBuffer == null)
_inputBuffer = GetComponent();
// _inputReader 必须在 Inspector 中赋值(SerializeField)
// 已移除 Resources.FindObjectsOfTypeAll 全资产扫描回退
}
private bool HasRequiredStateDependencies()
{
if (_dependenciesReady) return true;
bool ok = _movement != null && _animancer != null && _inputBuffer != null && _inputReader != null;
if (ok)
{
_dependenciesReady = true;
_missingDependencyLogged = false;
return true;
}
if (!_missingDependencyLogged)
{
Debug.LogError($"[PlayerController] Missing required dependencies. " +
$"Movement={(_movement != null ? "OK" : "NULL")}, " +
$"Animancer={(_animancer != null ? "OK" : "NULL")}, " +
$"InputBuffer={(_inputBuffer != null ? "OK" : "NULL")}, " +
$"InputReader={(_inputReader != null ? "OK" : "NULL")}");
_missingDependencyLogged = true;
}
return false;
}
// ── 状态访问器 ────────────────────────────────────────────────────────
// 使用 GetState() 按类型获取任意状态实例,不再暴露具名属性。
}
}