Firstborn/Assets/Scripts/LockpickingManager.cs
Schaken-Mods b8ab71969a Finished lockpicking, tied it to the Skills system
Finished lockpicking. tied it to the Attributes system. when you pick a lock you gain dexterity, the higher your dexterity, the easier it is to pick locks.
2023-05-05 22:02:18 -05:00

333 lines
9.1 KiB
C#

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;
private LootingPoint curLootingPoint;
[Space(8)]
[Header("\tLockpicking References")]
[SerializeField] private GameObject lockpickingUI;
[SerializeField] private Transform LockPickUI;
[SerializeField] private GameObject LockPickBack;
[SerializeField] public Item LockPick;
[SerializeField] private GameObject PadLock;
[SerializeField] private GameObject DoorLock;
[SerializeField] private TextMeshProUGUI PicksLeft;
[SerializeField] private SpinVert PadlockSV;
[SerializeField] private SpinVert DoorSV;
[SerializeField] private List<GameObject> ThingsToHide;
[Space(8)]
[Header("\tAudio")]
[SerializeField] private AudioSource audioSource;
[Space(8)]
[SerializeField] private AudioClip pickAttempt;
[SerializeField] private AudioClip pickBroke;
[SerializeField] private AudioClip pickSuccess;
[SerializeField] private AudioClip LockUnlocking;
[Header("\tStarting Positions")]
[SerializeField] private Vector3 PickAngle;
[SerializeField] private Vector3 OrigPos;
[SerializeField] private float MinAngle = -70f;
[SerializeField] private float MaxAngle = 70f;
private bool isShaking = false;
private bool isBroken = false;
private float shakeTime = 0f;
private float angle = 0f;
private float angleX = 0f;
private float target = 0f;
private float acceptableRange = 0f;
private float direction = 0f;
private bool isDoor = false;
private SpinVert RealSV;
// 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;
void Start() {
PickAngle = LockPickUI.transform.rotation.eulerAngles;
}
public void StartPicking(Door _door)
{
if (_door.lockLevel == DoorLockLevel.Impossible) return;
curDoor = _door;
isDoor = true;
RealSV = DoorSV;
switch (_door.lockLevel)
{
case DoorLockLevel.VeryEasy:
acceptableRange = 50f; //25
break;
case DoorLockLevel.Easy:
acceptableRange = 38f; //20
break;
case DoorLockLevel.Medium:
acceptableRange = 26f; //13
break;
case DoorLockLevel.Hard:
acceptableRange = 15f; //8
break;
case DoorLockLevel.VeryHard:
acceptableRange = 3f; //3
break;
}
Begin();
}
public void StartPicking(LootingPoint _LootingPoint)
{
if (_LootingPoint.lockLevel == ContainerLockLevel.Impossible) return;
curLootingPoint = _LootingPoint;
isDoor = false;
RealSV = PadlockSV;
switch (_LootingPoint.lockLevel)
{
case ContainerLockLevel.VeryEasy:
acceptableRange = 50f; //25
break;
case ContainerLockLevel.Easy:
acceptableRange = 38f; //20
break;
case ContainerLockLevel.Medium:
acceptableRange = 26f; //13
break;
case ContainerLockLevel.Hard:
acceptableRange = 15f; //8
break;
case ContainerLockLevel.VeryHard:
acceptableRange = 3f; //3
break;
}
Begin();
}
private void Begin() {
acceptableRange = (acceptableRange + EntityAttributes.PlayerAttributes.attributes.Dexterity);
Debug.Log("acceptableRange: "+acceptableRange);
PickAngle = LockPickUI.transform.rotation.eulerAngles;
OrigPos = PickAngle;
MinAngle = PickAngle.y - 70;
MaxAngle = PickAngle.y + 70;
RealSV.ResetRotation();
PicksLeft.text = Inventory.PlayerInventory.GetItemCount(LockPick).ToString();
if (!Inventory.PlayerInventory.HasItem(LockPick.ItemID))
return;
angle = PickAngle.y;
target = Random.Range(MinAngle, MaxAngle);
if (durability <= 0)
durability = 5; // 5 attempts per Lockpick
RckPlayer.instance.input.SwitchCurrentActionMap("LockpickingUI");
DoorLock.SetActive(isDoor);
PadLock.SetActive(!isDoor);
lockpickingUI.SetActive(true);
RckPlayer.instance.isPickingLock = true;
for (int i = 0; i < ThingsToHide.Count; i++)
ThingsToHide[i].SetActive(false);
}
void FixedUpdate()
{
if (isShaking)
{
float distance = Mathf.Abs(angle - target);
PickAngle = LockPickUI.transform.rotation.eulerAngles;
PickAngle.x = Mathf.Clamp((Random.Range(-distance, distance) / 90f) * 10f, -10, 10);
PickAngle.y = angle;
LockPickUI.rotation = Quaternion.Euler(PickAngle);
shakeTime -= Time.fixedDeltaTime;
if (shakeTime <= 0) {
isShaking = false;
PickAngle = LockPickUI.transform.rotation.eulerAngles;
PickAngle.x = angleX;
LockPickUI.rotation = Quaternion.Euler(PickAngle);
}
}
if (isBroken) {
//this is where I build an animation making it look like it is broke
shakeTime -= Time.fixedDeltaTime; // May as well use this as the breaking animation time
if (shakeTime <= 0) { // show it broken, then vanish for 1 second, and come back new. need to figure out how to reset rotation...
if (LockPickUI.gameObject.activeSelf) {
LockPickUI.gameObject.SetActive(false);
shakeTime = 1f;
Vector3 TempV = LockPickUI.transform.rotation.eulerAngles; // Reset Angle
//TempV.x = TempV.x - 90f;
LockPickBack.transform.rotation = Quaternion.Euler(TempV);
} else {
isBroken = false;
//LockPickBack.SetActive(true);
LockPickUI.gameObject.SetActive(true);
LockPickUI.rotation = Quaternion.Euler(OrigPos);
angle = OrigPos.y;
durability = 5; // Resets the picks health
}
}
}
}
void Update()
{
if (!RckPlayer.instance.isPickingLock)
return;
if (isShaking)
return;
if (isBroken)
return;
direction = -RckPlayer.instance.input.currentActionMap.FindAction("Move").ReadValue<Vector2>().x;
angle += direction * Time.deltaTime * 16.0f;
angle = Mathf.Clamp(angle, MinAngle, MaxAngle);
LockPickUI.rotation = Quaternion.Euler(PickAngle.x, angle, PickAngle.z);
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
Debug.Log("Angle: "+angle+"; Min: "+(target - acceptableRange)+"; Max: "+(target + acceptableRange));
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();
isBroken = true; // this makes Lateupdate fire, which fires off Attempt();
shakeTime = 2f; // Making this 0 so it just skips the shaking. We need an animation here instead (New Function)
angleX = PickAngle.x;
Vector3 TempV = LockPickBack.transform.rotation.eulerAngles; // Reset Angle
TempV.x = TempV.x + 45f;
LockPickBack.transform.rotation = Quaternion.Euler(TempV);
// LockPickBack.SetActive(false);
}
else
{
isShaking = true;
shakeTime = 1f;
if(audioSource != null)
audioSource.PlayOneShot(pickAttempt);
}
}
public void CheatUnlock() {
StartCoroutine(UnlockLock());
}
IEnumerator UnlockLock() {
EntityAttributes.PlayerAttributes.attributes.DexterityPoints += 1;
int A = EntityAttributes.PlayerAttributes.attributes.DexterityPoints;
int B = EntityAttributes.PlayerAttributes.attributes.Dexterity;
while (A >= (B*3)) {
EntityAttributes.PlayerAttributes.attributes.Dexterity += 1;
EntityAttributes.PlayerAttributes.attributes.DexterityPoints = (A-(B*3));
A = EntityAttributes.PlayerAttributes.attributes.DexterityPoints;
B = EntityAttributes.PlayerAttributes.attributes.Dexterity;
}
if (isDoor) {
curDoor.UnlockDoor();
} else {
curLootingPoint.UnlockContainer();
}
RealSV.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;
curDoor = null;
curLootingPoint = null;
RckPlayer.instance.input.SwitchCurrentActionMap("Player");
LockPickUI.rotation = Quaternion.Euler(OrigPos);
}
}
}