124 lines
3.4 KiB
C#
Raw Normal View History

2025-09-24 11:24:38 +05:00
using DG.Tweening;
using UnityEngine;
using TMPro;
namespace TPSBR.UI
{
public class UICrosshair : UIWidget
{
// PRIVATE MEMBERS
[SerializeField]
private RectTransform _resizingGroup;
[SerializeField]
private CanvasGroup _crosshairRootGroup;
[SerializeField]
private CanvasGroup _unarmedGroup;
[SerializeField]
private CanvasGroup _armedGroup;
[SerializeField]
private GameObject _sniperScope;
[SerializeField]
private UIBehaviour _undesiredFirePosition;
[SerializeField]
private float _undesiredFireCrosshairAlpha = 0.6f;
[Header("Audio")]
[SerializeField]
private AudioSetup _hitPerformed;
[SerializeField]
private AudioSetup _criticalHitPerformed;
[Header("Hit Feedback")]
[SerializeField]
private CanvasGroup _hitGroup;
[SerializeField]
private CanvasGroup _criticalHitGroup;
[SerializeField]
private CanvasGroup _fatalHitGroup;
[SerializeField]
private float _hitGroupDelay = 0.15f;
[SerializeField]
private float _hitGroupFadeInDuration = 0.1f;
[SerializeField]
private float _hitGroupFadeOutDuration = 0.8f;
[Header("Dispersion")]
[SerializeField]
private float _sizeDispersion0 = 24f;
[SerializeField]
private float _sizeDispersion50 = 1000f;
[SerializeField]
private float _changeSpeed = 20f;
private float _defaultSize;
private int _lastSoundFrame;
private Vector2 _targetSize;
// PUBLIC METHODS
public void HitPerformed(HitData hitData)
{
PlayEffect(hitData.IsCritical == true ? _criticalHitPerformed : _hitPerformed);
var hitGroup = hitData.IsFatal == true ? _fatalHitGroup : (hitData.IsCritical == true ? _criticalHitGroup : _hitGroup);
DOTween.Kill(hitGroup);
hitGroup.DOFade(1f, _hitGroupFadeInDuration).SetDelay(_hitGroupDelay);
hitGroup.DOFade(0f, _hitGroupFadeOutDuration).SetDelay(_hitGroupDelay + _hitGroupFadeInDuration + 0.1f);
}
public void UpdateCrosshair(Agent agent)
{
var weapon = agent.Weapons.CurrentWeapon;
float size = _defaultSize;
bool weaponValid = weapon != null && weapon.Object.IsValid;
if (weaponValid == true && weapon is FirearmWeapon firearmWeapon)
{
size = Mathf.Lerp(_sizeDispersion0, _sizeDispersion50, firearmWeapon.TotalDispersion / 50f);
}
_targetSize = new Vector2(size, size);
_resizingGroup.sizeDelta = Vector2.Lerp(_resizingGroup.sizeDelta, _targetSize, Time.deltaTime * _changeSpeed);
bool showScope = weaponValid == true && weapon.HitType == EHitType.Sniper && agent.Character.CharacterController.Data.Aim == true;
_armedGroup.SetVisibility(showScope == false && weaponValid);
_unarmedGroup.SetVisibility(weaponValid == false);
_sniperScope.SetActive(showScope);
bool showUndesiredFirePosition = weaponValid == true && agent.Interactions.IsUndesiredTargetPoint;
_undesiredFirePosition.SetActive(showUndesiredFirePosition);
if (showUndesiredFirePosition == true)
{
_undesiredFirePosition.transform.position = Context.Camera.Camera.WorldToScreenPoint(agent.Interactions.TargetPoint);
}
_crosshairRootGroup.alpha = Mathf.Lerp(_crosshairRootGroup.alpha, showUndesiredFirePosition == true ? _undesiredFireCrosshairAlpha : 1f, Time.deltaTime * 8f);
}
// MONOBEHAVIOUR
private void Awake()
{
_defaultSize = _resizingGroup.sizeDelta.x;
}
// PRIVATE MEMBERS
private void PlayEffect(AudioSetup setup)
{
if (Time.frameCount == _lastSoundFrame)
return; // Play only one sound per frame
SceneUI.PlaySound(setup);
_lastSoundFrame = Time.frameCount;
}
}
}