Upload from upload_mods.ps1

This commit is contained in:
Nathaniel Cosford
2025-06-04 16:44:53 +09:30
commit f1fbbe67bb
1722 changed files with 165268 additions and 0 deletions

View File

@@ -0,0 +1,531 @@
using UnityEngine.Events;
/*
* Thank you for using my Lockpicking asset! I hope it works great in your game. You can extend it to suit your game by
* manipulating some of the code below. For instance, if your player can have a various level of "lockpicking" skill,
* you may consider multiplying the value of lockGive by their skill, so that a higher skilled player would find it
* easier to open a lock.
*
* Enjoy!
*/
namespace Lockpicking
{
//[ExecuteInEditMode]
[RequireComponent(typeof(LockEmissive))]
public class Cipher : MonoBehaviour
{
[Header("Speed Settings")]
[Tooltip("Maximum shake distance per shake change.")]
[SerializeField]
private float maxShake = 0.5f;
[Tooltip("Amount of time between shake changes when shaking.")]
[SerializeField]
private float shakeTime = 0.1f;
[Tooltip("Speed of the wheel when turning.")]
public float turnSpeed = 180f;
[Header("Lock Setup")]
[Tooltip("Number of symbols on the wheel. Should be spaced evenly.")]
public int symbolCount = 18;
[Tooltip("How close do we have to be to perfectly aligned for the placement of a wheel to count?")]
public float closeEnough = 3f;
[Tooltip("If true, wheels will \"snap\" into a new random spot on setup. If false, they will rotate to those spots.")]
public bool quickReset;
[Tooltip("If true, the active wheel will be highlighted using the emissive map of the material.")]
public bool highlightActiveWheel = true;
[Tooltip("If true, wheels will move to the closest spot when the player stops input movement.")]
public bool moveToClosestSpot;
[Header("Lock Details")]
[Tooltip("When true, the lock has been opened.")]
public bool isOpen;
[Tooltip("When true, the lock will reset itself on awake. Set this to false if you are choosing a specific combination.")]
public bool resetOnAwake;
[Header("Animation Trigger Strings")] public string openTrigger = "Open";
public string closeTrigger = "Close";
// Audio Settings
[Range(0f, 1f)] public float clickVolumeMin = 0.1f;
[Range(0f, 1f)] public float clickVolumeMax = 0.4f;
[Range(0f, 1f)] public float squeekVolumeMin = 0.1f;
[Range(0f, 1f)] public float squeekVolumeMax = 0.4f;
[Range(0, 100)] public int squeekChance = 50;
[Range(0f, 15f)] public float squeekRate = 3.5f;
public float[] unlockAngle; // All the unlock angles for each wheel
public float[] startAngle; // All the starting angles for each wheel
public float[] turnedDistance; // amount each wheel has been turned
public float[] turnedDistancePrev; // amount each wheel has been turned
public bool[] isMoving; // Records whether the wheels are moving
public bool playAudioOnSetup = true;
[Header("Plumbing")] public GameObject[] wheels;
public LocksetAudio audioClick;
public LocksetAudio audioSqueek;
public LocksetAudio audioJiggle;
public LocksetAudio audioJiggle2;
public LocksetAudio audioJiggle3;
public LocksetAudio audioOpen;
// Events
private readonly UnityEvent lockOpen = new UnityEvent();
// Private variables
private int _activeWheel;
private int _closeTrigger;
private LocksetAudio _locksetAudio;
// Private animation hashes
private int _openTrigger;
private Animator animator;
private float getReadyPostReadyTimer = 0.3f;
private bool isReady; // WHen true, player can interact
private bool isShaking; // When true, the lock is shaking (trying to be opened but in the wrong combination)
private LockEmissive lockEmissive;
private Vector3 preshake; // Saves the pre-shake angles
private float shakeTimer; // Counter for the shake Time
// private float _speed;
private float squeekTimer;
public bool VisualizeSolution { get; set; }
public bool VisualizeStart { get; set; }
public float ActiveWheelStart
{
get => startAngle[ActiveWheel()];
set => startAngle[ActiveWheel()] = value;
}
public float ActiveWheelSolution
{
get => unlockAngle[ActiveWheel()];
set => unlockAngle[ActiveWheel()] = value;
}
private void Awake()
{
squeekTimer = squeekRate;
_locksetAudio = GetComponent<LocksetAudio>();
animator = GetComponent<Animator>();
lockEmissive = GetComponent<LockEmissive>();
if (!highlightActiveWheel)
lockEmissive.highlightRenderer = null;
_openTrigger = Animator.StringToHash(openTrigger);
_closeTrigger = Animator.StringToHash(closeTrigger);
if (resetOnAwake) ResetLock();
}
private void Update()
{
// Do actions to get ready, if we are not ready
if (!isReady)
{
GetReady();
if (playAudioOnSetup)
DoAudio();
return;
}
if (getReadyPostReadyTimer > 0)
getReadyPostReadyTimer -= Time.deltaTime;
if (moveToClosestSpot)
MoveToClosestSpot();
ResetMovement();
if (highlightActiveWheel) lockEmissive.SetHighlightRenderer(wheels[_activeWheel].GetComponent<Renderer>());
DoAudio();
}
private void OnValidate()
{
#if UNITY_EDITOR
if (unlockAngle.Length != wheels.Length )
{
Debug.Log("Updating Lengths");
unlockAngle = new float[wheels.Length];
startAngle = new float[wheels.Length];
turnedDistance = new float[wheels.Length];
isMoving = new bool[wheels.Length];
}
if (_visualizeSolution)
SetRotationToSolution();
else if (_visualizeStart)
SetRotationToStart();
else
SetRotationToZero();
for (int i = 0; i < wheels.Length; i++)
{
unlockAngle[i] = ClosestSpot(unlockAngle[i]);
}
#endif
}
public int ActiveWheel()
{
return _activeWheel;
}
public void EditorOnValidate()
{
#if UNITY_EDITOR
EditorUtility.SetDirty(this);
#endif
OnValidate();
}
private void SetRotationToSolution()
{
for (var i = 0; i < wheels.Length; i++)
{
var eulerAngles = wheels[i].transform.localEulerAngles;
eulerAngles.x = unlockAngle[i];
wheels[i].transform.localEulerAngles = eulerAngles;
}
}
private void SetRotationToStart()
{
for (var i = 0; i < wheels.Length; i++)
{
var eulerAngles = wheels[i].transform.localEulerAngles;
eulerAngles.x = startAngle[i];
wheels[i].transform.localEulerAngles = eulerAngles;
}
}
private void SetRotationToZero()
{
for (var i = 0; i < wheels.Length; i++) wheels[i].transform.localEulerAngles = new Vector3();
}
public float DistanceLeft(int i)
{
if (turnedDistance.Length >= i + 1)
{
var left = unlockAngle[i] - turnedDistance[i];
if (left < -350)
left += 360;
if (left > 350)
left -= 360;
return left;
}
return 9999;
}
private void DoAudio()
{
for (var i = 0; i < turnedDistance.Length; i++)
{
var turnSpeed = 0f;
if (turnedDistance[i] != turnedDistancePrev[i])
{
if (getReadyPostReadyTimer <= 0 || playAudioOnSetup)
{
if (audioSqueek)
// Squeek
if (squeekRate > 0)
{
squeekTimer -= Time.deltaTime;
if (squeekTimer <= 0)
{
if (UnityEngine.Random.Range(0, 100) < squeekChance)
{
//Log.Out("Cipher-DoAudio PLAY SOUND: audioSqueek");
audioSqueek.PlayAudioClip(UnityEngine.Random.Range(squeekVolumeMin, squeekVolumeMax));
}
squeekTimer = squeekRate;
}
}
if (audioClick)
{
// Clicks
turnSpeed = turnedDistance[i] - turnedDistancePrev[i];
var turnedMod = turnedDistance[i] % (360 / symbolCount);
var turnedModPrev = turnedDistancePrev[i] % (360 / symbolCount);
if ((turnSpeed > 0 || turnSpeed < -350) && (turnedMod < turnedModPrev || turnedMod > 0 && turnedModPrev < 0))
{
//Log.Out("Cipher-DoAudio PLAY SOUND: audioClick 1");
audioClick.PlayAudioClip(UnityEngine.Random.Range(clickVolumeMin, clickVolumeMax));
}
else if ((turnSpeed < 0 || turnSpeed > 350) && (turnedMod > turnedModPrev || turnedMod < 0 && turnedModPrev > 0))
{
//Log.Out("Cipher-DoAudio PLAY SOUND: audioClick 2");
audioClick.PlayAudioClip(UnityEngine.Random.Range(clickVolumeMin, clickVolumeMax));
}
else if (turnedMod == 0)
{
//Log.Out("Cipher-DoAudio PLAY SOUND: audioClick 3");
audioClick.PlayAudioClip(UnityEngine.Random.Range(clickVolumeMin, clickVolumeMax));
}
}
}
turnedDistancePrev[i] = turnedDistance[i];
}
}
}
public int NextWheelIndex()
{
return _activeWheel + 1 < wheels.Length ? _activeWheel + 1 : 0;
}
public int PrevWheelIndex()
{
return _activeWheel - 1 < 0 ? wheels.Length - 1 : _activeWheel - 1;
}
public void SelectWheel(int value)
{
_activeWheel = value < wheels.Length && value >= 0 ? value : 0;
}
public void ResetMovement()
{
for (var i = 0; i < wheels.Length; i++) isMoving[i] = false;
}
public void MoveToClosestSpot()
{
for (var i = 0; i < wheels.Length; i++)
// Only run this if the wheel is not moving (i.e. being moved by the player)
if (!isMoving[i])
{
if (turnedDistance[i] < 0) turnedDistance[i] += 360;
/*
float smallestDistance = 360f;
float closestRotation = 0f;
for (int d = 0; d < 360 / symbolCount; d++)
{
float diff = d * (360 / symbolCount);
if (Mathf.Abs(Mathf.Abs(turnedDistance[i]) - diff) < smallestDistance)
{
smallestDistance = Mathf.Abs(Mathf.Abs(turnedDistance[i]) - diff);
closestRotation = diff;
}
}
MoveTowards(i, closestRotation);
*/
MoveTowards(i, ClosestSpot(Mathf.Abs(turnedDistance[i])));
}
}
private float ClosestSpot(float value)
{
var smallestDistance = 360f;
var closestRotation = 0f;
for (var d = -360; d < 360 / symbolCount; d++)
{
float diff = d * (360 / symbolCount);
if (Mathf.Abs(value - diff) < smallestDistance)
{
smallestDistance = Mathf.Abs(value - diff);
closestRotation = diff;
}
}
return closestRotation;
}
public void TryOpen()
{
if (!isShaking)
preshake = transform.localEulerAngles;
if (!isOpen)
{
for (var i = 0; i < wheels.Length; i++)
if (Mathf.Abs(DistanceLeft(i)) > closeEnough)
{
Shake();
return;
}
isOpen = true;
animator.SetTrigger(_openTrigger);
//Log.Out("Lockpicking-TryOpen PLAY SOUND: audioPadlockOpen");
audioOpen.PlayOnce();
// Invoke the event for any other scripts that are listening
lockOpen.Invoke();
}
}
public void StopShaking()
{
transform.localEulerAngles = preshake;
isShaking = false;
if (audioJiggle)
{
audioJiggle.StopLoop();
if (audioJiggle2 != null)
audioJiggle2.StopLoop();
if (audioJiggle3 != null)
audioJiggle3.StopLoop();
}
}
private void Shake()
{
if (!isShaking)
isShaking = true;
shakeTimer -= Time.deltaTime;
if (shakeTimer <= 0)
{
// Start with the current values
var newShake = preshake;
// Add some modification
//newShake.z += UnityEngine.Random.Range(-maxShake, maxShake);
newShake.x += UnityEngine.Random.Range(-maxShake, maxShake);
newShake.y += UnityEngine.Random.Range(-maxShake, maxShake);
// Set the value + modification
transform.localEulerAngles = newShake;
// Reset the timer
shakeTimer = shakeTime;
}
if (audioJiggle)
{
audioJiggle.PlayLoop();
if (audioJiggle2 != null)
audioJiggle2.PlayLoop();
if (audioJiggle3 != null)
audioJiggle3.PlayLoop();
}
}
public void GetReady()
{
var readyCount = 0;
for (var i = 0; i < wheels.Length; i++)
{
var speed = 1;
var distanceLeft = startAngle[i] - turnedDistance[i];
if (VisualizeSolution) distanceLeft = unlockAngle[i] - turnedDistance[i];
if (distanceLeft < 0) speed = -1;
var turnAmount = speed * turnSpeed * Time.deltaTime;
if (Mathf.Abs(distanceLeft) < Mathf.Abs(turnAmount))
{
turnAmount = distanceLeft;
readyCount++;
}
if (quickReset || VisualizeSolution)
{
turnAmount = distanceLeft;
readyCount++;
}
SetTurnedDistance(i, turnAmount);
RotateWheel(wheels[i].transform, turnAmount);
}
if (readyCount == wheels.Length)
isReady = true;
}
public void MoveActiveWheel(int speed)
{
MoveWheel(_activeWheel, speed);
}
public void MoveWheel(int i, int speed, float destination = 999f)
{
if (isReady)
{
isMoving[i] = true; // Mark this wheel as currently moving
var turnAmount = speed * turnSpeed * Time.deltaTime;
if (destination != 999)
if (Mathf.Abs(destination - turnedDistance[i]) < Mathf.Abs(turnAmount))
turnAmount = destination - turnedDistance[i];
SetTurnedDistance(i, turnAmount);
RotateWheel(wheels[i].transform, turnAmount);
}
}
private void RotateWheel(Transform transform, float value)
{
transform.Rotate(value, 0.0f, 0.0f, Space.Self);
}
public void MoveTowards(int i, float closestRotation)
{
if (turnedDistance[i] > closestRotation)
MoveWheel(i, -1, closestRotation);
else
MoveWheel(i, 1, closestRotation);
}
public void SetTurnedDistance(int i, float distance)
{
turnedDistance[i] += distance;
if (turnedDistance[i] > 360)
turnedDistance[i] -= 360;
if (turnedDistance[i] < -360)
turnedDistance[i] += 360;
}
public void ResetLock()
{
Debug.Log("ResetLock");
isOpen = false;
isReady = false;
animator.SetTrigger(_closeTrigger);
// Shuffle each wheel
for (var i = 0; i < wheels.Length; i++)
{
unlockAngle[i] = RandomAngle();
startAngle[i] = RandomAngle();
}
}
private float RandomAngle()
{
return UnityEngine.Random.Range(0, symbolCount) * (360 / symbolCount) - 180;
}
}
}

