Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PingWheel v0.2.5
PingWheelValheim.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("PingWheelValheim")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PingWheelValheim")] [assembly: AssemblyTitle("PingWheelValheim")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace PingWheelValheim { internal static class CameraUtils { public static Camera GetActiveCamera() { if (!((Object)(object)GameCamera.instance != (Object)null)) { return Camera.main; } return GameCamera.instance.m_camera; } } internal static class PingTrackedTarget { public static Character Resolve(ZDOID zdoid) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (((ZDOID)(ref zdoid)).IsNone() || (Object)(object)ZNetScene.instance == (Object)null) { return null; } GameObject val = ZNetScene.instance.FindInstance(zdoid); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<Character>(); } public static Vector3 HoverPoint(Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) return character.GetTopPoint() + Vector3.up * 0.3f; } } internal static class PingMarkerManager { private static readonly Dictionary<long, GameObject> ActiveMarkers = new Dictionary<long, GameObject>(); public static void Spawn(long senderId, Vector3 worldPos, PingTargetKind kind, ZDOID targetZdoid, string senderName, string targetName, string prefabName, PingCategory category) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (ActiveMarkers.TryGetValue(senderId, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } GameObject val = new GameObject("PingWheel_Marker"); val.transform.position = worldPos + Vector3.up * 0.1f; PingMarkerBehaviour pingMarkerBehaviour = val.AddComponent<PingMarkerBehaviour>(); pingMarkerBehaviour.SenderId = senderId; pingMarkerBehaviour.Init(tracked: (kind == PingTargetKind.Creature) ? PingTrackedTarget.Resolve(targetZdoid) : null, avatar: (kind == PingTargetKind.Creature && PingWheelPlugin.ShowAvatars.Value) ? PingAvatar.Get(prefabName) : null, kind: kind, category: category, senderName: senderName, targetName: targetName, worldPos: worldPos, lifetime: PingWheelPlugin.MarkerLifetime.Value); ActiveMarkers[senderId] = val; PingSound.Play(category); } public static Sprite GetPinSprite(PinType type) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Minimap s_instance = Minimap.s_instance; if ((Object)(object)s_instance == (Object)null || s_instance.m_icons == null) { return null; } foreach (SpriteData icon in s_instance.m_icons) { if (icon.m_name == type) { return icon.m_icon; } } return null; } public static void Release(long senderId, GameObject go) { if (ActiveMarkers.TryGetValue(senderId, out var value) && (Object)(object)value == (Object)(object)go) { ActiveMarkers.Remove(senderId); } } } internal static class PingAvatar { private static readonly Dictionary<string, Sprite> Hits = new Dictionary<string, Sprite>(); private static readonly HashSet<string> Misses = new HashSet<string>(); public static Sprite Get(string prefabName) { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Invalid comparison between Unknown and I4 if (string.IsNullOrEmpty(prefabName) || (Object)(object)ZNetScene.instance == (Object)null) { return null; } if (Hits.TryGetValue(prefabName, out var value)) { if ((Object)(object)value != (Object)null) { return value; } Hits.Remove(prefabName); } if (Misses.Contains(prefabName)) { return null; } Sprite val = null; try { GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); if ((Object)(object)prefab == (Object)null) { return null; } CharacterDrop component = prefab.GetComponent<CharacterDrop>(); if ((Object)(object)component != (Object)null && component.m_drops != null) { foreach (Drop drop in component.m_drops) { ItemDrop val2 = (((Object)(object)drop.m_prefab != (Object)null) ? drop.m_prefab.GetComponent<ItemDrop>() : null); if (!((Object)(object)val2 == (Object)null) && (int)val2.m_itemData.m_shared.m_itemType == 13) { val = val2.m_itemData.GetIcon(); break; } } } } catch (Exception ex) { PingWheelPlugin.Log.LogWarning((object)("Avatar lookup for '" + prefabName + "' failed: " + ex.Message)); return null; } if ((Object)(object)val != (Object)null) { Hits[prefabName] = val; } else { Misses.Add(prefabName); } return val; } } internal class PingMarkerBehaviour : MonoBehaviour { private float _timeLeft; private SpriteRenderer _icon; private Character _tracked; private Vector3 _worldPos; private string _senderName; private string _targetName; private PingCategory _category; private PinData _mapPin; private string _labelCache; private int _labelDistance = -1; private bool _labelRussian; public static readonly List<PingMarkerBehaviour> Active = new List<PingMarkerBehaviour>(); public long SenderId { get; set; } public Sprite AvatarSprite { get; private set; } public Vector3 AnchorPosition => ((Component)this).transform.position + Vector3.up * 1.3f; public Color Color { get; private set; } public string LabelText => ComposeLabelText(); public void Init(PingTargetKind kind, PingCategory category, string senderName, string targetName, Character tracked, Vector3 worldPos, float lifetime, Sprite avatar) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(targetName) && Localization.m_instance != null) { targetName = Localization.m_instance.Localize(targetName); } _timeLeft = lifetime; AvatarSprite = avatar; _tracked = tracked; _worldPos = worldPos; _senderName = senderName; _targetName = targetName; _category = category; Color color = (Color = ((category != PingCategory.Auto) ? PingCategories.Color(category) : KindColor(kind))); Active.Add(this); if (PingWheelPlugin.MapPins.Value) { string text = ((category != PingCategory.Auto) ? PingCategories.Name(category) : string.Empty); string text2 = (string.IsNullOrEmpty(targetName) ? text : ((text.Length > 0) ? (text + " — " + targetName) : targetName)); string name = ((text2.Length > 0) ? (senderName + ": " + text2) : senderName); _mapPin = PingMapPin.Add(worldPos, name, (PinType)12); } GameObject val2 = new GameObject("Icon"); val2.transform.SetParent(((Component)this).transform, false); val2.transform.localPosition = Vector3.up * 1.3f; _icon = val2.AddComponent<SpriteRenderer>(); _icon.sprite = PingMarkerManager.GetPinSprite(PingCategories.Pin(category)); _icon.color = color; float value = PingWheelPlugin.MarkerIconScale.Value; val2.transform.localScale = new Vector3(value, value, value); } private void Update() { try { Tick(); } catch (Exception e) { PingGuard.Report("Marker", e); Object.Destroy((Object)(object)((Component)this).gameObject); } } private void Tick() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) _timeLeft -= Time.deltaTime; if (_timeLeft <= 0f) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } if ((Object)(object)_tracked != (Object)null) { _worldPos = PingTrackedTarget.HoverPoint(_tracked); ((Component)this).transform.position = _worldPos; if (_mapPin != null) { _mapPin.m_pos = ((Component)_tracked).transform.position; } } Camera activeCamera = CameraUtils.GetActiveCamera(); if ((Object)(object)activeCamera != (Object)null && (Object)(object)_icon != (Object)null) { ((Component)_icon).transform.rotation = ((Component)activeCamera).transform.rotation; } } private void OnDestroy() { Active.Remove(this); PingMarkerManager.Release(SenderId, ((Component)this).gameObject); PingMapPin.Remove(_mapPin); } private string ComposeLabelText() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.RoundToInt(((Object)(object)Player.m_localPlayer != (Object)null) ? Vector3.Distance(((Component)Player.m_localPlayer).transform.position, _worldPos) : 0f); bool flag = PingCategories.IsRussian(); if (_labelCache != null && num == _labelDistance && flag == _labelRussian) { return _labelCache; } string text = ((_category != PingCategory.Auto) ? PingCategories.Name(_category) : string.Empty); string text2 = (string.IsNullOrEmpty(_targetName) ? text : ((text.Length > 0) ? (text + " — " + _targetName) : _targetName)); string text3 = ((text2.Length > 0) ? $"{text2} ({num}m)" : $"{num}m"); _labelCache = _senderName + ": " + text3; _labelDistance = num; _labelRussian = flag; return _labelCache; } private static Color KindColor(PingTargetKind kind) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) return (Color)(kind switch { PingTargetKind.Creature => new Color(1f, 0.35f, 0.25f), PingTargetKind.Resource => new Color(0.4f, 1f, 0.4f), PingTargetKind.Piece => new Color(0.4f, 0.75f, 1f), PingTargetKind.Pickable => new Color(0.6f, 1f, 0.85f), _ => Color.yellow, }); } } internal static class PingSender { private static float _lastSentAt = float.NegativeInfinity; public static float CooldownRemaining => Mathf.Max(0f, PingWheelPlugin.PingCooldown.Value - (Time.unscaledTime - _lastSentAt)); public static void NotifyCooldown() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)1, PingCategories.CooldownMessage, 0, (Sprite)null, false); } } public static void TrySendPing(PingCategory category, bool notifyOnCooldown = false) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (CooldownRemaining > 0f) { if (notifyOnCooldown) { NotifyCooldown(); } return; } PingTarget target; try { if (!Targeting.TryGetTarget(out target)) { return; } } catch (Exception e) { PingGuard.Report("Targeting", e); return; } _lastSentAt = Time.unscaledTime; target.Category = category; PingNetwork.SendPing(target); PingWheelPlugin.Log.LogInfo((object)$"Ping sent at {target.Position} category={category} kind={target.Kind} name=\"{target.Name}\" zdoid={target.TargetZdoid}"); } } internal static class PingNetwork { private const string RpcName = "PingWheel_Ping_v2"; private const int MaxNameLength = 64; private const float MaxCoordinate = 30000f; private static readonly Dictionary<long, float> LastReceivedAt = new Dictionary<long, float>(); public static void Register() { LastReceivedAt.Clear(); ZRoutedRpc.instance.Register<ZPackage>("PingWheel_Ping_v2", (Action<long, ZPackage>)RPC_ReceivePing); } public static void SendPing(PingTarget target) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance != null && !((Object)(object)Player.m_localPlayer == (Object)null)) { ZPackage val = new ZPackage(); val.Write(target.Position); val.Write(Player.m_localPlayer.GetPlayerName()); val.Write(target.Name ?? string.Empty); val.Write((int)target.Kind); val.Write(target.TargetZdoid); val.Write(target.PrefabName ?? string.Empty); val.Write((int)target.Category); ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PingWheel_Ping_v2", new object[1] { val }); } } private static void RPC_ReceivePing(long sender, ZPackage pkg) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } float unscaledTime = Time.unscaledTime; if (LastReceivedAt.TryGetValue(sender, out var value) && unscaledTime - value < PingWheelPlugin.PingCooldown.Value * 0.8f) { return; } try { Vector3 val = pkg.ReadVector3(); string text = pkg.ReadString(); string text2 = pkg.ReadString(); int num = pkg.ReadInt(); ZDOID targetZdoid = pkg.ReadZDOID(); string text3 = pkg.ReadString(); int num2 = pkg.ReadInt(); if (!IsSane(val) || text.Length > 64 || text2.Length > 64 || text3.Length > 64 || num < 0 || num > 255 || !Enum.IsDefined(typeof(PingTargetKind), (byte)num) || !Enum.IsDefined(typeof(PingCategory), num2)) { PingWheelPlugin.Log.LogWarning((object)$"Dropped malformed ping from {sender}."); return; } LastReceivedAt[sender] = unscaledTime; PingMarkerManager.Spawn(sender, val, (PingTargetKind)num, targetZdoid, text, text2, text3, (PingCategory)num2); } catch (Exception ex) { PingWheelPlugin.Log.LogWarning((object)$"Dropped unreadable ping from {sender}: {ex.Message}"); } } private static bool IsSane(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z) && Mathf.Abs(v.x) < 30000f && Mathf.Abs(v.y) < 30000f) { return Mathf.Abs(v.z) < 30000f; } return false; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class ZNetAwakePatch { private static void Postfix() { try { PingNetwork.Register(); } catch (Exception arg) { PingWheelPlugin.Log.LogError((object)$"Couldn't register the ping RPC (pings disabled this session): {arg}"); } } } internal static class PingMapPin { private static bool _warned; public static PinData Add(Vector3 pos, string name, PinType type) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) try { Minimap s_instance = Minimap.s_instance; if ((Object)(object)s_instance == (Object)null) { return null; } return s_instance.AddPin(pos, type, name, false, false, 0L, default(PlatformUserID)); } catch (Exception e) { Warn("AddPin", e); return null; } } public static void Remove(PinData pin) { if (pin == null) { return; } try { Minimap s_instance = Minimap.s_instance; if (!((Object)(object)s_instance == (Object)null)) { s_instance.RemovePin(pin); } } catch (Exception e) { Warn("RemovePin", e); } } private static void Warn(string what, Exception e) { if (!_warned) { _warned = true; PingWheelPlugin.Log.LogWarning((object)("Minimap." + what + " failed (logged once): " + e.Message)); } } } internal static class PingOffscreenArrows { private const float Margin = 48f; private const float ArrowSize = 26f; private const float OnScreenLabelDrop = 34f; private static readonly Vector2[] Outline = (Vector2[])(object)new Vector2[4] { new Vector2(-1f, 0f), new Vector2(1f, 0f), new Vector2(0f, -1f), new Vector2(0f, 1f) }; private static Texture2D _arrowTex; private static GUIStyle _labelStyle; private static readonly GUIContent Content = new GUIContent(); private static bool _fontLookupDone; private static Font _font; internal static GUIStyle LabelStyle => _labelStyle; public static void Draw() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) if ((int)Event.current.type != 7 || PingMarkerBehaviour.Active.Count == 0) { return; } Camera activeCamera = CameraUtils.GetActiveCamera(); if ((Object)(object)activeCamera == (Object)null) { return; } EnsureResources(); _labelStyle.fontSize = PingWheelPlugin.LabelFontSize.Value; float num = Screen.width; float num2 = Screen.height; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(num / 2f, num2 / 2f); Vector2 val5 = default(Vector2); foreach (PingMarkerBehaviour item in PingMarkerBehaviour.Active) { if ((Object)(object)item == (Object)null) { continue; } Vector3 val2 = activeCamera.WorldToScreenPoint(item.AnchorPosition); bool flag = val2.z < 0f; if (!flag && val2.x >= 0f && val2.x <= num && val2.y >= 0f && val2.y <= num2) { DrawLabel(new Vector2(val2.x, num2 - val2.y + 34f), item); continue; } Vector2 val3 = new Vector2(val2.x, val2.y) - val; if (flag) { val3 = -val3; } if (((Vector2)(ref val3)).sqrMagnitude < 1f) { val3 = Vector2.up; } float num3 = num / 2f - 48f; float num4 = num2 / 2f - 48f; float num5 = ((Mathf.Abs(val3.x) > 0.001f) ? (num3 / Mathf.Abs(val3.x)) : float.MaxValue); float num6 = ((Mathf.Abs(val3.y) > 0.001f) ? (num4 / Mathf.Abs(val3.y)) : float.MaxValue); Vector2 val4 = val + val3 * Mathf.Min(num5, num6); ((Vector2)(ref val5))..ctor(val4.x, num2 - val4.y); Vector2 val6 = new Vector2(val3.x, 0f - val3.y); Vector2 normalized = ((Vector2)(ref val6)).normalized; float num7 = Mathf.Atan2(normalized.y, normalized.x) * 57.29578f; Color color = GUI.color; Matrix4x4 matrix = GUI.matrix; GUI.color = item.Color; GUIUtility.RotateAroundPivot(num7, val5); GUI.DrawTexture(new Rect(val5.x - 13f, val5.y - 13f, 26f, 26f), (Texture)(object)_arrowTex); GUI.matrix = matrix; GUI.color = color; DrawLabel(val5 - normalized * (32f + (float)_labelStyle.fontSize), item); } } private static void DrawLabel(Vector2 center, PingMarkerBehaviour marker) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) string labelText = marker.LabelText; Content.text = labelText; Vector2 val = _labelStyle.CalcSize(Content); Sprite avatarSprite = marker.AvatarSprite; float num = (((Object)(object)avatarSprite != (Object)null) ? ((float)_labelStyle.fontSize * 1.9f) : 0f); float num2 = (((Object)(object)avatarSprite != (Object)null) ? 5f : 0f); float num3 = num + num2 + val.x; float num4 = Mathf.Max(val.y, num); float num5 = Mathf.Clamp(center.x - num3 / 2f, 4f, Mathf.Max(4f, (float)Screen.width - num3 - 4f)); float num6 = Mathf.Clamp(center.y - num4 / 2f, 4f, Mathf.Max(4f, (float)Screen.height - num4 - 4f)); Color color = GUI.color; if ((Object)(object)avatarSprite != (Object)null && (Object)(object)avatarSprite.texture != (Object)null) { Rect textureRect = avatarSprite.textureRect; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)avatarSprite.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)avatarSprite.texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)avatarSprite.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)avatarSprite.texture).height); GUI.color = Color.white; GUI.DrawTextureWithTexCoords(new Rect(num5, num6 + (num4 - num) / 2f, num, num), (Texture)(object)avatarSprite.texture, val2); } DrawOutlinedText(new Rect(num5 + num + num2, num6 + (num4 - val.y) / 2f, val.x, val.y), labelText, marker.Color, _labelStyle); GUI.color = color; } internal static void DrawOutlinedText(Rect rect, string text, Color color, GUIStyle style) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) Color color2 = GUI.color; GUI.color = Color.black; Vector2[] outline = Outline; foreach (Vector2 val in outline) { GUI.Label(new Rect(((Rect)(ref rect)).x + val.x, ((Rect)(ref rect)).y + val.y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), text, style); } GUI.color = color; GUI.Label(rect, text, style); GUI.color = color2; } internal static void EnsureResources() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_arrowTex == (Object)null) { _arrowTex = new Texture2D(64, 64, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)61 }; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num = (1f - (float)j / 64f) * 32f - Mathf.Abs((float)i - 32f); _arrowTex.SetPixel(j, i, new Color(1f, 1f, 1f, Mathf.Clamp01(num))); } } _arrowTex.Apply(); } if (!_fontLookupDone) { _fontLookupDone = true; Font[] array = Resources.FindObjectsOfTypeAll<Font>(); foreach (Font val in array) { if (((Object)val).name.IndexOf("Averia", StringComparison.OrdinalIgnoreCase) >= 0) { _font = val; if (((Object)val).name.IndexOf("Bold", StringComparison.OrdinalIgnoreCase) >= 0) { break; } } } PingWheelPlugin.Log.LogInfo((object)("Label font: " + (((Object)(object)_font != (Object)null) ? ((Object)_font).name : "IMGUI default"))); } if (_labelStyle == null) { _labelStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, fontStyle = (FontStyle)(!((Object)(object)_font != (Object)null)), wordWrap = false, richText = false }; if ((Object)(object)_font != (Object)null) { _labelStyle.font = _font; } } } } internal static class PingGuard { private static readonly Dictionary<string, float> LastReported = new Dictionary<string, float>(); public static void Report(string where, Exception e) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!LastReported.TryGetValue(where, out var value) || !(realtimeSinceStartup - value < 10f)) { LastReported[where] = realtimeSinceStartup; PingWheelPlugin.Log.LogError((object)$"{where} failed (logged at most every 10 s): {e}"); } } } internal static class PingKeyCheck { private static bool _done; public unsafe static void RunOnce() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) if (!_done && !((Object)(object)Player.m_localPlayer == (Object)null)) { _done = true; KeyboardShortcut value = PingWheelPlugin.PingKey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; List<string> list = FindConflicts(mainKey); if (list.Count > 0) { PingWheelPlugin.Log.LogWarning((object)(string.Format("PingKey {0} is also bound in the game to: {1}. ", mainKey, string.Join(", ", list)) + "Both will fire on the same press; pick another key in the mod config.")); } bool flag = PingCategories.IsRussian(); string text = string.Empty; if (!PingWheelPlugin.HintShown.Value) { PingWheelPlugin.HintShown.Value = true; text = (flag ? $"PingWheel: клавиша пинга - {mainKey} (нажатие - пинг, удержание - колесо). Сменить можно в конфиге мода (PingKey, F1)." : $"PingWheel: the ping key is {mainKey} (tap = ping, hold = wheel). Change it in the mod config (PingKey, F1)."); } if (list.Count > 0 && PingWheelPlugin.ConflictWarnedFor.Value != ((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString()) { PingWheelPlugin.ConflictWarnedFor.Value = ((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString(); string text2 = (flag ? string.Format("PingWheel: {0} уже занята игрой ({1}). Смени PingKey в конфиге.", mainKey, string.Join(", ", list)) : string.Format("PingWheel: {0} is already used by the game ({1}). Change PingKey in the config.", mainKey, string.Join(", ", list))); text = ((text.Length > 0) ? (text + "\n" + text2) : text2); } if (text.Length > 0) { ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } } } private static List<string> FindConflicts(KeyCode key) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string>(); try { string text = ToInputSystemPath(key); ZInput instance = ZInput.m_instance; if (text == null || instance == null || instance.m_buttons == null) { return list; } foreach (KeyValuePair<string, ButtonDef> button in instance.m_buttons) { ButtonDef value = button.Value; object obj = ((object)value)?.GetType().GetProperty("ButtonAction", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(value); if (!(obj?.GetType().GetProperty("bindings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj) is IEnumerable enumerable)) { continue; } foreach (object item in enumerable) { if (string.Equals(item?.GetType().GetProperty("effectivePath", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item) as string, text, StringComparison.OrdinalIgnoreCase)) { list.Add(string.IsNullOrEmpty(value.Name) ? button.Key : value.Name); break; } } } } catch (Exception ex) { PingWheelPlugin.Log.LogInfo((object)("Couldn't inspect the game's key bindings (skipping conflict check): " + ex.Message)); } return list; } private unsafe static string ToInputSystemPath(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected I4, but got Unknown if ((int)key <= 96) { if ((int)key == 13) { return "<Keyboard>/enter"; } if ((int)key == 96) { return "<Keyboard>/backquote"; } } else { if ((int)key == 305) { return "<Keyboard>/rightCtrl"; } if ((int)key == 306) { return "<Keyboard>/leftCtrl"; } switch (key - 323) { case 0: return "<Mouse>/leftButton"; case 1: return "<Mouse>/rightButton"; case 2: return "<Mouse>/middleButton"; case 3: return "<Mouse>/backButton"; case 4: return "<Mouse>/forwardButton"; } } string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); if (text.Length == 1 && char.IsLetter(text[0])) { return "<Keyboard>/" + char.ToLowerInvariant(text[0]); } if (text.StartsWith("Alpha") && text.Length == 6) { return "<Keyboard>/" + text[5]; } if (text.StartsWith("Mouse") || text.StartsWith("Joystick")) { return null; } return "<Keyboard>/" + char.ToLowerInvariant(text[0]) + text.Substring(1); } } internal static class PingSound { private struct Note { public float Freq; public float Start; public float Duration; public float OvertoneMul; public float OvertoneGain; public Note(float freq, float start, float duration, float overtoneMul, float overtoneGain) { Freq = freq; Start = start; Duration = duration; OvertoneMul = overtoneMul; OvertoneGain = overtoneGain; } } private const int SampleRate = 44100; private static readonly Dictionary<PingCategory, AudioClip> Clips = new Dictionary<PingCategory, AudioClip>(); private static AudioSource _source; public static void Play(PingCategory category) { if (!PingWheelPlugin.PingSounds.Value) { return; } float value = PingWheelPlugin.PingSoundVolume.Value; if (value <= 0f) { return; } try { AudioSource source = GetSource(); AudioClip clip = GetClip(category); if ((Object)(object)source != (Object)null && (Object)(object)clip != (Object)null) { source.PlayOneShot(clip, value); } } catch (Exception ex) { PingWheelPlugin.Log.LogWarning((object)("Ping sound failed (logged once): " + ex.Message)); PingWheelPlugin.PingSounds.Value = false; } } private static AudioSource GetSource() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_source != (Object)null) { return _source; } _source = new GameObject("PingWheel_Audio") { hideFlags = (HideFlags)61 }.AddComponent<AudioSource>(); _source.playOnAwake = false; _source.spatialBlend = 0f; AudioMan instance = AudioMan.m_instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_guiMixer != (Object)null) { _source.outputAudioMixerGroup = instance.m_guiMixer; } return _source; } private static AudioClip GetClip(PingCategory category) { if (Clips.TryGetValue(category, out var value) && (Object)(object)value != (Object)null) { return value; } value = Build(category); Clips[category] = value; return value; } private static AudioClip Build(PingCategory category) { Note[] array = category switch { PingCategory.Attack => new Note[2] { new Note(330f, 0f, 0.16f, 2f, 0.12f), new Note(330f, 0.18f, 0.2f, 2f, 0.12f) }, PingCategory.ComeHere => new Note[2] { new Note(494f, 0f, 0.2f, 2f, 0.1f), new Note(740f, 0.18f, 0.38f, 2f, 0.1f) }, PingCategory.Danger => new Note[4] { new Note(392f, 0f, 0.18f, 2f, 0.12f), new Note(311f, 0.2f, 0.18f, 2f, 0.12f), new Note(392f, 0.4f, 0.18f, 2f, 0.12f), new Note(311f, 0.6f, 0.26f, 2f, 0.12f) }, _ => new Note[2] { new Note(660f, 0f, 0.5f, 2f, 0.12f), new Note(990f, 0f, 0.4f, 2f, 0.06f) }, }; float num = 0f; Note[] array2 = array; for (int i = 0; i < array2.Length; i++) { Note note = array2[i]; num = Mathf.Max(num, note.Start + note.Duration); } float[] array3 = new float[Mathf.CeilToInt((num + 0.05f) * 44100f)]; array2 = array; for (int i = 0; i < array2.Length; i++) { Note note2 = array2[i]; int num2 = Mathf.FloorToInt(note2.Start * 44100f); int num3 = Mathf.CeilToInt(note2.Duration * 44100f); for (int j = 0; j < num3 && num2 + j < array3.Length; j++) { float num4 = (float)j / 44100f; float num5 = Mathf.Clamp01(num4 / 0.015f); float num6 = num5 * num5 * (3f - 2f * num5) * Mathf.Exp(-4f * num4 / note2.Duration); float num7 = MathF.PI * 2f * note2.Freq * num4; float num8 = Mathf.Sin(num7) + note2.OvertoneGain * Mathf.Sin(num7 * note2.OvertoneMul); array3[num2 + j] += num8 * num6; } } float num9 = 0.0001f; float[] array4 = array3; foreach (float num10 in array4) { num9 = Mathf.Max(num9, Mathf.Abs(num10)); } float num11 = 0.45f / num9; for (int k = 0; k < array3.Length; k++) { array3[k] *= num11; } AudioClip obj = AudioClip.Create($"PingWheel_{category}", array3.Length, 1, 44100, false); obj.SetData(array3, 0); ((Object)obj).hideFlags = (HideFlags)61; return obj; } } internal enum PingCategory { Auto, Attack, ComeHere, Attention, Danger } internal static class PingCategories { public static readonly PingCategory[] WheelOrder = new PingCategory[4] { PingCategory.Attack, PingCategory.ComeHere, PingCategory.Attention, PingCategory.Danger }; public static string AutoLabel { get { if (!IsRussian()) { return "AUTO"; } return "АВТО"; } } public static string CooldownMessage { get { if (!IsRussian()) { return "Ping on cooldown"; } return "Пинг перезаряжается"; } } public static string Name(PingCategory c) { bool flag = IsRussian(); switch (c) { case PingCategory.Attack: if (!flag) { return "ATTACK"; } return "АТАКУЮ"; case PingCategory.ComeHere: if (!flag) { return "COME HERE"; } return "ИДИ СЮДА"; case PingCategory.Attention: if (!flag) { return "ATTENTION"; } return "ВНИМАНИЕ"; case PingCategory.Danger: if (!flag) { return "DANGER"; } return "ОПАСНОСТЬ"; default: return string.Empty; } } internal static bool IsRussian() { Localization instance = Localization.m_instance; if (instance != null) { return string.Equals(instance.GetSelectedLanguage(), "Russian", StringComparison.OrdinalIgnoreCase); } return false; } public static Color Color(PingCategory c) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) return (Color)(c switch { PingCategory.Attack => new Color(1f, 0.3f, 0.25f), PingCategory.ComeHere => new Color(0.35f, 0.8f, 1f), PingCategory.Attention => new Color(1f, 0.9f, 0.3f), PingCategory.Danger => new Color(1f, 0.55f, 0.1f), _ => Color.white, }); } public static PinType Pin(PingCategory c) { return (PinType)(c switch { PingCategory.Attack => 9, PingCategory.ComeHere => 3, PingCategory.Danger => 4, _ => 12, }); } } internal static class PingWheelController { private const float DeadZone = 0.35f; private static bool _held; private static float _heldFor; private static Vector2 _cursor; private static bool _axisWarned; private static Texture2D _wedgeTex; private static Texture2D _discTex; public static bool IsOpen { get; private set; } private static float Radius => Mathf.Max(120f, (float)Screen.height * 0.17f); public static void Tick() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; KeyboardShortcut value = PingWheelPlugin.PingKey.Value; if (_held && (!Application.isFocused || !((Character)localPlayer).TakeInput())) { Reset(); } else { if (!_held && !((Character)localPlayer).TakeInput()) { return; } if (!PingWheelPlugin.WheelEnabled.Value) { if (PingWheelPlugin.IsShortcutDown(value)) { PingSender.TrySendPing(PingCategory.Auto, notifyOnCooldown: true); } return; } if (!_held) { if (PingWheelPlugin.IsShortcutDown(value)) { if (PingSender.CooldownRemaining > 0f) { PingSender.NotifyCooldown(); return; } _held = true; _heldFor = 0f; _cursor = Vector2.zero; } return; } _heldFor += Time.unscaledDeltaTime; if (Input.GetKeyDown((KeyCode)27)) { Reset(); return; } bool flag = !Input.GetKey(((KeyboardShortcut)(ref value)).MainKey); if (!IsOpen && !flag && _heldFor >= PingWheelPlugin.WheelHoldSeconds.Value) { IsOpen = true; } if (IsOpen) { MoveCursor(); } if (flag) { PingCategory category = (IsOpen ? Selected() : PingCategory.Auto); Reset(); PingSender.TrySendPing(category); } } } public static void Cancel() { Reset(); } private static void Reset() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) _held = false; IsOpen = false; _cursor = Vector2.zero; } private static void MoveCursor() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) try { Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")); _cursor += val * PingWheelPlugin.WheelSensitivity.Value; } catch (ArgumentException ex) { if (!_axisWarned) { _axisWarned = true; PingWheelPlugin.Log.LogWarning((object)("Mouse axes unavailable, wheel can't be steered: " + ex.Message)); } } float radius = Radius; if (((Vector2)(ref _cursor)).magnitude > radius) { _cursor = ((Vector2)(ref _cursor)).normalized * radius; } } private static PingCategory Selected() { if (((Vector2)(ref _cursor)).magnitude < Radius * 0.35f) { return PingCategory.Auto; } float num = Mathf.Atan2(_cursor.x, _cursor.y) * 57.29578f; if (num < 0f) { num += 360f; } int num2 = (int)((num + 45f) / 90f) % 4; return PingCategories.WheelOrder[num2]; } public static void Draw() { //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen || (int)Event.current.type != 7) { return; } EnsureTextures(); PingOffscreenArrows.EnsureResources(); float radius = Radius; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor((float)Screen.width / 2f, (float)Screen.height / 2f); PingCategory pingCategory = Selected(); Color color = GUI.color; Matrix4x4 matrix = GUI.matrix; for (int i = 0; i < 4; i++) { PingCategory num = PingCategories.WheelOrder[i]; bool flag = num == pingCategory; Color val2 = PingCategories.Color(num); GUI.color = (flag ? new Color(val2.r, val2.g, val2.b, 0.85f) : new Color(0.05f, 0.05f, 0.05f, 0.62f)); GUIUtility.RotateAroundPivot(90f * (float)i, val); GUI.DrawTexture(new Rect(val.x - radius, val.y - radius, radius * 2f, radius * 2f), (Texture)(object)_wedgeTex); GUI.matrix = matrix; } GUI.color = new Color(0.05f, 0.05f, 0.05f, 0.62f); float num2 = radius * 0.35f * 2f; GUI.DrawTexture(new Rect(val.x - num2 / 2f, val.y - num2 / 2f, num2, num2), (Texture)(object)_discTex); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(val.x + _cursor.x, val.y - _cursor.y); GUI.color = ((pingCategory == PingCategory.Auto) ? Color.white : PingCategories.Color(pingCategory)); GUI.DrawTexture(new Rect(val3.x - 5f, val3.y - 5f, 10f, 10f), (Texture)(object)_discTex); GUIStyle labelStyle = PingOffscreenArrows.LabelStyle; int fontSize = labelStyle.fontSize; try { labelStyle.fontSize = PingWheelPlugin.LabelFontSize.Value + 2; labelStyle.alignment = (TextAnchor)4; Vector2 val4 = default(Vector2); for (int j = 0; j < 4; j++) { PingCategory pingCategory2 = PingCategories.WheelOrder[j]; float num3 = (float)j * 90f * (MathF.PI / 180f); ((Vector2)(ref val4))..ctor(val.x + Mathf.Sin(num3) * radius * 0.68f, val.y - Mathf.Cos(num3) * radius * 0.68f); PingOffscreenArrows.DrawOutlinedText(new Rect(val4.x - radius * 0.5f, val4.y - 14f, radius, 28f), PingCategories.Name(pingCategory2), (pingCategory2 == pingCategory) ? Color.white : PingCategories.Color(pingCategory2), labelStyle); } string text = ((pingCategory == PingCategory.Auto) ? PingCategories.AutoLabel : PingCategories.Name(pingCategory)); PingOffscreenArrows.DrawOutlinedText(new Rect(val.x - num2 / 2f, val.y - 12f, num2, 24f), text, Color.white, labelStyle); } finally { labelStyle.fontSize = fontSize; labelStyle.alignment = (TextAnchor)3; GUI.color = color; GUI.matrix = matrix; } } private static void EnsureTextures() { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_wedgeTex != (Object)null) { return; } float num = 128f; float num2 = num * 0.35f + 6f; float num3 = num - 2f; _wedgeTex = NewTexture(256); _discTex = NewTexture(256); for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { float num4 = (float)j + 0.5f - num; float num5 = (float)i + 0.5f - num; float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5); float num7 = Mathf.Atan2(num4, num5) * 57.29578f; float num8 = (42.8f - Mathf.Abs(num7)) * (MathF.PI / 180f) * num6; float num9 = Mathf.Clamp01(Mathf.Min(new float[3] { num6 - num2, num3 - num6, num8 })); _wedgeTex.SetPixel(j, i, new Color(1f, 1f, 1f, num9)); _discTex.SetPixel(j, i, new Color(1f, 1f, 1f, Mathf.Clamp01(num - 2f - num6))); } } _wedgeTex.Apply(); _discTex.Apply(); } private static Texture2D NewTexture(int size) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown return new Texture2D(size, size, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)61 }; } } [HarmonyPatch(typeof(PlayerController), "TakeInput")] internal static class PlayerControllerTakeInputPatch { private static void Postfix(bool __0, ref bool __result) { try { if (__0 && PingWheelController.IsOpen) { __result = false; } } catch (Exception e) { PingGuard.Report("TakeInput patch", e); } } } [BepInPlugin("com.pingwheel.valheim", "PingWheel", "0.2.5")] public class PingWheelPlugin : BaseUnityPlugin { public const string PluginGuid = "com.pingwheel.valheim"; public const string PluginName = "PingWheel"; public const string PluginVersion = "0.2.5"; internal static ManualLogSource Log; internal static ConfigEntry<KeyboardShortcut> PingKey; internal static ConfigEntry<float> MaxDistance; internal static ConfigEntry<float> MarkerLifetime; internal static ConfigEntry<bool> EnemiesOnly; internal static ConfigEntry<bool> DetectResources; internal static ConfigEntry<bool> DetectPieces; internal static ConfigEntry<bool> DetectPickables; internal static ConfigEntry<float> MarkerIconScale; internal static ConfigEntry<int> LabelFontSize; internal static ConfigEntry<bool> ShowAvatars; internal static ConfigEntry<float> PingCooldown; internal static ConfigEntry<bool> WheelEnabled; internal static ConfigEntry<float> WheelHoldSeconds; internal static ConfigEntry<float> WheelSensitivity; internal static ConfigEntry<bool> PingSounds; internal static ConfigEntry<float> PingSoundVolume; internal static ConfigEntry<bool> HintShown; internal static ConfigEntry<string> ConflictWarnedFor; internal static ConfigEntry<bool> MapPins; internal static ConfigEntry<bool> OffscreenArrows; private Harmony _harmony; private ConfigEntry<float> BindRange(string section, string key, float def, float min, float max, string description) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, def, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())); } private ConfigEntry<int> BindRangeInt(string section, string key, int def, int min, int max, string description) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<int>(section, key, def, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>())); } private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; PingKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "PingKey", new KeyboardShortcut((KeyCode)122, Array.Empty<KeyCode>()), "Key that sends a ping at whatever is under the crosshair."); MaxDistance = BindRange("General", "MaxDistance", 50f, 5f, 200f, "Maximum raycast distance for target detection, in meters."); MarkerLifetime = BindRange("General", "MarkerLifetime", 10f, 1f, 120f, "How long a received ping marker stays visible, in seconds."); EnemiesOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnemiesOnly", true, "If true, only creatures hostile to you count as Creature pings (tamed animals, passive wildlife, other players, NPCs like traders are pinged as plain ground instead). If false, any creature counts."); DetectResources = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DetectResources", true, "If false, resource nodes (ore, trees, rocks) ping as plain ground instead of being called out as a Resource."); DetectPieces = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DetectPieces", true, "If false, placed building pieces (walls, floors, ...) ping as plain ground instead of being called out as a Piece."); DetectPickables = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DetectPickables", true, "If false, pickable items (berries, mushrooms, dropped loot, ...) ping as plain ground instead of being called out as Pickable."); MarkerIconScale = BindRange("General", "MarkerIconScale", 1f, 0.1f, 10f, "World-space scale of the marker icon (the same sprite Valheim's own map ping uses). It's a UI sprite reused in 3D, so the right size is a matter of taste - tune live via ConfigurationManager, no rebuild needed."); LabelFontSize = BindRangeInt("General", "LabelFontSize", 20, 8, 64, "Font size in pixels of the ping label (sender, target, distance). Drawn as HUD text on top of the game view so it stays crisp at any range. The creature portrait scales with it. Tune live via ConfigurationManager."); ShowAvatars = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowAvatars", true, "Show a small portrait of the pinged creature (its trophy icon, e.g. boar tusk for a boar) next to the ping label."); PingCooldown = BindRange("General", "PingCooldown", 1.5f, 0f, 30f, "Minimum seconds between your own pings (anti-spam). Incoming pings from any one player are also dropped if they arrive faster than this (with a little slack for network jitter), so a modified client can't flood you."); WheelEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Wheel", "WheelEnabled", true, "Hold the ping key to open the radial menu (attack / come here / attention / danger), move the mouse to pick, release to send. A quick tap or releasing in the middle sends a normal auto ping. If false, the key just sends an auto ping immediately."); WheelHoldSeconds = BindRange("Wheel", "WheelHoldSeconds", 0.2f, 0f, 2f, "How long the ping key must be held before the wheel appears."); WheelSensitivity = BindRange("Wheel", "WheelSensitivity", 4f, 0.1f, 50f, "How far the wheel's cursor moves per unit of mouse movement."); PingSounds = ((BaseUnityPlugin)this).Config.Bind<bool>("Sound", "PingSounds", true, "Play a short cue when a ping arrives (your own too). Each category has its own sound: attack, come here, attention/auto, danger."); PingSoundVolume = BindRange("Sound", "PingSoundVolume", 0.35f, 0f, 1f, "Volume of the ping cue, on top of the game's own SFX volume slider."); MapPins = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "MapPins", true, "Also put each ping on the map as a pin (removed when the ping expires or the same player pings again)."); OffscreenArrows = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OffscreenArrows", true, "Draw an arrow with label on the screen edge pointing at pings that are off-screen or behind you."); HintShown = ((BaseUnityPlugin)this).Config.Bind<bool>("Internal", "HintShown", false, "Internal: set once the first-run hint about the ping key has been shown. Don't edit."); ConflictWarnedFor = ((BaseUnityPlugin)this).Config.Bind<string>("Internal", "ConflictWarnedFor", string.Empty, "Internal: the key we last warned about (already used by the game). Don't edit."); _harmony = new Harmony("com.pingwheel.valheim"); _harmony.PatchAll(); Log.LogInfo((object)"PingWheel 0.2.5 loaded."); } private void OnGUI() { try { if (!((Object)(object)Player.m_localPlayer == (Object)null) && !PingGameState.IsUiCoveringWorld()) { if (OffscreenArrows.Value) { PingOffscreenArrows.Draw(); } PingWheelController.Draw(); } } catch (Exception e) { PingGuard.Report("OnGUI", e); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { try { if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null) { PingWheelController.Cancel(); return; } PingKeyCheck.RunOnce(); PingWheelController.Tick(); } catch (Exception e) { PingWheelController.Cancel(); PingGuard.Report("Update", e); } } internal static bool IsShortcutDown(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!Input.GetKey(modifier)) { return false; } } return true; } } internal static class PingGameState { public static bool IsUiCoveringWorld() { if (!Minimap.IsOpen() && !InventoryGui.IsVisible() && !Menu.IsVisible() && !StoreGui.IsVisible() && !TextInput.IsVisible() && !Console.IsVisible()) { return Hud.IsUserHidden(); } return true; } } internal enum PingTargetKind : byte { Ground, Creature, Resource, Piece, Pickable } internal struct PingTarget { public Vector3 Position; public PingTargetKind Kind; public string Name; public string PrefabName; public PingCategory Category; public ZDOID TargetZdoid; } internal static class Targeting { private static readonly RaycastHit[] HitBuffer = (RaycastHit[])(object)new RaycastHit[32]; public static bool TryGetTarget(out PingTarget target) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) target = default(PingTarget); Camera activeCamera = CameraUtils.GetActiveCamera(); if ((Object)(object)activeCamera == (Object)null) { return false; } float value = PingWheelPlugin.MaxDistance.Value; Ray ray = default(Ray); ((Ray)(ref ray))..ctor(((Component)activeCamera).transform.position, ((Component)activeCamera).transform.forward); int mask = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.m_interactMask : (-5)); if (TryRaycast(ray, value, mask, out var best)) { target.Position = ((RaycastHit)(ref best)).point; target.Kind = ClassifyHit(((RaycastHit)(ref best)).collider, out var name, out var zdoid, out var prefabName); target.Name = name; target.TargetZdoid = zdoid; target.PrefabName = prefabName; } else { target.Position = ((Ray)(ref ray)).origin + ((Ray)(ref ray)).direction * value; target.Kind = PingTargetKind.Ground; target.Name = string.Empty; } return true; } private static bool TryRaycast(Ray ray, float maxDistance, int mask, out RaycastHit best) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) best = default(RaycastHit); int num = Physics.RaycastNonAlloc(ray, HitBuffer, maxDistance, mask); Player localPlayer = Player.m_localPlayer; bool result = false; float num2 = float.MaxValue; for (int i = 0; i < num; i++) { RaycastHit val = HitBuffer[i]; if ((!((Object)(object)localPlayer != (Object)null) || !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)localPlayer).transform)) && ((RaycastHit)(ref val)).distance < num2) { num2 = ((RaycastHit)(ref val)).distance; best = val; result = true; } } return result; } private static PingTargetKind ClassifyHit(Collider collider, out string name, out ZDOID zdoid, out string prefabName) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) name = string.Empty; zdoid = default(ZDOID); prefabName = string.Empty; Character componentInParent = ((Component)collider).GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null && IsRelevantCreature(componentInParent)) { name = ((!string.IsNullOrEmpty(componentInParent.m_name)) ? componentInParent.m_name : GetHoverName(collider)); zdoid = componentInParent.GetZDOID(); prefabName = ((Object)((Component)componentInParent).gameObject).name.Replace("(Clone)", string.Empty).Trim(); return PingTargetKind.Creature; } if (PingWheelPlugin.DetectPickables.Value && (Object)(object)((Component)collider).GetComponentInParent<Pickable>() != (Object)null) { name = GetHoverName(collider); return PingTargetKind.Pickable; } if (PingWheelPlugin.DetectResources.Value && ((Object)(object)((Component)collider).GetComponentInParent<MineRock5>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<Destructible>() != (Object)null)) { name = RawName(collider); return PingTargetKind.Resource; } if (PingWheelPlugin.DetectPieces.Value && (Object)(object)((Component)collider).GetComponentInParent<WearNTear>() != (Object)null) { name = RawName(collider); return PingTargetKind.Piece; } return PingTargetKind.Ground; } private static string RawName(Collider collider) { Piece componentInParent = ((Component)collider).GetComponentInParent<Piece>(); if ((Object)(object)componentInParent != (Object)null && !string.IsNullOrEmpty(componentInParent.m_name)) { return componentInParent.m_name; } MineRock5 componentInParent2 = ((Component)collider).GetComponentInParent<MineRock5>(); if ((Object)(object)componentInParent2 != (Object)null && !string.IsNullOrEmpty(componentInParent2.m_name)) { return componentInParent2.m_name; } MineRock componentInParent3 = ((Component)collider).GetComponentInParent<MineRock>(); if ((Object)(object)componentInParent3 != (Object)null && !string.IsNullOrEmpty(componentInParent3.m_name)) { return componentInParent3.m_name; } ResourceRoot componentInParent4 = ((Component)collider).GetComponentInParent<ResourceRoot>(); if ((Object)(object)componentInParent4 != (Object)null && !string.IsNullOrEmpty(componentInParent4.m_name)) { return componentInParent4.m_name; } HoverText componentInParent5 = ((Component)collider).GetComponentInParent<HoverText>(); if ((Object)(object)componentInParent5 != (Object)null && !string.IsNullOrEmpty(componentInParent5.m_text)) { return componentInParent5.m_text; } return GetHoverName(collider); } private static string GetHoverName(Collider collider) { Hoverable componentInParent = ((Component)collider).GetComponentInParent<Hoverable>(); if (componentInParent == null) { return string.Empty; } return componentInParent.GetHoverName(); } private static bool IsRelevantCreature(Character character) { if (!PingWheelPlugin.EnemiesOnly.Value) { return true; } if (character.IsPlayer()) { return false; } BaseAI component = ((Component)character).GetComponent<BaseAI>(); if ((Object)(object)component != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { return component.IsEnemy((Character)(object)Player.m_localPlayer); } return false; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }