RizzeBattleRoyale/Assets/TPSBR/Scripts/UI/Widgets/UIHitDamageIndicator.cs
2025-09-24 11:24:38 +05:00

142 lines
3.9 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace TPSBR.UI
{
public class UIHitDamageIndicator : UIWidget
{
// PRIVATE MEMBERS
[SerializeField]
private UIHitDamageIndicatorItem _hitItem;
[SerializeField]
private UIHitDamageIndicatorItem _critItem;
[SerializeField]
private UIHitDamageIndicatorItem _fatalItem;
private List<UIHitDamageIndicatorItem> _activeItems = new List<UIHitDamageIndicatorItem>();
private List<UIHitDamageIndicatorItem> _inactiveItems = new List<UIHitDamageIndicatorItem>();
private List<UIHitDamageIndicatorItem> _activeCritItems = new List<UIHitDamageIndicatorItem>();
private List<UIHitDamageIndicatorItem> _inactiveCritItems = new List<UIHitDamageIndicatorItem>();
private List<UIHitDamageIndicatorItem> _activeFatalItems = new List<UIHitDamageIndicatorItem>();
private List<UIHitDamageIndicatorItem> _inactiveFatalItems = new List<UIHitDamageIndicatorItem>();
private RectTransform _canvasRectTransform;
private Canvas _canvas;
private List<HitData> _pendingHits = new List<HitData>(16);
// PUBLIC METHODS
public void HitPerformed(HitData hitData)
{
for (int i = 0; i < _pendingHits.Count; i++)
{
var pending = _pendingHits[i];
// Try to merge hit data
if (pending.Target == hitData.Target && pending.Target != null)
{
pending.Amount += hitData.Amount;
pending.IsFatal |= hitData.IsFatal;
pending.IsCritical |= hitData.IsCritical;
_pendingHits[i] = pending;
return;
}
}
_pendingHits.Add(hitData);
}
// UIWidget INTERFACE
protected override void OnInitialize()
{
_hitItem.SetActive(false);
_critItem.SetActive(false);
_fatalItem.SetActive(false);
_canvas = GetComponentInParent<Canvas>();
_canvasRectTransform = _canvas.transform as RectTransform;
}
protected override void OnHidden()
{
_pendingHits.Clear();
}
// MONOBEHAVIOUR
private void Update()
{
for (int i = 0; i < _pendingHits.Count; i++)
{
ProcessHit(_pendingHits[i]);
}
_pendingHits.Clear();
}
private void LateUpdate()
{
UpdateActiveItems(_activeItems, _inactiveItems);
UpdateActiveItems(_activeCritItems, _inactiveCritItems);
UpdateActiveItems(_activeFatalItems, _inactiveFatalItems);
}
// PRIVATE METHODS
private void ProcessHit(HitData hitData)
{
var activeItems = hitData.IsFatal == true ? _activeFatalItems : (hitData.IsCritical == true ? _activeCritItems : _activeItems);
var inactiveItems = hitData.IsFatal == true ? _inactiveFatalItems : (hitData.IsCritical == true ? _inactiveCritItems : _inactiveItems);
var hitItem = inactiveItems.PopLast();
if (hitItem == null)
{
hitItem = Instantiate(hitData.IsFatal == true ? _fatalItem : (hitData.IsCritical == true ? _critItem : _hitItem));
hitItem.transform.SetParent(_hitItem.transform.parent);
}
activeItems.Add(hitItem);
var hitPosition = hitData.Position;
if (hitData.Target != null)
{
hitPosition = hitData.Target.HitPivot.position;
}
hitItem.Activate(hitData.Amount, hitPosition);
hitItem.SetActive(true);
hitItem.transform.SetAsLastSibling();
}
private void UpdateActiveItems(List<UIHitDamageIndicatorItem> activeItems, List<UIHitDamageIndicatorItem> inactiveItems)
{
for (int i = activeItems.Count; i --> 0;)
{
var item = activeItems[i];
if (item.IsFinished == true)
{
item.SetActive(false);
activeItems.RemoveBySwap(i);
inactiveItems.Add(item);
continue;
}
item.transform.position = GetUIPosition(item.WorldPosition);
}
}
private Vector3 GetUIPosition(Vector3 worldPosition)
{
var screenPoint = Context.Camera.Camera.WorldToScreenPoint(worldPosition);
RectTransformUtility.ScreenPointToLocalPointInRectangle(_canvasRectTransform, screenPoint, _canvas.worldCamera, out Vector2 screenPosition);
return _canvasRectTransform.TransformPoint(screenPosition);
}
}
}