using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.AI;
using System.Collections.Generic;
///
/// プレイヤーの共通ゲージ、時間停止(Codingモード)、UI、および各種バフの制限時間を管理するクラス
///
public class PlayerStatusManager : MonoBehaviour
{
public static PlayerStatusManager Instance { get; private set; }
[Header("デバッグ設定")]
[Tooltip("チェックを入れると、ゲージが溜まっていなくてもZLZRでCodingModeを開けます(テスト用)")]
[SerializeField] private bool ignoreGaugeForDebug = true;
[Header("Codingモード用 入力設定")]
[SerializeField] private InputActionProperty zlButtonAction;
[SerializeField] private InputActionProperty zrButtonAction;
[Header("プレイヤー移動・操作制御用 入力設定")]
[Tooltip("プレイヤーの移動入力(例: LeftHand Move)のアクションを指定してください")]
[SerializeField] private InputActionProperty moveAction;
[Tooltip("プレイヤーの視点回転入力(例: RightHand Turn)があれば指定してください(任意)")]
[SerializeField] private InputActionProperty turnAction;
[Header("パズル制限時間設定")]
[Tooltip("CodingModeパズルの制限時間(秒)")]
[SerializeField] private float codingLimitDuration = 15f;
private float codingTimer = 0f;
[Header("ゲージ設定")]
[SerializeField] private float maxGauge = 100f;
[SerializeField] private float currentGauge = 0f;
[Header("表示UI設定")]
[SerializeField] private GameObject codingModeUI;
[SerializeField] private PuzzleGridBoard puzzleBoard; // 盤面参照
[Header("バフパラメータ設定")]
[SerializeField] private float buffDuration = 10f;
[SerializeField] private float attackBuffMultiplier = 1.5f;
[SerializeField] private float defenseBuffMultiplier = 0.5f;
[SerializeField] private float hpHealAmount = 30f;
private float attackBuffTimer = 0f;
private float defenseBuffTimer = 0f;
private bool isCodingMode = false;
private List pausedAnimators = new List();
private List pausedAgents = new List();
#region プロパティ
public bool IsAttackBuffActive => attackBuffTimer > 0f;
public bool IsDefenseBuffActive => defenseBuffTimer > 0f;
public float CurrentAttackMultiplier => IsAttackBuffActive ? attackBuffMultiplier : 1.0f;
public float CurrentDefenseMultiplier => IsDefenseBuffActive ? defenseBuffMultiplier : 1.0f;
#endregion
private void Awake()
{
if (Instance == null) { Instance = this; }
else { Destroy(gameObject); }
}
private void OnEnable()
{
EnableAction(zlButtonAction);
EnableAction(zrButtonAction);
EnableAction(moveAction);
EnableAction(turnAction);
}
private void OnDisable()
{
DisableAction(zlButtonAction);
DisableAction(zrButtonAction);
DisableAction(moveAction);
DisableAction(turnAction);
}
private void EnableAction(InputActionProperty property)
{
if (property.action != null) property.action.Enable();
}
private void DisableAction(InputActionProperty property)
{
if (property.action != null) property.action.Disable();
}
private void Start()
{
if (codingModeUI != null) codingModeUI.SetActive(false);
}
private void Update()
{
CheckComboInput();
if (!isCodingMode)
{
UpdateBuffTimers();
}
else
{
// CodingMode中の制限時間カウントダウン
codingTimer -= Time.deltaTime;
if (codingTimer <= 0f)
{
FailCodingModeByTimeout();
}
}
}
public void AddGauge(float amount)
{
if (isCodingMode) return;
currentGauge += amount;
currentGauge = Mathf.Clamp(currentGauge, 0f, maxGauge);
}
private void CheckComboInput()
{
if (zlButtonAction.action == null || zrButtonAction.action == null) return;
// 入力値の読み取り
float zlVal = zlButtonAction.action.ReadValue();
float zrVal = zrButtonAction.action.ReadValue();
bool zlPressed = zlButtonAction.action.triggered || zlVal > 0.5f;
bool zrPressed = zrButtonAction.action.triggered || zrVal > 0.5f;
// 両方のトリガーが引かれているか
bool isBothHeld = zlVal > 0.5f && zrVal > 0.5f;
bool isAnyTriggered = zlButtonAction.action.triggered || zrButtonAction.action.triggered;
if (isBothHeld && isAnyTriggered)
{
if (!isCodingMode)
{
// ゲージチェック(デバッグフラグがONならゲージ無視で起動)
if (ignoreGaugeForDebug || currentGauge >= maxGauge)
{
StartCodingMode();
}
else
{
Debug.LogWarning($"⚠️ ゲージが足りないためCodingModeを開けません。現在: {currentGauge} / 必要: {maxGauge}");
}
}
else
{
// CodingMode中に再度同時押し ➔ キャンセルして無消費で復帰
CancelCodingMode();
}
}
}
private void StartCodingMode()
{
isCodingMode = true;
codingTimer = codingLimitDuration;
if (puzzleBoard != null) puzzleBoard.ClearBoard();
DisableAction(moveAction);
DisableAction(turnAction);
// 敵のアニメーション・NavMesh停止
foreach (var anim in FindObjectsByType(FindObjectsSortMode.None))
{
if (anim == null || anim.gameObject == this.gameObject || anim.CompareTag("Player")) continue;
anim.speed = 0f;
pausedAnimators.Add(anim);
}
foreach (var agent in FindObjectsByType(FindObjectsSortMode.None))
{
if (agent == null || !agent.enabled || !agent.gameObject.activeInHierarchy || agent.CompareTag("Player")) continue;
if (!agent.isStopped) { agent.isStopped = true; pausedAgents.Add(agent); }
}
if (codingModeUI != null) codingModeUI.SetActive(true);
Debug.Log($"⏳ Codingモード開始(パズル制限時間: {codingLimitDuration}秒)");
}
public void ApplyBuffsAndResume(string buff1, string buff2)
{
ActivateBuffByName(buff1);
ActivateBuffByName(buff2);
ResumeWorldState(consumeGauge: true);
Debug.Log("🎉 パズル成功!バフを適用して再開。");
}
private void FailCodingModeByTimeout()
{
ResumeWorldState(consumeGauge: true);
Debug.Log("💀 時間切れ! Codingモード失敗(バフなし・ゲージ消費)。");
}
public void CancelCodingMode()
{
ResumeWorldState(consumeGauge: false);
Debug.Log("↩️ Codingモード手動キャンセル。");
}
private void ResumeWorldState(bool consumeGauge)
{
foreach (var anim in pausedAnimators) { if (anim != null) anim.speed = 1f; }
pausedAnimators.Clear();
foreach (var agent in pausedAgents) { if (agent != null && agent.enabled) agent.isStopped = false; }
pausedAgents.Clear();
EnableAction(moveAction);
EnableAction(turnAction);
isCodingMode = false;
if (codingModeUI != null) codingModeUI.SetActive(false);
if (consumeGauge) currentGauge = 0f;
}
private void ActivateBuffByName(string buffName)
{
switch (buffName)
{
case "AttackUp": attackBuffTimer = buffDuration; break;
case "DefenseUp": defenseBuffTimer = buffDuration; break;
case "Heal": ExecuteHeal(); break;
}
}
private void ExecuteHeal()
{
Debug.Log($"💚 HP回復バフ発動! 回復量: {hpHealAmount}");
}
private void UpdateBuffTimers()
{
if (attackBuffTimer > 0f) attackBuffTimer -= Time.deltaTime;
if (defenseBuffTimer > 0f) defenseBuffTimer -= Time.deltaTime;
}
}