using System; using System.Collections.Generic; using HG; using UnityEngine; namespace RoR2.UI; [RequireComponent(typeof(PointViewer))] public class SniperTargetViewer : MonoBehaviour { public GameObject visualizerPrefab; private PointViewer pointViewer; private HUD hud; private Dictionary, GameObject> hurtBoxToVisualizer = new Dictionary, GameObject>(); private List displayedTargets = new List(); private List previousDisplayedTargets = new List(); private void Awake() { pointViewer = GetComponent(); OnTransformParentChanged(); } private void OnTransformParentChanged() { hud = GetComponentInParent(); } private void OnDisable() { SetDisplayedTargets(Array.Empty()); hurtBoxToVisualizer.Clear(); } private void Update() { List list = CollectionPool>.RentCollection(); if ((bool)hud && (bool)hud.targetMaster) { TeamIndex teamIndex = hud.targetMaster.teamIndex; IReadOnlyList readOnlySniperTargetsList = HurtBox.readOnlySniperTargetsList; int i = 0; for (int count = readOnlySniperTargetsList.Count; i < count; i++) { HurtBox hurtBox = readOnlySniperTargetsList[i]; if ((bool)hurtBox.healthComponent && hurtBox.healthComponent.alive && FriendlyFireManager.ShouldDirectHitProceed(hurtBox.healthComponent, teamIndex) && (object)hurtBox.healthComponent.body != hud.targetMaster.GetBody()) { list.Add(hurtBox); } } } SetDisplayedTargets(list); list = CollectionPool>.ReturnCollection(list); } private void OnTargetDiscovered(HurtBox hurtBox) { if (!hurtBoxToVisualizer.ContainsKey(hurtBox)) { GameObject value = pointViewer.AddElement(new PointViewer.AddElementRequest { elementPrefab = visualizerPrefab, target = hurtBox.transform, targetWorldVerticalOffset = 0f, targetWorldRadius = HurtBox.sniperTargetRadius, scaleWithDistance = true }); hurtBoxToVisualizer.Add(hurtBox, value); } else { Debug.LogWarning($"Already discovered hurtbox: {hurtBox}"); } } private void OnTargetLost(HurtBox hurtBox) { if (hurtBoxToVisualizer.TryGetValue(hurtBox, out var value)) { pointViewer.RemoveElement(value); } } private void SetDisplayedTargets(IReadOnlyList newDisplayedTargets) { Util.Swap(ref displayedTargets, ref previousDisplayedTargets); displayedTargets.Clear(); ListUtils.AddRange(displayedTargets, newDisplayedTargets); List list = CollectionPool>.RentCollection(); List list2 = CollectionPool>.RentCollection(); ListUtils.FindExclusiveEntriesByReference(displayedTargets, previousDisplayedTargets, list, list2); foreach (HurtBox item in list2) { OnTargetLost(item); } foreach (HurtBox item2 in list) { OnTargetDiscovered(item2); } list2 = CollectionPool>.ReturnCollection(list2); list = CollectionPool>.ReturnCollection(list); } }