using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Text; using TMPro; using UnityEngine; namespace RoR2.UI; public class PingIndicator : MonoBehaviour { public enum PingType { Default, Enemy, Interactable, Count } public PositionIndicator positionIndicator; public TextMeshPro pingText; public Highlight pingHighlight; public ObjectScaleCurve pingObjectScaleCurve; public GameObject positionIndicatorRoot; public Color textBaseColor; public GameObject[] defaultPingGameObjects; public Color defaultPingColor; public float defaultPingDuration; public GameObject[] enemyPingGameObjects; public Color enemyPingColor; public float enemyPingDuration; public GameObject[] interactablePingGameObjects; public Color interactablePingColor; public float interactablePingDuration; public static List instancesList = new List(); private PingType pingType; private Color pingColor; private float pingDuration; private PurchaseInteraction pingTargetPurchaseInteraction; private HalcyoniteShrineInteractable halcyonShrine; private Transform targetTransformToFollow; private float fixedTimer; private static readonly StringBuilder sharedStringBuilder = new StringBuilder(); public Vector3 pingOrigin { get; set; } public Vector3 pingNormal { get; set; } public GameObject pingOwner { get; set; } public GameObject pingTarget { get; set; } public static Sprite GetInteractableIcon(GameObject gameObject) { PingInfoProvider component = gameObject.GetComponent(); if ((bool)component && (bool)component.pingIconOverride) { return component.pingIconOverride; } string path = "Textures/MiscIcons/texMysteryIcon"; if ((bool)gameObject.GetComponent()) { path = "Textures/MiscIcons/texBarrelIcon"; } else if (gameObject.name.Contains("Shrine")) { path = "Textures/MiscIcons/texShrineIconOutlined"; } else if ((bool)gameObject.GetComponent() || (bool)gameObject.GetComponent()) { path = "Textures/MiscIcons/texLootIconOutlined"; } else if ((bool)gameObject.GetComponent()) { path = "Textures/MiscIcons/texDroneIconOutlined"; } else if ((bool)gameObject.GetComponent()) { path = "Textures/MiscIcons/texTeleporterIconOutlined"; } else { PortalStatueBehavior component2 = gameObject.GetComponent(); if ((bool)component2 && component2.portalType == PortalStatueBehavior.PortalType.Shop) { path = "Textures/MiscIcons/texMysteryIcon"; } else { PurchaseInteraction component3 = gameObject.GetComponent(); if ((bool)component3 && component3.costType == CostTypeIndex.LunarCoin) { path = "Textures/MiscIcons/texMysteryIcon"; } else if ((bool)component3 || (bool)gameObject.GetComponent()) { path = "Textures/MiscIcons/texInventoryIconOutlined"; } } } return LegacyResourcesAPI.Load(path); } private void OnEnable() { instancesList.Add(this); } private void OnDisable() { instancesList.Remove(this); } [Conditional("ENABLE_PING_NAME_REPORTER")] private static void GenerateDebugMessageInChat(GameObject pingTarget) { if (pingTarget == null || !pingTarget) { return; } CharacterBody component = pingTarget.GetComponent(); if ((bool)component) { Chat.AddMessage("Debug: you pinged '" + component.gameObject.name.Replace("(Clone)", "") + "'"); return; } if (pingTarget.TryGetComponent(out var component2)) { PickupDef pickupDef = PickupCatalog.GetPickupDef(component2.GetInspectInfoProvider().GetInfo().dynamicInspectPickupIndex); if (pickupDef != null) { ItemDef itemDef = ItemCatalog.GetItemDef(pickupDef.itemIndex); if (pickupDef.displayPrefab != null) { Chat.AddMessage("Debug: you pinged '" + pickupDef.displayPrefab.gameObject.name + " ' (item name: " + ((itemDef != null) ? itemDef.name : "unknown") + "')"); return; } } } Chat.AddMessage("Debug: you pinged '" + pingTarget.gameObject.name); } public void RebuildPing() { pingHighlight.enabled = false; base.transform.rotation = Util.QuaternionSafeLookRotation(pingNormal); base.transform.position = (pingTarget ? pingTarget.transform.position : pingOrigin); base.transform.localScale = Vector3.one; positionIndicator.targetTransform = (pingTarget ? pingTarget.transform : null); positionIndicator.defaultPosition = base.transform.position; IDisplayNameProvider displayNameProvider = (pingTarget ? pingTarget.GetComponentInParent() : null); CharacterBody characterBody = null; ModelLocator modelLocator = null; pingType = PingType.Default; pingObjectScaleCurve.enabled = false; pingObjectScaleCurve.enabled = true; GameObject[] array = defaultPingGameObjects; for (int i = 0; i < array.Length; i++) { array[i].SetActive(value: false); } array = enemyPingGameObjects; for (int i = 0; i < array.Length; i++) { array[i].SetActive(value: false); } array = interactablePingGameObjects; for (int i = 0; i < array.Length; i++) { array[i].SetActive(value: false); } if ((bool)pingTarget) { UnityEngine.Debug.LogFormat("Ping target {0}", pingTarget); modelLocator = pingTarget.GetComponent(); if (displayNameProvider != null) { characterBody = pingTarget.GetComponent(); if ((bool)characterBody) { pingType = PingType.Enemy; targetTransformToFollow = characterBody.coreTransform; } else { pingType = PingType.Interactable; } } } string ownerName = GetOwnerName(); string text = (((MonoBehaviour)displayNameProvider) ? Util.GetBestBodyName(((MonoBehaviour)displayNameProvider).gameObject) : ""); _ = pingTarget != null; pingText.enabled = true; pingText.text = ownerName; switch (pingType) { case PingType.Default: { pingColor = defaultPingColor; pingDuration = defaultPingDuration; pingHighlight.isOn = false; array = defaultPingGameObjects; for (int i = 0; i < array.Length; i++) { array[i].SetActive(value: true); } Chat.AddMessage(string.Format(Language.GetString("PLAYER_PING_DEFAULT"), ownerName)); break; } case PingType.Enemy: { pingColor = enemyPingColor; pingDuration = enemyPingDuration; array = enemyPingGameObjects; for (int i = 0; i < array.Length; i++) { array[i].SetActive(value: true); } if (!modelLocator) { break; } Transform modelTransform = modelLocator.modelTransform; if ((bool)modelTransform) { CharacterModel component4 = modelTransform.GetComponent(); if ((bool)component4) { bool flag = false; CharacterModel.RendererInfo[] baseRendererInfos = component4.baseRendererInfos; for (int i = 0; i < baseRendererInfos.Length; i++) { CharacterModel.RendererInfo rendererInfo = baseRendererInfos[i]; if (!rendererInfo.ignoreOverlays && !flag) { pingHighlight.highlightColor = Highlight.HighlightColor.teleporter; pingHighlight.targetRenderer = rendererInfo.renderer; pingHighlight.strength = 1f; pingHighlight.isOn = true; pingHighlight.enabled = true; flag = true; break; } } } } Chat.AddMessage(string.Format(Language.GetString("PLAYER_PING_ENEMY"), ownerName, text)); break; } case PingType.Interactable: { pingColor = interactablePingColor; pingDuration = interactablePingDuration; pingTargetPurchaseInteraction = pingTarget.GetComponent(); halcyonShrine = pingTarget.GetComponent(); Sprite interactableIcon = GetInteractableIcon(pingTarget); SpriteRenderer component = interactablePingGameObjects[0].GetComponent(); ShopTerminalBehavior component2 = pingTarget.GetComponent(); TeleporterInteraction component3 = pingTarget.GetComponent(); if ((bool)component2) { PickupIndex pickupIndex = component2.CurrentPickupIndex(); text = string.Format(CultureInfo.InvariantCulture, "{0} ({1})", text, (component2.pickupIndexIsHidden || !component2.pickupDisplay) ? "?" : Language.GetString(PickupCatalog.GetPickupDef(pickupIndex)?.nameToken ?? PickupCatalog.invalidPickupToken)); } else if ((bool)component3) { pingDuration = 30f; pingText.enabled = false; component3.PingTeleporter(ownerName, this); } else if (!pingTarget.gameObject.name.Contains("Shrine") && ((bool)pingTarget.GetComponent() || (bool)pingTarget.GetComponent())) { pingDuration = 60f; } array = interactablePingGameObjects; for (int i = 0; i < array.Length; i++) { array[i].SetActive(value: true); } Renderer renderer = null; renderer = ((!modelLocator) ? pingTarget.GetComponentInChildren() : modelLocator.modelTransform.GetComponentInChildren()); if ((bool)renderer) { pingHighlight.highlightColor = Highlight.HighlightColor.interactive; pingHighlight.targetRenderer = renderer; pingHighlight.strength = 1f; pingHighlight.isOn = true; pingHighlight.enabled = true; } component.sprite = interactableIcon; component.enabled = !component3; if ((bool)pingTargetPurchaseInteraction && pingTargetPurchaseInteraction.costType != 0) { sharedStringBuilder.Clear(); CostTypeDef costTypeDef = CostTypeCatalog.GetCostTypeDef(pingTargetPurchaseInteraction.costType); int num = pingTargetPurchaseInteraction.cost; if (pingTargetPurchaseInteraction.costType.Equals(CostTypeIndex.Money) && TeamManager.LongstandingSolitudesInParty() > 0) { num *= TeamManager.LongstandingSolitudesInParty() + 1; } costTypeDef.BuildCostStringStyled(num, sharedStringBuilder, forWorldDisplay: false); Chat.AddMessage(string.Format(Language.GetString("PLAYER_PING_INTERACTABLE_WITH_COST"), ownerName, text, sharedStringBuilder.ToString())); } else { Chat.AddMessage(string.Format(Language.GetString("PLAYER_PING_INTERACTABLE"), ownerName, text)); } break; } } pingText.color = textBaseColor * pingColor; fixedTimer = pingDuration; } public string GetOwnerName() { if (!pingOwner) { return ""; } return Util.GetBestMasterName(pingOwner.GetComponent()); } public void DestroyPing() { if ((bool)pingTarget) { pingTarget.GetComponent()?.CancelTeleporterPing(this); } Object.Destroy(base.gameObject); } private void Update() { if (pingType == PingType.Interactable && (bool)pingTargetPurchaseInteraction && !pingTargetPurchaseInteraction.available && !halcyonShrine) { DestroyPing(); } fixedTimer -= Time.deltaTime; if (fixedTimer <= 0f) { DestroyPing(); } } private void LateUpdate() { if (!pingTarget) { if ((object)pingTarget != null) { DestroyPing(); } } else if ((bool)targetTransformToFollow) { base.transform.SetPositionAndRotation(targetTransformToFollow.position, targetTransformToFollow.rotation); } } }