View File

@@ -0,0 +1,73 @@
using Lockpicking;
using UnityEngine.Serialization;
public class CipherControls : MonoBehaviour
{
[FormerlySerializedAs("cypher")] public Cipher cipher;
// Update is called once per frame
private void Update()
{
if (cipher.gameObject.activeSelf)
InputControls();
}
private void InputControls()
{
if (Input.GetKeyDown(KeyCode.Tab))
{
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
cipher.SelectWheel(cipher.PrevWheelIndex());
else
cipher.SelectWheel(cipher.NextWheelIndex());
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
cipher.SelectWheel(cipher.PrevWheelIndex());
if (Input.GetKeyDown(KeyCode.RightArrow))
cipher.SelectWheel(cipher.NextWheelIndex());
if (Input.GetKey(KeyCode.UpArrow))
cipher.MoveActiveWheel(-1);
if (Input.GetKey(KeyCode.DownArrow))
cipher.MoveActiveWheel(1);
if (Input.GetKey(KeyCode.Q))
cipher.MoveWheel(0, -1);
if (Input.GetKey(KeyCode.A))
cipher.MoveWheel(0, 1);
if (Input.GetKey(KeyCode.W))
cipher.MoveWheel(1, -1);
if (Input.GetKey(KeyCode.S))
cipher.MoveWheel(1, 1);
if (Input.GetKey(KeyCode.E))
cipher.MoveWheel(2, -1);
if (Input.GetKey(KeyCode.D))
cipher.MoveWheel(2, 1);
if (Input.GetKey(KeyCode.R))
cipher.MoveWheel(3, -1);
if (Input.GetKey(KeyCode.F))
cipher.MoveWheel(3, 1);
if (Input.GetKey(KeyCode.T))
cipher.MoveWheel(4, -1);
if (Input.GetKey(KeyCode.G))
cipher.MoveWheel(4, 1);
if (Input.GetKey(KeyCode.Y))
cipher.MoveWheel(5, -1);
if (Input.GetKey(KeyCode.H))
cipher.MoveWheel(5, 1);
}
}

View File

@@ -0,0 +1,79 @@
//using UnityEngine;
//using UnityEngine.UI;
//using Lockpicking;
//using UnityEngine.Serialization;
//public class CipherDemoUI : MonoBehaviour
//{
// // Set up references to the Text objects
// public Text wheel1;
// public Text wheel2;
// public Text wheel3;
// public Text wheel4;
// public Text wheel5;
// public Text wheel6;
// public Cipher cipher;
// public Color highlightColor = new Color(255f,0f,171f,1f);
// void Start()
// {
//// ResetLock();
// }
// void Update()
// {
// DrawText();
// }
// private void DrawText()
// {
// if (Input.GetKey(KeyCode.O))
// {
// cipher.TryOpen();
// }
// if (Input.GetKeyUp(KeyCode.O))
// {
// cipher.StopShaking();
// }
// if (Mathf.Abs(cipher.DistanceLeft(0)) < cipher.closeEnough)
// wheel1.color = highlightColor;
// else
// wheel1.color = Color.white;
// if (Mathf.Abs(cipher.DistanceLeft(1)) < cipher.closeEnough)
// wheel2.color = highlightColor;
// else
// wheel2.color = Color.white;
// if (Mathf.Abs(cipher.DistanceLeft(2)) < cipher.closeEnough)
// wheel3.color = highlightColor;
// else
// wheel3.color = Color.white;
// if (Mathf.Abs(cipher.DistanceLeft(3)) < cipher.closeEnough)
// wheel4.color = highlightColor;
// else
// wheel4.color = Color.white;
// if (Mathf.Abs(cipher.DistanceLeft(4)) < cipher.closeEnough)
// wheel5.color = highlightColor;
// else
// wheel5.color = Color.white;
// if (Mathf.Abs(cipher.DistanceLeft(5)) < cipher.closeEnough)
// wheel6.color = highlightColor;
// else
// wheel6.color = Color.white;
// wheel1.text = "" + cipher.DistanceLeft(0);
// wheel2.text = "" + cipher.DistanceLeft(1);
// wheel3.text = "" + cipher.DistanceLeft(2);
// wheel4.text = "" + cipher.DistanceLeft(3);
// wheel5.text = "" + cipher.DistanceLeft(4);
// wheel6.text = "" + cipher.DistanceLeft(5);
// }
// public void ResetLock()
// {
// cipher.ResetLock();
// }
//}

View File

@@ -0,0 +1,773 @@
using UnityEngine.Events;
/*
* Thank you for using my Lockpicking asset! I hope it works great in your game. You can extend it to suit your game by
* manipulating some of the code below. For instance, if your player can have a various level of "lockpicking" skill,
* you may consider multiplying the value of lockGive by their skill, so that a higher skilled player would find it
* easier to open a lock.
*
* Enjoy!
*/
namespace Lockpicking
{
[RequireComponent(typeof(LockEmissive))]
public class Keyhole : MonoBehaviour
{
// 7 Days To Die stuff
public int NumLockPicks;
public EntityPlayer player;
public BlockValue blockValue;
[Header("Plumbing")] public GameObject keyhole; // The keyhole with lockpick A that turns the entire keyhole object to open it
public GameObject lockpickObject; // The lockpick that turns to match the secret lockAngle
public Animator lockpickAnimator; // Animator on the lockpick in the lockpickObject
public Animator _padlockAnimator;
public GameObject padlock1; // Link to the padlock 1 game object
public GameObject button;
public LocksetAudio audioTurnClick;
public LocksetAudio audioSqueek;
public LocksetAudio audioOpen;
public LocksetAudio audioJiggle;
public LocksetAudio audioJiggle2;
public LocksetAudio audioJiggle3;
public LocksetAudio audioPadlockOpen;
public LocksetAudio audioPadlockJiggle;
public LocksetAudio audioLockpickBreak;
public LocksetAudio audioLockpickEnter;
public LocksetAudio audioLockpickClick;
// Audio Settings
[Range(0f, 1f)] public float clickVolumeMin = 0.1f;
[Range(0f, 1f)] public float clickVolumeMax = 0.4f;
[Range(0, 100)] public int clickChance = 100;
[Range(0f, 15f)] public float clickRate = 10f;
[Range(0f, 1f)] public float squeekVolumeMin = 0.1f;
[Range(0f, 1f)] public float squeekVolumeMax = 0.4f;
[Range(0, 100)] public int squeekChance = 50;
[Range(0f, 360f)] public float squeekRate = 20f;
public bool buttonDown;
private LockEmissive _lockEmissive; // Link to the lockEmissive script on this object
private float _lockpickAnglePrev;
// Private variables
private float breakCounter; // Counter for taking a break after a broken lockpick
public float breakTimeCounter;
private bool isShaking; // Whether we are currently shaking or not
private Vector3 preshakeKeyhole; // Saves the pre-shake angles
private Vector3 preshakeLockpick; // Saves the pre-shake angles
private float shakeTimer; // Counter for the shake Time
private float squeekTimer;
private void Awake()
{
squeekTimer = squeekRate;
_pickAnglesDefault = LockpickAngles();
_lockEmissive = gameObject.GetComponent<LockEmissive>();
if (_lockEmissive == null)
gameObject.AddComponent<LockEmissive>();
if (padlock1 != null)
{
_padlockAnimator = padlock1.gameObject.GetComponent<Animator>();
if (_padlockAnimator == null)
_padlockAnimator = padlock1.gameObject.AddComponent<Animator>();
}
_closeTrigger = Animator.StringToHash(closeTrigger);
_openTrigger = Animator.StringToHash(openTrigger);
_lockpickBreakTrigger = Animator.StringToHash(lockPickBreakTrigger);
_lockpickInsertTrigger = Animator.StringToHash(lockPickInsertTrigger);
if (resetOnAwake)
ResetLock();
}
private void Update()
{
if (NumLockPicks > 0)
{
PassValuesToEmissiveScript();
if (BreakingForAnimation())
return;
HandlePlayerInput();
}
else
{
RefreshLockPicks();
}
}
private void OnEnable()
{
RefreshLockPicks();
ResetLock();
if (NumLockPicks > 0)
UpdateLockPicks(true);
else
UpdateLockPicks(false);
}
private void OnDisable()
{
NumLockPicks = 0;
}
private void OnValidate()
{
LockAngle = LockAngle;
LockGive = LockGive;
CloseDistance = CloseDistance;
_pickAngleMin = Mathf.Clamp(_pickAngleMin, minLockAngle, maxLockAngle);
_pickAngleMax = Mathf.Clamp(_pickAngleMax, minLockAngle, maxLockAngle);
minGiveAmount = Mathf.Clamp(minGiveAmount, 1f, 360f);
maxGiveAmount = Mathf.Clamp(maxGiveAmount, 1f, 360f);
minCloseDistance = Mathf.Clamp(minCloseDistance, 5f, 360f);
maxCloseDistance = Mathf.Clamp(maxCloseDistance, 5f, 360f);
}
public float BreakTimeCounter()
{
return breakTimeCounter;
}
public float LockPickAngle()
{
return GetAngle(LockpickAngles().z);
}
public float KeyholeAngle()
{
return GetAngle(KeyholeAngles().z);
}
public void EditorOnValidate()
{
#if UNITY_EDITOR
EditorUtility.SetDirty(this);
#endif
OnValidate();
}
private void UpdateLockPicks(bool enable)
{
// Hide the lock picks or show them.
keyhole.transform.FindInChilds("LockpickB (Turnable)").gameObject.SetActive(enable);
keyhole.transform.FindInChilds("LockpickA").gameObject.SetActive(enable);
}
private void RefreshLockPicks()
{
if (player == null)
return;
var uiforPlayer = LocalPlayerUI.GetUIForPlayer(player as EntityPlayerLocal);
var playerInventory = uiforPlayer.xui.PlayerInventory;
var item = ItemClass.GetItem("resourceLockPick");
if (item != null)
NumLockPicks = playerInventory.GetItemCount(item);
if (NumLockPicks > 0)
UpdateLockPicks(true);
else
UpdateLockPicks(false);
}
private void HandlePlayerInput()
{
if (_lockIsOpen) return;
if (openPressure > 0)
{
TryToTurnKeyhole();
}
else
{
StopShaking();
ReturnKeyholeToDefaultPosition();
TurnLockpick(turnSpeedLockpick * lockpickPressure);
}
}
private bool BreakingForAnimation()
{
if (breakCounter > 0f)
{
breakCounter -= Time.deltaTime;
ReturnKeyholeToDefaultPosition();
return true;
}
return false;
}
private void ReturnKeyholeToDefaultPosition()
{
TurnKeyhole(-returnSpeedKeyhole);
}
private void TryToTurnKeyhole()
{
if (LockCanTurn())
{
TurnKeyhole(turnSpeedKeyhole * openPressure);
if (KeyholeTurnValue() <= 0 && LockpickIsInPosition())
OpenLock();
}
else
{
Shake();
}
}
private void PassValuesToEmissiveScript()
{
_lockEmissive.breakpointValue = Mathf.Clamp(breakTimeCounter / breakTime, 0, 1);
_lockEmissive.successValue = Mathf.Clamp(KeyholeTurnValue(), 0, 1);
}
private bool LockpickIsInPosition()
{
return LockPickAngle() < _lockAngle + _lockGive && LockPickAngle() > _lockAngle - _lockGive;
}
private void Shake()
{
// If we are not already shaking, save the original rotations.
if (!isShaking)
{
if (audioPadlockJiggle && padlock1 != null && padlock1.activeSelf)
{
audioPadlockJiggle.PlayLoop();
}
else
{
if (audioJiggle)
audioJiggle.PlayLoop();
if (audioJiggle2 != null)
audioJiggle2.PlayLoop();
if (audioJiggle3 != null)
audioJiggle3.PlayLoop();
}
preshakeKeyhole = KeyholeAngles();
preshakeLockpick = LockpickAngles();
isShaking = true;
}
// Check breakTimeCounter to stop shaking at the right time
breakTimeCounter += Time.deltaTime;
//Log.Out($"Break Time Counter: {breakTimeCounter} Total BreakTime: {breakTime}");
if (breakTimeCounter > breakTime)
{
StopShaking();
BreakLockpick();
return;
}
shakeTimer -= Time.deltaTime;
if (shakeTimer <= 0)
{
// Start with the current values
var newShakeKeyhole = preshakeKeyhole;
var newShakeLockpick = preshakeLockpick;
// Add some modification
newShakeKeyhole.z += UnityEngine.Random.Range(-maxShake, maxShake);
newShakeLockpick.z += UnityEngine.Random.Range(-maxShake, maxShake);
// Set the value + modification
SetKeyholeAngles(newShakeKeyhole);
SetLockpickAngles(newShakeLockpick);
// Reset the timer
shakeTimer = shakeTime;
}
}
private void StopShaking()
{
if (isShaking)
{
if (audioPadlockJiggle && padlock1 != null && padlock1.activeSelf)
{
audioPadlockJiggle.StopLoop();
}
else if (audioJiggle)
{
audioJiggle.StopLoop();
if (audioJiggle2 != null)
audioJiggle2.StopLoop();
if (audioJiggle3 != null)
audioJiggle3.StopLoop();
}
SetKeyholeAngles(preshakeKeyhole);
SetLockpickAngles(preshakeLockpick);
isShaking = false;
}
}
private void SetKeyholeAngles(Vector3 value)
{
keyhole.transform.localEulerAngles = value;
}
private void SetLockpickAngles(Vector3 value)
{
lockpickObject.transform.localEulerAngles = value;
}
public void BreakLockpick()
{
//Log.Out("Lockpicking-BreakLockpick START");
if (audioLockpickBreak)
{
//Log.Out("Lockpicking-BreakLockpick PLAY SOUND: audioLockpickBreak");
//Log.Out("Lockpicking-BreakLockpick audioLockpickBreak.name: " + audioLockpickBreak.name);
//audioLockpickBreak.DelayPlay(1f);
audioLockpickBreak.PlayOnce();
}
breakCounter = breakPause; // Set so we can't do any actions for a short time
breakTimeCounter = 0f; // Reset the breakCounter
ResetLockpickPosition(); // Reset the lockpick position
lockpickAnimator.SetTrigger(_lockpickBreakTrigger); // Play the break animation
lockpickBroke.Invoke(); // Invoke this event in case other scripts are listening
/*if (audioLockpickEnter && audioLockpickEnter.isActiveAndEnabled)
{
Log.Out("Lockpicking-BreakLockpick PLAY SOUND: audioLockpickEnter");
audioLockpickEnter.DelayPlay(1f);
}*/
// Remove the broke pick lock.
if (player != null)
{
//Log.Out("Lockpicking-BreakLockpick REMOVE LOCK PICK");
var playerUI = (player as EntityPlayerLocal).PlayerUI;
var playerInventory = playerUI.xui.PlayerInventory;
var item = ItemClass.GetItem("resourceLockPick");
var itemStack = new ItemStack(item, 1);
playerInventory.RemoveItem(itemStack);
RefreshLockPicks();
}
if (NumLockPicks > 0)
{
//Log.Out("Lockpicking-BreakLockpick 1");
UpdateLockPicks(true);
}
else
{
//Log.Out("Lockpicking-BreakLockpick 2");
UpdateLockPicks(false);
}
}
/// <summary>
/// Call this when the lock is open successfully.
/// </summary>
public void OpenLock()
{
if (!_lockIsOpen)
{
if (audioPadlockOpen && padlock1 != null && padlock1.activeInHierarchy)
{
//Log.Out("Lockpicking-OpenLock PLAY SOUND: audioPadlockOpen");
audioPadlockOpen.PlayOnce();
if (_padlockAnimator != null)
_padlockAnimator.SetTrigger(_openTrigger);
}
else if (audioOpen)
{
//Log.Out("Lockpicking-OpenLock PLAY SOUND: audioOpen");
audioOpen.PlayOnce();
}
// Invoke the event for any other scripts that are listening
lockOpen.Invoke();
_lockIsOpen = true;
}
}
private void DoSqueekAudio(float speed)
{
if (audioSqueek)
if (squeekRate > 0)
{
squeekTimer -= Mathf.Abs(speed) * Time.deltaTime;
if (squeekTimer <= 0)
{
if (UnityEngine.Random.Range(0, 100) < squeekChance)
{
//Log.Out("Keyhole-DoSqueekAudio PLAY SOUND: audioSqueek");
audioSqueek.PlayAudioClip(UnityEngine.Random.Range(squeekVolumeMin, squeekVolumeMax));
}
squeekTimer = squeekRate;
}
}
}
private float GetAngle(float eulerAngle)
{
var angle = eulerAngle;
angle %= 360;
if (angle > 180)
angle -= 360;
return angle;
}
private void TurnLockpick(float speed)
{
// If we are at or outside of our max range, return
if (LockPickAngle() >= _pickAngleMax && speed > 0 || LockPickAngle() <= _pickAngleMin && speed < 0)
return;
// Set the new angle
var newAngle = new Vector3(LockpickAngles().x, LockpickAngles().y,
LockpickAngles().z + speed * Time.deltaTime);
SetLockpickAngles(newAngle);
DoClickAudio(speed, newAngle);
}
private void DoClickAudio(float speed, Vector3 newAngle)
{
var angleMod = newAngle.z % clickRate;
var prevMod = _lockpickAnglePrev % clickRate;
if (speed > 0 && angleMod < prevMod || speed < 0 && angleMod > prevMod)
if (audioTurnClick != null)
{
//Log.Out("Keyhole-DoClickAudio PLAY SOUND: audioTurnClick");
audioTurnClick.PlayAudioClip(UnityEngine.Random.Range(clickVolumeMin, clickVolumeMax));
}
_lockpickAnglePrev = newAngle.z;
}
private Vector3 LockpickAngles()
{
return lockpickObject.transform.localEulerAngles;
}
private void TurnKeyhole(float speed)
{
// If we are at or outside of our max range, return
if (KeyholeAngle() >= _keyholeAngleMax && speed > 0 || KeyholeAngle() <= _keyholeAngleDefault && speed < 0)
return;
// Set the new angle
SetKeyholeAngles(new Vector3(KeyholeAngles().x, KeyholeAngles().y, KeyholeAngles().z + speed * Time.deltaTime));
DoSqueekAudio(speed);
}
private Vector3 KeyholeAngles()
{
return keyhole.transform.localEulerAngles;
}
public float KeyholeTurnValue()
{
return (_keyholeAngleMax - KeyholeAngle()) / (_keyholeAngleMax - _keyholeAngleDefault);
}
public void SetLock(float newLockAngle, float newLockGive, float newCloseDistance)
{
_lockAngle = newLockAngle;
_lockGive = newLockGive;
_closeDistance = newCloseDistance;
if (audioLockpickEnter && audioLockpickEnter.isActiveAndEnabled)
{
//Log.Out("Lockpicking-BreakLockpick PLAY SOUND: audioLockpickEnter");
audioLockpickEnter.DelayPlay(0.7f);
}
ResetLockpickPosition();
lockpickAnimator.SetTrigger(_lockpickInsertTrigger); // Play the animation
}
public void SetLock(float lockAngleMin, float lockAngleMax, float lockGiveMin,
float lockGiveMax, float closeDistanceMin, float closeDistanceMax)
{
SetLock(UnityEngine.Random.Range(lockAngleMin, lockAngleMax),
UnityEngine.Random.Range(lockGiveMin, lockGiveMax),
UnityEngine.Random.Range(closeDistanceMin, closeDistanceMax));
}
public void ResetLock()
{
LockIsOpen = false;
ProgressionValue progressionValue = null;
var difficulty = 0;
var prevBreakTime = breakTime;
var prevMaxGive = maxGiveAmount;
var healthLeft = blockValue.Block.MaxDamage - blockValue.damage;
// Adjust the difficulty based on the lock damage
if (healthLeft <= 10000)
difficulty = 3;
if (healthLeft <= 2500)
difficulty = 2;
if (healthLeft <= 400)
difficulty = 1;
if (healthLeft <= 200)
difficulty = 0;
// give more time to avoid breaking pick locks.
if (player != null)
{
var secureBlock = Block.list[blockValue.type];
if (secureBlock != null)
{
if (secureBlock.Properties.Values.ContainsKey("LockPickDifficulty"))
difficulty = int.Parse(secureBlock.Properties.Values["LockPickDifficulty"]);
}
var maxGiveAmounts = "10,8,6,4".Split(','); //Configuration.GetPropertyValue("AdvancedLockpicking", "MaxGiveAmount").Split(',');
var breakTimes = "1.2,1.0,.8,.6".Split(','); //Configuration.GetPropertyValue("AdvancedLockpicking", "BreakTime").Split(',');
// Default values.
maxGiveAmount = 10f;
breakTime = 2f;
if (maxGiveAmounts.Length >= difficulty)
{
maxGiveAmount = StringParsers.ParseFloat(maxGiveAmounts[difficulty]);
breakTime = StringParsers.ParseFloat(breakTimes[difficulty]);
}
progressionValue = player.Progression.GetProgressionValue("perkLockPicking");
if (progressionValue is { Level: > 0 })
{
prevBreakTime = breakTime;
prevMaxGive = maxGiveAmount;
breakTime += (float)progressionValue.Level / 5;
maxGiveAmount += (float)progressionValue.Level * 2;
}
}
SetLock(minLockAngle, maxLockAngle,
minGiveAmount, maxGiveAmount,
minCloseDistance, maxCloseDistance);
if (GamePrefs.GetBool(EnumGamePrefs.DebugMenuEnabled))
{
var progression = " Progression: ";
progression = progressionValue != null ? $"{progression} Level {progressionValue.Level} BreakTime Before: {prevBreakTime} MaxGiveAmount Before: {prevMaxGive}" : $"{progression} N/A";
/*Log.Out("");
Log.Out("-------------------------------------------");
Log.Out($"Configured Lock Pick: Break Time: {breakTime} MaxGiveAmount: {maxGiveAmount} Lock Difficulty: {difficulty} Block Damage: {healthLeft} {progression} ");
Log.Out("Lock Angle: " + _lockAngle + " Give: " + _lockGive + " Close distance: " + _closeDistance);
Log.Out($"MinLockAngle: {minLockAngle} MaxLockAngle: {maxLockAngle} Min Give Amount: {minGiveAmount} Max Give Amount: {maxGiveAmount} Min Close distance: {minCloseDistance} Max Close Distance: {maxCloseDistance}");
Log.Out(" To Adjust, run console command lock 2 34");
Log.Out(" For breaktime of 2 and maxgive of 34");
Log.Out("-------------------------------------------");*/
}
RefreshLockPicks();
}
public void ResetLockpickPosition()
{
SetLockpickAngles(_pickAnglesDefault);
if (_padlockAnimator != null)
_padlockAnimator.SetTrigger(_closeTrigger);
}
public bool LockCanTurn()
{
return !(LockPickAngle() < GetAngle(_lockAngle) - _lockGive - _closeDistance * KeyholeTurnValue()) &&
!(LockPickAngle() > GetAngle(_lockAngle) + _lockGive + _closeDistance * KeyholeTurnValue());
}
public bool LockComplete()
{
if (!LockIsOpen)
return false;
if (padlock1 != null && padlock1.activeInHierarchy)
{
if (_padlockAnimator != null)
// If the padlock is fully animated
if (_padlockAnimator.GetCurrentAnimatorStateInfo(0).IsName("Padlock1Opened"))
return true;
}
else
{
return !audioOpen.isAudioPlaying();
}
return false;
}
#region ThirdParty
// Events
private readonly UnityEvent lockpickBroke = new UnityEvent();
private readonly UnityEvent lockOpen = new UnityEvent();
[Header("Player Input")] public float openPressure;
public float lockpickPressure;
[Header("Speed Settings")]
[Tooltip("Speed of the lockpick when input value is full.")]
[Range(1f, 720f)]
public float turnSpeedLockpick = 50f;
[Tooltip("Speed of the entire keyhole when input value is full.")]
[Range(1f, 720f)]
public float turnSpeedKeyhole = 50f;
[Tooltip("Speed at which the lock will return to normal when the input value is 0.")]
[Range(1f, 720f)]
public float returnSpeedKeyhole = 150f;
[Tooltip("Maximum shake distance per shake change.")]
[SerializeField]
private float maxShake = 0.5f;
[Tooltip("Amount of time between shake changes when shaking.")]
[SerializeField]
private float shakeTime = 0.1f;
[Header("Pick Settings")]
[Tooltip("Starting angle of the lock pick.")]
[SerializeField]
private Vector3 _pickAnglesDefault;
[Tooltip("Minimum angle the lock pick can travel to.")]
[SerializeField]
private float _pickAngleMin = -90f;
[Tooltip("Maximum angle the lock pick can travel to.")]
[SerializeField]
private float _pickAngleMax = 90f;
[Header("Keyhole Settings")]
[Tooltip("Starting angle of the keyhole.")]
[SerializeField]
private float _keyholeAngleDefault = 0f;
[Tooltip("Maximum angle of the keyhole. At this angle, the lock will open.")]
[SerializeField]
private float _keyholeAngleMax = 90f;
[Header("Lock Settings")]
[Tooltip("If true, lock details will be randomized on awake")]
public bool resetOnAwake = true;
[Tooltip("Minimum angle the lock can be set to.")]
[Range(0f, 180f)]
public float minLockAngle = -90f;
[Tooltip("Maximum angle the lock can be set to.")]
[Range(0f, 180f)]
public float maxLockAngle = 90f;
[Tooltip("Minimum distance (plus and minus) from the lock angle that the lock will open.")]
[Range(1f, 180f)]
public float minGiveAmount = 1f;
[Tooltip("Maximum distance (plus and minus) from the lock angle that the lock will open.")]
[Range(1f, 180f)]
public float maxGiveAmount = 30f;
[Tooltip("Minimum distance for the pick to be in for the lock will turn partially.")]
[Range(5f, 180f)]
public float minCloseDistance = 5f;
[Tooltip("Maximum distance for the pick to be in for the lock will turn partially.")]
[Range(5f, 180f)]
public float maxCloseDistance = 10f;
[Tooltip("Amount of time to ignore player input after a lock pick breaks.")]
[Range(0f, 5f)]
public float breakPause = 2f;
[Header("Lock Details")]
[Tooltip("True if the lock is already open (unlocked).")]
[SerializeField]
private bool _lockIsOpen;
public bool LockIsOpen
{
get => _lockIsOpen;
set => _lockIsOpen = value;
}
[Tooltip("The exact angle the lock is set to.")]
private float _lockAngle;
public float LockAngle
{
get => _lockAngle;
set => _lockAngle = Mathf.Clamp(value, minLockAngle, maxLockAngle);
}
[Tooltip("The distance to/from the LockAngle the lock pick needs to be in for the lock to open successfully.")]
[SerializeField]
private float _lockGive;
public float LockGive
{
get => _lockGive;
set => _lockGive = Mathf.Clamp(value, 1, maxGiveAmount);
}
[Tooltip("If the lock pick is within this distance to the angle range which the lock will open, the lock will turn partially when an open attempt is made.")]
[SerializeField]
private float _closeDistance;
public float CloseDistance
{
get => _closeDistance;
set => _closeDistance = Mathf.Clamp(value, 5, maxCloseDistance);
}
[Tooltip("The amount of time before a lock pick breaks when the lock is unable to be opened, but the player is attempting to open it.")]
[Range(0f, 5f)]
public float breakTime = 1f;
[Header("Animation Trigger Strings")] public string openTrigger = "OpenPadlock";
public string closeTrigger = "ClosePadlock";
public string lockPickBreakTrigger = "BreakLockpick1";
public string lockPickInsertTrigger = "InsertLockpick";
// Private animation hashes
private int _openTrigger;
private int _closeTrigger;
private int _lockpickBreakTrigger;
private int _lockpickInsertTrigger;
#endregion
}
}

View File

@@ -0,0 +1,43 @@
//using UnityEngine;
//using UnityEngine.UI;
//using Lockpicking;
//public class KeyholeDemoUI : MonoBehaviour
//{
// // Set up references to the Text objects
// public Text lockAngleText;
// public Text lockRangeText;
// public Text breakTimeText;
// public Text lockpickAngleText;
// public Text keyholeAngleText;
// public Text closeDistanceText;
// public Keyhole lockpick;
// void Start()
// {
// ResetLock();
// }
// void Update()
// {
// DrawText();
// }
// private void DrawText()
// {
// lockAngleText.text = "" + lockpick.LockAngle;
// lockRangeText.text = "" + Mathf.Round(lockpick.LockAngle - lockpick.LockGive) + " to " + Mathf.Round(lockpick.LockAngle + lockpick.LockGive);
// breakTimeText.text = "" + lockpick.BreakTimeCounter;
// lockpickAngleText.text = "" + lockpick.LockPickAngle;
// keyholeAngleText.text = "" + lockpick.KeyholeTurnValue;
// closeDistanceText.text = "" + lockpick.CloseDistance;
// }
// public void ResetLock()
// {
// lockpick.ResetLock();
// }
//}

View File

@@ -0,0 +1,64 @@
using UnityEngine.Events;
[RequireComponent(typeof(Animator))]
public class LockButton : MonoBehaviour
{
[Header("Animation Trigger Strings")] public string pressDownTrigger = "ButtonPressDown";
public string pressUpTrigger = "ButtonPressUp";
[Header("Plumbing")][SerializeField] private Animator animator;
public LocksetAudio audioButtonPressed;
public LocksetAudio audioButtonReset;
private readonly UnityEvent buttonPressed = new UnityEvent();
private readonly UnityEvent buttonReset = new UnityEvent();
private bool _isUp = true;
private int _pressDownTrigger;
private int _pressUpTrigger;
private void Start()
{
animator = GetComponent<Animator>();
}
private void Awake()
{
_pressDownTrigger = Animator.StringToHash(pressDownTrigger);
_pressUpTrigger = Animator.StringToHash(pressUpTrigger);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.P))
ToggleButton();
}
public void ToggleButton()
{
if (_isUp)
{
animator.SetTrigger(_pressDownTrigger);
buttonPressed.Invoke();
//Log.Out("LockButton-ToggleButton PLAY SOUND: audioButtonPressed");
audioButtonPressed.PlayOnce();
}
else
{
animator.SetTrigger(_pressUpTrigger);
buttonReset.Invoke();
//Log.Out("LockButton-ToggleButton PLAY SOUND: audioButtonReset");
audioButtonReset.PlayOnce();
}
_isUp = !_isUp;
}
public void ToggleButton(bool up)
{
if (up && !_isUp || !up && _isUp)
ToggleButton();
}
}

