using System.Collections; using System.Collections.Generic; using UnityEngine; using RPGCreationKit.Player; using RPGCreationKit.CellsSystem; using TMPro; 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; [Space(5)] [Header("\tLockpicking References")] [SerializeField] private GameObject lockpickingUI; [SerializeField] private RectTransform PickSprite; [SerializeField] private Transform LockPickUI; [SerializeField] public Item LockPick; [SerializeField] private Animator PadLock; [SerializeField] private TextMeshProUGUI PicksLeft; [SerializeField] private SpinVert SV; [SerializeField] private List ThingsToHide; [Space(5)] [Header("\tAudio")] [SerializeField] private AudioSource audioSource; [Space(5)] [SerializeField] private AudioClip pickAttempt; [SerializeField] private AudioClip pickBroke; [SerializeField] private AudioClip pickSuccess; [SerializeField] private AudioClip LockUnlocking; 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) { SV.ResetRotation(); PicksLeft.text = Inventory.PlayerInventory.GetItemCount(LockPick).ToString(); if (_door.lockLevel == DoorLockLevel.Impossible) return; if (!Inventory.PlayerInventory.HasItem(LockPick.ItemID)) return; shouldDisableControls = _shouldDisableControls; curDoor = _door; angle = 0f; target = 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; } RckPlayer.instance.input.SwitchCurrentActionMap("LockpickingUI"); lockpickingUI.SetActive(true); RckPlayer.instance.isPickingLock = true; for (int i = 0; i < ThingsToHide.Count; i++) ThingsToHide[i].SetActive(false); 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((Random.Range(-distance, distance) / 90f) * 10f, -10, 10)); Vector3 temp = LockPickUI.transform.rotation.eulerAngles; temp.x = 170 + Mathf.Clamp((Random.Range(-distance, distance) / 90f) * 10f, -10, 10); temp.y = angle; temp.z = 270f; LockPickUI.rotation = Quaternion.Euler(temp); //LockPickUI.rotation = Quaternion.Euler(angle, 90 + , 180); 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, 10, 170); //PickSprite.rotation = Quaternion.Euler(0, 0, angle); //LockPickUI.rotation = Quaternion.Euler(angle, 90, 180); Vector3 temp = LockPickUI.transform.rotation.eulerAngles; temp.x = 170f; temp.y = angle; temp.z = 270f; LockPickUI.rotation = Quaternion.Euler(temp); 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! StartCoroutine(UnlockLock()); return; } if (durability <= 0) // Breaks Pick. Lets make the pick in 2 pieces and animate a break { Inventory.PlayerInventory.RemoveItem(LockPick.ItemID, 1); PicksLeft.text = Inventory.PlayerInventory.GetItemCount(LockPick).ToString(); if (audioSource != null) audioSource.PlayOneShot(pickBroke); if (Inventory.PlayerInventory.GetItemCount(LockPick) < 1) StopPicking(); } else { isShaking = true; shakeTime = 1f; if(audioSource != null) audioSource.PlayOneShot(pickAttempt); } } public void CheatUnlock() { StartCoroutine(UnlockLock()); } IEnumerator UnlockLock() { curDoor.UnlockDoor(); SV.StartSpinning(); if (audioSource != null) audioSource.PlayOneShot(LockUnlocking); yield return new WaitForSecondsRealtime(1.5f); StopPicking(); } public void StopPicking() { for (int i = 0; i < ThingsToHide.Count; i++) ThingsToHide[i].SetActive(true); lockpickingUI.SetActive(false); isShaking = false; RckPlayer.instance.isPickingLock = false; if (shouldDisableControls) RckPlayer.instance.EnableDisableControls(true); curDoor = null; RckPlayer.instance.input.SwitchCurrentActionMap("Player"); } } }