using System.Collections.Generic;
using NightclubArcadia.Player;
using StarterAssets;
using UnityEngine;
namespace NightclubArcadia.UI
{
///
/// Ref-counted freeze of the player's ThirdPersonController. Multiple
/// independent holders (dialogue, menu) can Acquire/Release; the controller
/// stays disabled until the last holder releases.
///
public sealed class PlayerControlLock : MonoBehaviour
{
readonly HashSet holders = new HashSet();
ThirdPersonController playerController;
StarterAssetsInputs playerInputs;
Animator playerAnimator;
PlayerMotionArbiter motionArbiter;
static readonly int AnimIDSpeed = Animator.StringToHash("Speed");
static readonly int AnimIDMotionSpeed = Animator.StringToHash("MotionSpeed");
public bool IsLocked => holders.Count > 0;
void Awake()
{
playerController = GetComponent();
playerInputs = GetComponent();
playerAnimator = GetComponent();
motionArbiter = GetComponent();
}
public void Acquire(object reason)
{
if (reason == null)
{
throw new System.ArgumentNullException(nameof(reason));
}
var wasLocked = IsLocked;
holders.Add(reason);
if (!wasLocked && IsLocked)
{
ApplyLock(true);
}
}
public void Release(object reason)
{
if (reason == null)
{
return;
}
var wasLocked = IsLocked;
holders.Remove(reason);
if (wasLocked && !IsLocked)
{
ApplyLock(false);
}
}
void ApplyLock(bool locked)
{
if (playerController == null)
{
return;
}
if (locked)
{
// Clear pending input and the locomotion blend before freezing
// the controller. Disabling it mid-stride otherwise leaves
// Speed at its last value, and the character keeps running on
// the spot for the whole conversation.
if (playerInputs != null)
{
playerInputs.MoveInput(Vector2.zero);
playerInputs.LookInput(Vector2.zero);
playerInputs.SprintInput(false);
playerInputs.JumpInput(false);
}
if (playerAnimator != null)
{
playerAnimator.SetFloat(AnimIDSpeed, 0f);
playerAnimator.SetFloat(AnimIDMotionSpeed, 0f);
}
motionArbiter?.ResetState();
}
// cursor state hook — see plan §3.4
playerController.enabled = !locked;
}
}
}