241 lines
7.7 KiB
C#
241 lines
7.7 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; }
|
||
|
||
[Header("デバッグ設定")]
|
||
[SerializeField] private bool ignoreGaugeForDebug = true;
|
||
|
||
[Header("Codingモード用 入力設定")]
|
||
[SerializeField] private InputActionProperty zlButtonAction;
|
||
[SerializeField] private InputActionProperty zrButtonAction;
|
||
|
||
[Header("プレイヤー移動・操作制御用 入力設定")]
|
||
[SerializeField] private InputActionProperty moveAction;
|
||
[SerializeField] private InputActionProperty turnAction;
|
||
|
||
[Header("パズル制限時間設定")]
|
||
[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;
|
||
|
||
[Header("バフパラメータ設定")]
|
||
[Tooltip("攻撃力UP・防御力UPの持続時間 (秒)")]
|
||
[SerializeField] private float buffDuration = 10f;
|
||
[Tooltip("攻撃力UP時のダメージ倍率")]
|
||
[SerializeField] private float attackBuffMultiplier = 1.5f;
|
||
[Tooltip("防御力UP時の被ダメージ軽減率")]
|
||
[SerializeField] private float defenseBuffMultiplier = 0.5f;
|
||
[Tooltip("HP回復バフ発動時の回復量")]
|
||
[SerializeField] private float hpHealAmount = 30f;
|
||
|
||
private float attackBuffTimer = 0f;
|
||
private float defenseBuffTimer = 0f;
|
||
private bool isCodingMode = false;
|
||
|
||
public GameObject successEffectPrefab;
|
||
// エフェクトを出す位置(合体したブロックの少し上など)
|
||
public Transform effectSpawnPoint;
|
||
|
||
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 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>();
|
||
float zrVal = zrButtonAction.action.ReadValue<float>();
|
||
|
||
bool isBothHeld = zlVal > 0.5f && zrVal > 0.5f;
|
||
bool isAnyTriggered = zlButtonAction.action.triggered || zrButtonAction.action.triggered;
|
||
|
||
if (isBothHeld && isAnyTriggered)
|
||
{
|
||
if (!isCodingMode)
|
||
{
|
||
if (ignoreGaugeForDebug || currentGauge >= maxGauge)
|
||
{
|
||
StartCodingMode();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"⚠️ ゲージ不足のためCodingModeを開始できません。現在: {currentGauge} / 必要: {maxGauge}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
CancelCodingMode();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void StartCodingMode()
|
||
{
|
||
isCodingMode = true;
|
||
codingTimer = codingLimitDuration;
|
||
|
||
// 1. プレイヤーの移動制御をロック
|
||
DisableAction(moveAction);
|
||
DisableAction(turnAction);
|
||
|
||
// 2. パズルブロックの状態・位置を全リセット
|
||
PuzzleBlock.ResetAllBlocksInScene();
|
||
|
||
// 3. 敵のアニメーション・NavMeshを停止
|
||
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)
|
||
{
|
||
Instantiate(successEffectPrefab, effectSpawnPoint.position, effectSpawnPoint.rotation);
|
||
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;
|
||
}
|
||
} |