View File

@@ -0,0 +1,71 @@
using Lockpicking;
public class LockControls : MonoBehaviour
{
public Keyhole lockpick;
PlayerActionsLocal playerActions;
private void Update()
{
if (!lockpick)
return;
if (playerActions == null)
{
var player = GameManager.Instance.World.GetPrimaryPlayer();
if (player != null)
playerActions = player.PlayerUI.playerInput;
}
if (lockpick.gameObject.activeSelf) InputControls();
}
private bool Left()
{
if (Input.GetKey(KeyCode.JoystickButton4)) return true;
if (Input.GetKey(KeyCode.A)) return true;
if (Input.GetKey(KeyCode.LeftArrow)) return true;
if (Input.mouseScrollDelta.y < 0) return true;
return false;
}
private bool Right()
{
if (Input.GetKey(KeyCode.JoystickButton5)) return true;
if (Input.GetKey(KeyCode.D)) return true;
if (Input.GetKey(KeyCode.RightArrow)) return true;
if (Input.mouseScrollDelta.y > 0) return true;
return false;
}
private void InputControls()
{
ResetValues();
if (Input.GetKey(KeyCode.Space))
{
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
lockpick.openPressure = 0.4f;
else
lockpick.openPressure = 1f;
}
if (playerActions == null) return;
if (Left())
lockpick.lockpickPressure = -1f;
if (Right())
lockpick.lockpickPressure = 1f;
//if (Input.GetKey(KeyCode.LeftArrow))
//else if (Input.GetKey(KeyCode.RightArrow)) lockpick.lockpickPressure = 1f;
}
private void ResetValues()
{
lockpick.openPressure = 0f;
lockpick.lockpickPressure = 0f;
}
}

