243 lines
8.2 KiB
C#
243 lines
8.2 KiB
C#
using OnlyScove.Scripts;
|
|
using UnityEngine;
|
|
|
|
namespace Invector.vCharacterController
|
|
{
|
|
[vClassHeader("MELEE LOCK-ON")]
|
|
public class vLockOn : vLockOnBehaviour
|
|
{
|
|
#region variables
|
|
[System.Serializable]
|
|
public class LockOnEvent : UnityEngine.Events.UnityEvent<Transform> { }
|
|
|
|
[Tooltip("Make sure to disable or change the StrafeInput to a different key at the Player Input component")]
|
|
public bool strafeWhileLockOn = true;
|
|
[Tooltip("Create a Image inside the UI and assign here")]
|
|
public RectTransform aimImagePrefab;
|
|
public Canvas aimImageContainer;
|
|
public Vector2 aimImageSize = new Vector2(30, 30);
|
|
[Tooltip("True: Hide the sprite when not Lock On, False: Always show the Sprite")]
|
|
public bool hideSprite = true;
|
|
[Tooltip("Create a offset for the sprite based at the center of the target")]
|
|
[Range(-0.5f, 0.5f)]
|
|
public float spriteHeight = 0.25f;
|
|
[Tooltip("Offset for the camera height")]
|
|
public float cameraHeightOffset;
|
|
[Tooltip("Transition Speed for the Camera")]
|
|
public float lockSpeed = 0.5f;
|
|
|
|
[vEditorToolbar("Debug")]
|
|
public bool debugMode;
|
|
|
|
internal bool isLockingOn;
|
|
public LockOnEvent onLockOnTarget;
|
|
public LockOnEvent onUnLockOnTarget;
|
|
protected Canvas _aimCanvas;
|
|
protected RectTransform _aimImage;
|
|
|
|
protected bool _inTarget;
|
|
protected virtual bool inTarget { get { return _inTarget; } set { _inTarget = value; } }
|
|
protected vThirdPersonInput tpInput;
|
|
protected InputReader inputReader;
|
|
|
|
#endregion
|
|
|
|
protected override void Start()
|
|
{
|
|
base.Start();
|
|
Init();
|
|
|
|
tpInput = GetComponent<vThirdPersonInput>();
|
|
if (tpInput)
|
|
{
|
|
inputReader = tpInput.inputReader;
|
|
|
|
tpInput.onUpdate -= UpdateLockOn;
|
|
tpInput.onUpdate += UpdateLockOn;
|
|
|
|
// access the HealthController to Reset the LockOn when Dead
|
|
GetComponent<vHealthController>().onDead.AddListener((GameObject g) =>
|
|
{
|
|
// action to reset lockOn
|
|
isLockingOn = false;
|
|
LockOn(false);
|
|
UpdateLockOn();
|
|
});
|
|
}
|
|
|
|
if (inputReader == null) inputReader = GetComponentInParent<InputReader>();
|
|
|
|
if (!aimImageContainer)
|
|
{
|
|
aimImageContainer = gameObject.GetComponentInChildren<Canvas>(true);
|
|
}
|
|
}
|
|
|
|
public RectTransform aimImage
|
|
{
|
|
get
|
|
{
|
|
if (_aimImage) return _aimImage;
|
|
if (aimImageContainer)
|
|
{
|
|
_aimImage = Instantiate(aimImagePrefab, Vector2.zero, Quaternion.identity) as RectTransform;
|
|
_aimImage.SetParent(aimImageContainer.transform);
|
|
return _aimImage;
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("Missing UI Canvas in the scene, please add one");
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
protected virtual void UpdateLockOn()
|
|
{
|
|
if (this.tpInput == null || inputReader == null) return;
|
|
|
|
LockOnInput();
|
|
|
|
// unlock the camera if the target is null
|
|
if (isLockingOn && (tpInput.tpCamera.lockTarget == null) || LostTargetDistance())
|
|
{
|
|
isLockingOn = false;
|
|
LockOn(false);
|
|
}
|
|
|
|
// choose to use lock-on with strafe or free movement
|
|
if (strafeWhileLockOn && !tpInput.cc.locomotionType.Equals(vThirdPersonMotor.LocomotionType.OnlyStrafe))
|
|
{
|
|
if (isLockingOn && tpInput.tpCamera.lockTarget != null)
|
|
{
|
|
tpInput.cc.lockInStrafe = true;
|
|
tpInput.cc.isStrafing = true;
|
|
}
|
|
else
|
|
{
|
|
tpInput.cc.lockInStrafe = false;
|
|
tpInput.cc.isStrafing = false;
|
|
}
|
|
}
|
|
|
|
if (isLockingOn && tpInput.tpCamera.lockTarget)
|
|
{
|
|
if (inputReader.ConsumeNext()) ChangeTarget(1);
|
|
else if (inputReader.ConsumePrevious()) ChangeTarget(-1);
|
|
}
|
|
|
|
CheckForTargetDistance();
|
|
CheckForCharacterAlive();
|
|
UpdateAimImage();
|
|
}
|
|
|
|
protected virtual void LockOnInput()
|
|
{
|
|
// lock the camera into a target, if there is any around
|
|
if (inputReader.ConsumeToggleView() && !tpInput.cc.customAction)
|
|
{
|
|
isLockingOn = !isLockingOn;
|
|
LockOn(isLockingOn);
|
|
}
|
|
}
|
|
|
|
protected virtual bool LostTargetDistance()
|
|
{
|
|
if (!isLockingOn || currentTarget == null) return false;
|
|
|
|
float distance = Vector3.Distance(transform.position, currentTarget.position);
|
|
|
|
return distance > rangeToExitLockOn ? true : false;
|
|
}
|
|
|
|
protected override void SetTarget()
|
|
{
|
|
if (tpInput.tpCamera != null)
|
|
{
|
|
tpInput.tpCamera.SetLockTarget(currentTarget.transform, cameraHeightOffset, lockSpeed);
|
|
onLockOnTarget.Invoke(currentTarget);
|
|
}
|
|
}
|
|
|
|
protected virtual void CheckForTargetDistance()
|
|
{
|
|
if (!isLockingOn || currentTarget == null) return;
|
|
|
|
float distance = Vector3.Distance(transform.position, currentTarget.position);
|
|
|
|
if (distance > rangeToExitLockOn)
|
|
{
|
|
isLockingOn = false;
|
|
LockOn(false);
|
|
}
|
|
}
|
|
|
|
protected virtual void CheckForCharacterAlive()
|
|
{
|
|
if (currentTarget && !isCharacterAlive() && inTarget || (inTarget && !isCharacterAlive()))
|
|
{
|
|
ResetLockOn();
|
|
inTarget = false;
|
|
LockOn(true);
|
|
StopLockOn();
|
|
}
|
|
}
|
|
|
|
protected virtual void LockOn(bool value)
|
|
{
|
|
base.UpdateLockOn(value);
|
|
if (!inTarget && currentTarget)
|
|
{
|
|
inTarget = true;
|
|
// send current target if inTarget
|
|
SetTarget();
|
|
}
|
|
else if (inTarget && !currentTarget)
|
|
{
|
|
inTarget = false;
|
|
// send message to clear current target
|
|
StopLockOn();
|
|
}
|
|
}
|
|
|
|
protected virtual void UpdateAimImage()
|
|
{
|
|
if (!aimImageContainer || !aimImage) return;
|
|
if (hideSprite)
|
|
{
|
|
aimImage.sizeDelta = aimImageSize;
|
|
if (currentTarget && !aimImage.transform.gameObject.activeSelf && isCharacterAlive())
|
|
aimImage.transform.gameObject.SetActive(true);
|
|
else if (!currentTarget && aimImage.transform.gameObject.activeSelf)
|
|
aimImage.transform.gameObject.SetActive(false);
|
|
else if (_aimImage.transform.gameObject.activeSelf && !isCharacterAlive())
|
|
aimImage.transform.gameObject.SetActive(false);
|
|
}
|
|
if (currentTarget && aimImage && aimImageContainer)
|
|
aimImage.anchoredPosition = currentTarget.GetScreenPointOffBoundsCenter(aimImageContainer, tpInput.tpCamera.targetCamera, spriteHeight);
|
|
else if (aimImageContainer)
|
|
aimImage.anchoredPosition = Vector2.zero;
|
|
}
|
|
|
|
public virtual void StopLockOn()
|
|
{
|
|
if (currentTarget == null && tpInput.tpCamera != null)
|
|
{
|
|
onUnLockOnTarget.Invoke(tpInput.tpCamera.lockTarget);
|
|
tpInput.tpCamera.RemoveLockTarget();
|
|
isLockingOn = false;
|
|
inTarget = false;
|
|
}
|
|
}
|
|
|
|
public virtual void NextTarget()
|
|
{
|
|
base.ChangeTarget(1);
|
|
}
|
|
|
|
public virtual void PreviousTarget()
|
|
{
|
|
base.ChangeTarget(-1);
|
|
}
|
|
}
|
|
} |