124 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			124 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | 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; | ||
|  | 		} | ||
|  | 	} | ||
|  | } |