View File

@@ -0,0 +1,36 @@
//using UnityEngine;
//using UnityEngine.UI;
//public class LockDemoCommonControls : MonoBehaviour
//{
// public GameObject canvasUI;
// public Button[] allTextureButtons;
// void Update()
// {
// if (Input.GetKeyDown(KeyCode.C))
// canvasUI.SetActive(!canvasUI.activeSelf);
// if (Input.GetKeyDown(KeyCode.Alpha1))
// allTextureButtons[0].onClick.Invoke();
// if (Input.GetKeyDown(KeyCode.Alpha2))
// allTextureButtons[1].onClick.Invoke();
// if (Input.GetKeyDown(KeyCode.Alpha3))
// allTextureButtons[2].onClick.Invoke();
// if (Input.GetKeyDown(KeyCode.Alpha4))
// allTextureButtons[3].onClick.Invoke();
// if (Input.GetKeyDown(KeyCode.Alpha5))
// allTextureButtons[4].onClick.Invoke();
// if (Input.GetKeyDown(KeyCode.Alpha6))
// allTextureButtons[5].onClick.Invoke();
// if (Input.GetKeyDown(KeyCode.Alpha7))
// allTextureButtons[6].onClick.Invoke();
// }
//}

View File

@@ -0,0 +1,146 @@
public class LockEmissive : MonoBehaviour
{
[Header("Behavior")] public bool pulse = true;
public bool breakpoint;
public bool success;
public bool off;
[Header("Settings")][Range(0f, 5f)] public float pulseSpeedMod = 0.5f;
[Header("Colors")] public Color hightlightColor = Color.yellow;
public Color[] colors = { Color.cyan, Color.red, Color.yellow, Color.green, Color.blue, Color.magenta, Color.white, Color.grey, Color.yellow, Color.blue };
[Header("Renderers")][SerializeField] private Renderer[] _renderers;
public Renderer highlightRenderer;
// Hidden from Inspector
[HideInInspector] public float breakpointValue;
[HideInInspector] public float successValue;
private int _colorIndex;
// Private variables
private float _pulseValue;
private void Start()
{
}
private void Update()
{
if (off)
{
SetAllMaterials(0f);
}
else if (pulse)
{
_pulseValue = Mathf.PingPong(Time.time * pulseSpeedMod, 1); // Pulse the value over time
SetAllMaterials(_pulseValue); // Set the values
}
else if (breakpoint)
{
SetAllMaterials(breakpointValue); // Set the values
}
else if (success)
{
SetAllMaterials(Mathf.Clamp(Mathf.Abs(successValue - 1), 0, 1)); // Set the values
}
if (highlightRenderer)
SetHighlightMaterial();
}
private Color _activeColor()
{
return colors[_colorIndex];
}
public void SetRenders(Renderer[] newRenders)
{
_renderers = newRenders;
}
public void SetHighlightRenderer(Renderer value)
{
highlightRenderer = value;
}
private void SetHighlightMaterial()
{
// sphereii: disable the high light color
//highlightRenderer.material.SetColor("_EmissionColor", hightlightColor);
highlightRenderer.material.SetColor("_EmissionColor", Color.clear);
}
/// <summary>
/// Sets all materials attached to the renderers array
/// </summary>
/// <param name="value"></param>
private void SetAllMaterials(float value)
{
if (_renderers == null) return;
for (var i = 0; i < _renderers.Length; i++)
if (_renderers[i] != null && _renderers[i].gameObject != null)
if (_renderers[i].gameObject.activeSelf)
SetMaterial(_renderers[i].material, value);
}
/// <summary>
/// Sets a single material
/// </summary>
/// <param name="material"></param>
/// <param name="value"></param>
private void SetMaterial(Material material, float value)
{
var finalColor = _activeColor() * Mathf.LinearToGammaSpace(value);
//material.SetColor("_EmissionColor", finalColor);
// sphereii: give it a nice bronze color
material.SetColor("_EmissionColor", new Color(0.666f, 0.588f, 0.275f, 1f));
}
public void NextColor()
{
_colorIndex = _colorIndex + 1 >= colors.Length ? 0 : _colorIndex + 1;
}
public void PrevColor()
{
_colorIndex = _colorIndex - 1 < 0 ? colors.Length - 1 : _colorIndex - 1;
}
public void SetPulse()
{
pulse = true;
breakpoint = false;
success = false;
off = false;
}
public void SetBreakpoint()
{
pulse = false;
breakpoint = true;
success = false;
off = false;
}
public void SetSuccess()
{
pulse = false;
breakpoint = false;
success = true;
off = false;
}
public void SetOff()
{
pulse = false;
breakpoint = false;
success = false;
off = true;
}
}

