using UnityEngine; using RPGCreationKit.Player; using RPGCreationKit.CellsSystem; namespace RPGCreationKit { public class LockpickingManager : MonoBehaviour { public static LockpickingManager instance; private void Awake() { if (instance == null) instance = this; else Debug.LogError("Anomaly detected with the singleton pattern of 'LockpickingManager', are you using multiple LockpickingManager?"); } private Door curDoor; public string LockpickItemID; [Space(5)] [Header("Book References")] public GameObject backgroundUI; public GameObject lockpickingUI; public RectTransform PickSprite; [Space(5)] [Header("Audio")] public AudioSource audioSource; [Space(5)] public AudioClip pickAttempt; public AudioClip pickBroke; public AudioClip pickSuccess; private bool isShaking = false; private float shakeTime = 0f; private bool shouldDisableControls = false; private float angle = 0f; private float target = 0f; private float acceptableRange = 0f; private float direction = 0f; // Durability is Static, and Held between lockpicking sessions, so that they cant exit then return to lockpicking to reset durability private static int durability = 0; public void StartPicking(Door _door, bool _shouldDisableControls) { if (_door.lockLevel == DoorLockLevel.Impossible) return; if (!Inventory.PlayerInventory.HasItem(LockpickItemID)) return; shouldDisableControls = _shouldDisableControls; curDoor = _door; angle = 0f; target = UnityEngine.Random.Range(-140, 141); if (durability <= 0) durability = 5; // 5 attempts per Lockpick switch (_door.lockLevel) { case DoorLockLevel.VeryEasy: acceptableRange = 25f; break; case DoorLockLevel.Easy: acceptableRange = 20f; break; case DoorLockLevel.Medium: acceptableRange = 13f; break; case DoorLockLevel.Hard: acceptableRange = 8f; break; case DoorLockLevel.VeryHard: acceptableRange = 3f; break; } backgroundUI.SetActive(true); RckPlayer.instance.input.SwitchCurrentActionMap("LockpickingUI"); lockpickingUI.SetActive(true); RckPlayer.instance.isPickingLock = true; if (shouldDisableControls) RckPlayer.instance.EnableDisableControls(false); } void FixedUpdate() { if (isShaking) { float distance = Mathf.Abs(angle - target); PickSprite.rotation = Quaternion.Euler(0, 0, angle + Mathf.Clamp((UnityEngine.Random.Range(-distance, distance) / 90f) * 10f, -10, 10)); shakeTime -= Time.fixedDeltaTime; if (shakeTime <= 0) isShaking = false; } } void Update() { if (!RckPlayer.instance.isPickingLock) return; if (isShaking) return; direction = -RckPlayer.instance.input.currentActionMap.FindAction("Move").ReadValue().x; angle += direction * Time.deltaTime * 16.0f; angle = Mathf.Clamp(angle, -90, 90); PickSprite.rotation = Quaternion.Euler(0, 0, angle); if (RckPlayer.instance.input.currentActionMap.FindAction("Attempt").triggered) { Attempt(); } else if (RckPlayer.instance.input.currentActionMap.FindAction("Close").triggered) { StopPicking(); } } void Attempt() { if (!RckPlayer.instance.isPickingLock) return; if (durability <= 0) return; durability--; // Check if successfull attempt if(angle > target - acceptableRange && angle < target + acceptableRange) { // Success! curDoor.UnlockDoor(); if (audioSource != null) audioSource.PlayOneShot(pickBroke); StopPicking(); return; } if (durability <= 0) { Inventory.PlayerInventory.RemoveItem(LockpickItemID, 1); if (audioSource != null) audioSource.PlayOneShot(pickBroke); StopPicking(); } else { isShaking = true; shakeTime = 1f; if(audioSource != null) audioSource.PlayOneShot(pickAttempt); } } public void StopPicking() { backgroundUI.SetActive(false); lockpickingUI.SetActive(false); isShaking = false; RckPlayer.instance.isPickingLock = false; if (shouldDisableControls) RckPlayer.instance.EnableDisableControls(true); curDoor = null; RckPlayer.instance.input.SwitchCurrentActionMap("Player"); } } }