180 lines
6.1 KiB
C#
180 lines
6.1 KiB
C#
using UnityEngine;
|
||
using UnityEngine.InputSystem;
|
||
using UnityEngine.AI;
|
||
using System.Collections.Generic;
|
||
|
||
public class PlayerStatusManager : MonoBehaviour
|
||
{
|
||
public static PlayerStatusManager Instance { get; private set; }
|
||
|
||
[SerializeField] private InputActionProperty zlButtonAction;
|
||
[SerializeField] private InputActionProperty zrButtonAction;
|
||
|
||
[SerializeField] private InputActionProperty moveAction;
|
||
[SerializeField] private InputActionProperty turnAction;
|
||
[SerializeField] private float codingLimitDuration = 15f;
|
||
private float codingTimer = 0f;
|
||
|
||
[SerializeField] private float maxGauge = 100f;
|
||
[SerializeField] private float currentGauge = 0f;
|
||
|
||
[SerializeField] private GameObject codingModeUI;
|
||
[SerializeField] private PuzzleGridBoard puzzleBoard; // 盤面参照
|
||
|
||
[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<Animator> pausedAnimators = new List<Animator>();
|
||
private List<NavMeshAgent> pausedAgents = new List<NavMeshAgent>();
|
||
|
||
#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 Update()
|
||
{
|
||
CheckComboInput();
|
||
|
||
if (!isCodingMode)
|
||
{
|
||
UpdateBuffTimers();
|
||
}
|
||
else
|
||
{
|
||
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;
|
||
|
||
bool zlPressed = zlButtonAction.action.triggered && zlButtonAction.action.ReadValue<float>() > 0.5f;
|
||
bool zrPressed = zrButtonAction.action.triggered && zrButtonAction.action.ReadValue<float>() > 0.5f;
|
||
|
||
bool isComboTriggered = (zlPressed && zrButtonAction.action.ReadValue<float>() > 0.5f) ||
|
||
(zrPressed && zlButtonAction.action.ReadValue<float>() > 0.5f);
|
||
|
||
if (isComboTriggered)
|
||
{
|
||
if (!isCodingMode && currentGauge >= maxGauge)
|
||
{
|
||
StartCodingMode();
|
||
}
|
||
else if (isCodingMode)
|
||
{
|
||
CancelCodingMode(); // 手動キャンセルはゲージ維持
|
||
}
|
||
}
|
||
}
|
||
|
||
private void StartCodingMode()
|
||
{
|
||
isCodingMode = true;
|
||
codingTimer = codingLimitDuration; // タイマーリセット
|
||
|
||
if (puzzleBoard != null) puzzleBoard.ClearBoard();
|
||
if (moveAction.action != null) moveAction.action.Disable();
|
||
if (turnAction.action != null) turnAction.action.Disable();
|
||
|
||
foreach (var anim in FindObjectsByType<Animator>(FindObjectsSortMode.None))
|
||
{
|
||
if (anim == null || anim.gameObject == this.gameObject || anim.CompareTag("Player")) continue;
|
||
anim.speed = 0f;
|
||
pausedAnimators.Add(anim);
|
||
}
|
||
|
||
foreach (var agent in FindObjectsByType<NavMeshAgent>(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();
|
||
|
||
if (moveAction.action != null) moveAction.action.Enable();
|
||
if (turnAction.action != null) turnAction.action.Enable();
|
||
|
||
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;
|
||
}
|
||
} |