View File

@@ -0,0 +1,51 @@
public class LockEmissiveControls : MonoBehaviour
{
public Renderer[] baseplate1;
public Renderer[] baseplate2;
public Renderer[] lock1;
public Renderer[] lock2;
public Renderer[] lock3;
public Renderer[] button;
public Renderer[] padlock1;
public Renderer[] padlock2;
public void SetBaseplate1(Texture newTexture)
{
for (var i = 0; i < baseplate1.Length; i++) baseplate1[i].material.SetTexture("_EmissionMap", newTexture);
}
public void SetBaseplate2(Texture newTexture)
{
for (var i = 0; i < baseplate2.Length; i++) baseplate2[i].material.SetTexture("_EmissionMap", newTexture);
}
public void SetLock1(Texture newTexture)
{
for (var i = 0; i < lock1.Length; i++) lock1[i].material.SetTexture("_EmissionMap", newTexture);
}
public void SetLock2(Texture newTexture)
{
for (var i = 0; i < lock2.Length; i++) lock2[i].material.SetTexture("_EmissionMap", newTexture);
}
public void SetLock3(Texture newTexture)
{
for (var i = 0; i < lock3.Length; i++) lock3[i].material.SetTexture("_EmissionMap", newTexture);
}
public void SetButton(Texture newTexture)
{
for (var i = 0; i < button.Length; i++) button[i].material.SetTexture("_EmissionMap", newTexture);
}
public void SetPadlock1(Texture newTexture)
{
for (var i = 0; i < padlock1.Length; i++) padlock1[i].material.SetTexture("_EmissionMap", newTexture);
}
public void SetPadlock2(Texture newTexture)
{
for (var i = 0; i < padlock2.Length; i++) padlock2[i].material.SetTexture("_EmissionMap", newTexture);
}
}

View File

@@ -0,0 +1,61 @@
public class LockObjectRotation : MonoBehaviour
{
public bool mouseMovementOn;
[SerializeField] private float maxX = 30f; // Max rotation
[SerializeField] private float maxY = 30f; // Max rotation
[SerializeField] private Vector3 mousePosition; // last position of mouse
[SerializeField] private float speed = 2160f; // speed of rotation
[SerializeField] private float startX; // Starting rotation
[SerializeField] private float startY; // Starting rotation
public Camera uiCam;
private void Start()
{
startX = GetAngle(transform.localEulerAngles.x);
startY = GetAngle(transform.localEulerAngles.y);
}
private void Update()
{
MouseMovement();
mousePosition = uiCam.ScreenToViewportPoint(Input.mousePosition); // Save mouse position every frame.
//mousePosition = Camera.main.ScreenToViewportPoint(Input.mousePosition); // Save mouse position every frame.
}
private void MouseMovement()
{
// If we are holding down the left mouse button...
if (Input.GetMouseButton(0) || mouseMovementOn)
{
// Grab the new position of the mouse, 0,0 - 1,1
var newPosition = uiCam.ScreenToViewportPoint(Input.mousePosition);
//Vector3 newPosition = Camera.main.ScreenToViewportPoint(Input.mousePosition);
// Compute the delta in the x and y positions. Do inversion for the yDelta. Note X/Y are flipped.
var horDelta = -(newPosition.x - mousePosition.x) * speed * Time.deltaTime;
var verDelta = (newPosition.y - mousePosition.y) * speed * Time.deltaTime;
// Make sure we don't go over our max range
if (GetAngle(transform.localEulerAngles.x) + verDelta > startX + maxX || GetAngle(transform.localEulerAngles.x) + verDelta < startX - maxX)
verDelta = 0;
if (GetAngle(transform.localEulerAngles.y) + horDelta > startY + maxY || GetAngle(transform.localEulerAngles.y) + horDelta < startY - maxY)
horDelta = 0;
// Compute & assign the new angle
var newAngles = new Vector3(transform.localEulerAngles.x + verDelta,
transform.localEulerAngles.y + horDelta, transform.localEulerAngles.z);
transform.localEulerAngles = newAngles;
}
}
private float GetAngle(float eulerAngle)
{
var angle = eulerAngle;
angle %= 360;
if (angle > 180)
angle -= 360;
return angle;
}
}

View File

@@ -0,0 +1,75 @@
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class LocksetAudio : MonoBehaviour
{
public AudioClip[] clips;
private float _delay;
private AudioSource audioSource;
public void Awake()
{
audioSource = GetComponent<AudioSource>();
}
public void PlayAudioClip(float volume = 0.5f)
{
if (clips == null)
return;
if (clips.Length > 0)
{
SelectRandomClip();
audioSource.volume = volume;
audioSource.Play();
}
}
public void PlayOnce()
{
SelectRandomClip();
if (audioSource.clip == null)
return;
audioSource.PlayOneShot(audioSource.clip);
}
public bool isAudioPlaying()
{
return audioSource.isPlaying;
}
public void DelayPlay(float delay)
{
_delay = delay;
StartCoroutine("Delay");
}
public IEnumerator Delay()
{
yield return new WaitForSeconds(_delay);
PlayOnce();
}
public void PlayLoop()
{
if (!audioSource.isPlaying)
{
SelectRandomClip();
audioSource.Play();
}
}
public void StopLoop()
{
audioSource.Pause();
}
public void SelectRandomClip()
{
if (clips == null)
return;
if (clips.Length > 0) audioSource.clip = clips[UnityEngine.Random.Range(0, clips.Length)];
}
}

View File

@@ -0,0 +1,175 @@
using Lockpicking;
using System.Collections.Generic;
using Object = UnityEngine.Object;
// This class sites between the thirdparty Keyhole script + prefabs and support scripts.
public class SphereLocks
{
private GameObject _lockPick;
private GameObject _lockPickAsset;
// transforms
private List<string> _transforms = new List<string>();
public void Init(BlockValue blockValue, Vector3i blockPos)
{
// Check if the current block has a pre-defined lockpick prefab
var lockPrefab = "";
if (blockValue.type != 0)
if (blockValue.Block.Properties.Contains("LockPrefab"))
lockPrefab = blockValue.Block.Properties.GetStringValue("LockPrefab");
// Load up the default.
if (string.IsNullOrEmpty(lockPrefab))
{
// If the globally configured lock pick cotnains Lockset01, assume its the default.
lockPrefab = "#@modfolder(Locks):Resources/Locks.unity3d?Lockset01"; // Configuration.GetPropertyValue("AdvancedLockpicking", "LockPrefab");
if (lockPrefab.EndsWith("Lockset01"))
{
var locks = new List<string> { "Lockset01", "Lockset02", "Lockset03", "Lockset04", "padlock01" };
var randomKey = Math.Abs(blockPos.x % 9);
var randomLock = randomKey switch
{
< 1 => "Lockset01",
< 3 => "Lockset02",
< 5 => "Lockset03",
< 7 => "Lockset04",
_ => "padlock01"
};
lockPrefab = lockPrefab.Replace("Lockset01", randomLock);
}
}
if (string.IsNullOrEmpty(lockPrefab))
return;
try
{
_lockPickAsset = DataLoader.LoadAsset<GameObject>(lockPrefab);
_lockPick = Object.Instantiate(_lockPickAsset);
}
catch (Exception ex)
{
Log.Out($"LockPrefab not valid. Falling back to vanilla.");
return;
}
Disable();
// Marked transforms
_transforms = new List<string> { "Baseplate1", "Baseplate2", "ButtonInner", "ButtonInner", "ButtonOuter", "Padlock1_low" };
_transforms.AddRange(new List<string> { "Padlock1_Latch_low", "Lock1Outer", "Lock2Outer", "Lock3Outer", "Lock1Inner", "Lock2Inner", "Lock3Inner" });
if (_lockPick.GetComponent<Keyhole>() == null)
{
// Populate the Keyhole
var keyhole = _lockPick.AddComponent<Keyhole>();
keyhole.keyhole = FindTransform("Keyhole (Turnable)").gameObject;
// attach the lock control the to top level
LockControls lockControl;
if (_lockPick.transform.parent != null)
lockControl = _lockPick.transform.parent.gameObject.AddComponent<LockControls>();
else
lockControl = _lockPick.transform.gameObject.AddComponent<LockControls>();
lockControl.lockpick = keyhole;
// Lock Pick configuration
keyhole.lockpickObject = _lockPick.transform.FindInChilds("LockpickB (Turnable)").gameObject;
keyhole.lockpickAnimator = FindTransform("LockpickB").GetComponent<Animator>();
keyhole.lockpickAnimator.gameObject.SetActive(true);
keyhole.blockValue = blockValue;
var cam = FindTransform("Cam2").GetComponentInChildren<Camera>();
if (cam != null)
{
cam.rect = new Rect(0.25f, 0.25f, 0.5f, 0.5f);
var lockObjectRotation = keyhole.lockpickObject.transform.gameObject.AddComponent<LockObjectRotation>();
lockObjectRotation.uiCam = cam;
}
var padlock = FindTransform("Padlock1");
if (padlock != null)
{
keyhole.padlock1 = padlock.gameObject;
keyhole.audioPadlockJiggle = FindTransform("Audio Padlock Jiggle").gameObject.AddComponent<LocksetAudio>();
keyhole.audioPadlockOpen = FindTransform("Audio Padlock Open").gameObject.AddComponent<LocksetAudio>();
}
// audio configuration
keyhole.audioTurnClick = FindTransform("Audio Turn Click").gameObject.AddComponent<LocksetAudio>();
keyhole.audioSqueek = FindTransform("Audio Squeek").gameObject.AddComponent<LocksetAudio>();
keyhole.audioOpen = FindTransform("Audio Open").gameObject.AddComponent<LocksetAudio>();
keyhole.audioJiggle = FindTransform("Audio Jiggle A").gameObject.AddComponent<LocksetAudio>();
keyhole.audioJiggle2 = FindTransform("Audio Jiggle B").gameObject.AddComponent<LocksetAudio>();
keyhole.audioJiggle3 = FindTransform("Audio Jiggle C").gameObject.AddComponent<LocksetAudio>();
keyhole.audioLockpickBreak = FindTransform("Audio Lockpick Break").gameObject.AddComponent<LocksetAudio>();
keyhole.audioLockpickEnter = FindTransform("Audio Lockpick Enter").gameObject.AddComponent<LocksetAudio>();
keyhole.audioLockpickClick = FindTransform("Audio Lockpick Click").gameObject.AddComponent<LocksetAudio>();
var lockEmissive = _lockPick.AddComponent<LockEmissive>();
// lockEmissive.off = true;
var lstRenders = new List<Renderer>();
var tempRender = new Renderer[12];
foreach (var transform in _transforms)
{
var temp = FindTransform(transform);
if (temp)
lstRenders.Add(FindTransform(transform).GetComponent<MeshRenderer>());
}
lockEmissive.SetRenders(lstRenders.ToArray());
}
Enable();
}
public Keyhole GetScript()
{
return _lockPick != null ? _lockPick.GetComponent<Keyhole>() : null;
}
public bool IsLockOpened()
{
return _lockPick != null && _lockPick.GetComponent<Keyhole>().LockComplete();
}
public void SetPlayer(EntityPlayer player)
{
if (_lockPick != null) _lockPick.GetComponent<Keyhole>().player = player;
}
private Transform FindTransform(string target)
{
return _lockPick.transform.FindInChilds(target);
}
public void Enable()
{
if (_lockPick == null) return;
_lockPick.SetActive(true);
_lockPick.GetComponent<Keyhole>().ResetLock();
}
public void Disable()
{
if (_lockPick != null)
{
Keyhole keyhole = _lockPick.GetComponent<Keyhole>();
if (keyhole != null && keyhole.breakTimeCounter > 0)
{
//Log.Out("Sphereii_Locks Disabled START, breakTimeCounter: " + keyhole.breakTimeCounter);
keyhole.BreakLockpick();
}
_lockPick.SetActive(false);
}
}
}

View File

@@ -0,0 +1,88 @@
// Simple XUI screen to enable the lock picking to have a window-style pop up.
public class XUiC_PickLocking : XUiController
{
public static string ID = "";
private Vector3i blockPos;
private BlockValue currentBlock;
private SphereLocks Lock;
// Reference to our current locked container
private ILockable LockedItem;
public override void Init()
{
Lock = new SphereLocks();
ID = windowGroup.ID;
base.Init();
}
public override void Update(float _dt)
{
base.Update(_dt);
if (LockedItem == null)
return;
// Check if the lock is open
if (Lock.IsLockOpened())
{
LockedItem.SetLocked(false);
OnClose();
}
}
// Set the container reference so we can unlock it.
public static void Open(LocalPlayerUI playerUi, ILockable lockedItem, BlockValue blockValue, Vector3i blockPos)
{
// Configure the lock pick
playerUi.xui.FindWindowGroupByName(ID).GetChildByType<XUiC_PickLocking>().LockedItem = lockedItem;
playerUi.xui.FindWindowGroupByName(ID).GetChildByType<XUiC_PickLocking>().currentBlock = blockValue;
playerUi.xui.FindWindowGroupByName(ID).GetChildByType<XUiC_PickLocking>().blockPos = blockPos;
playerUi.windowManager.Open(ID, true);
}
// Set the player reference and display the lock.
public override void OnOpen()
{
EntityPlayer player = xui.playerUI.entityPlayer;
base.OnOpen();
Lock = new SphereLocks();
// Pass the Player reference to the lock before we enable.
Lock.Init(currentBlock, blockPos);
Lock.SetPlayer(player);
Lock.Enable();
if (!ThreadManager.IsMainThread()) return;
xui.playerUI.entityPlayer.PlayOneShot("open_sign");
}
public override void OnClose()
{
if (Lock.IsLockOpened())
{
var blockValue = BlockValue.Air;
if (!currentBlock.Block.LockpickDowngradeBlock.isair)
{
blockValue = currentBlock.Block.LockpickDowngradeBlock;
}
else if (!currentBlock.Block.DowngradeBlock.isair)
{
blockValue = currentBlock.Block.DowngradeBlock;
}
if (!blockValue.isair)
{
blockValue = BlockPlaceholderMap.Instance.Replace(blockValue, GameManager.Instance.World.GetGameRandom(), blockPos.x, blockPos.z, false);
blockValue.rotation = currentBlock.rotation;
blockValue.meta = currentBlock.meta;
GameManager.Instance.World.SetBlockRPC(0, blockPos, blockValue, blockValue.Block.Density);
}
}
Lock.Disable();
LockedItem = null;
base.OnClose();
xui.playerUI.windowManager.Close(ID);
if (!ThreadManager.IsMainThread()) return;
xui.playerUI.entityPlayer.PlayOneShot("close_sign");
}
}