Decompiled source of UniversalCooldownUI v1.1.5
plugins\UniversalCooldownUI.dll
Decompiled 6 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using Microsoft.CodeAnalysis; using ProjectM.Network; using ProjectM.UI; using TMPro; using Unity.Collections; using Unity.Entities; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("UniversalCooldownUI")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Bloodcraft fix for V Rising 1.1.15: cooldown recovery in tooltips, weapon bonuses and a native Blood tab in the character window.")] [assembly: AssemblyFileVersion("1.1.5.0")] [assembly: AssemblyInformationalVersion("1.1.5")] [assembly: AssemblyProduct("UniversalCooldownUI")] [assembly: AssemblyTitle("UniversalCooldownUI")] [assembly: AssemblyVersion("1.1.5.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace UniversalCooldownUI { internal static class BuffsTab { internal sealed class Section { public string Kind = ""; public string Title = ""; public readonly List<KeyValuePair<string, string>> Rows = new List<KeyValuePair<string, string>>(); } private const string DataFilePrefix = "universalcooldown_buffs"; private static readonly Color TextColor = new Color(1f, 1f, 1f, 0.92f); private static Color _green = new Color(0.42f, 0.85f, 0.33f); private static InventorySubMenu _menu; private static GameObject _root; private static Transform _content; private static CanvasGroup _windowGroup; private static SimpleStunButton _button; private static TMP_Text _buttonLabel; private static RectTransform _buttonRect; private static Sprite _normalSprite; private static Sprite _selectedSprite; private static Color _normalColor = Color.white; private static Color _selectedColor = Color.white; private static Image _highlight; private static GameObject _headerTemplate; private static GameObject _dividerTemplate; private static GameObject _rowTemplate; private static readonly List<SimpleStunButton> VanillaButtons = new List<SimpleStunButton>(); private static readonly List<(TMP_Text Text, string Value)> Enforced = new List<(TMP_Text, string)>(); private static List<Section> _lastSections = new List<Section>(); private static List<Section> _remoteSections = new List<Section>(); private static float _lastDataTime = -999f; private static bool _built; private static bool _active; private static bool _nativeTab; private static int _tabIndex = -1; private static int _lastTab = -99; private static int _lastClickFrame = -1; private static int _layoutFrames; private static string _signature = string.Empty; private static float _nextRefresh; private static int _tickFrame = -1; private static float _nextEnforce; private static DateTime _fileStamp = DateTime.MinValue; private static ulong _localId; private static float _nextIdTry; private static int _warmStage; private static int _warmFrame; private static int _warmPrevTab; private static int _warmRetryAt; internal static ulong LocalSteamId => _localId; internal static void Bind(InventorySubMenu menu) { if ((Object)(object)menu != (Object)null) { _menu = menu; } } internal static void Rebind(InventorySubMenu menu) { try { CleanupExisting(menu); } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] cleanup: " + ex.Message)); } ResetState(); _remoteSections.Clear(); _lastSections.Clear(); _signature = string.Empty; _fileStamp = DateTime.MinValue; _lastDataTime = -999f; _warmStage = 0; _warmRetryAt = 0; _menu = menu; } internal static void Tick(World world) { try { if ((Object)(object)_menu == (Object)null || !Plugin.BloodTab.Value) { return; } ChatSync.SetWorld(world); ChatSync.AutoPoll(); if (_localId == 0L && world != null) { TryResolveLocalId(world); } int frameCount = Time.frameCount; if (frameCount == _tickFrame) { return; } _tickFrame = frameCount; if (_built && ((Object)(object)_root == (Object)null || (Object)(object)_button == (Object)null)) { ResetState(); } bool activeInHierarchy = ((Component)_menu).gameObject.activeInHierarchy; if (activeInHierarchy && !_built) { TryBuild(); } if (_built) { WarmUpTemplates(); if (activeInHierarchy) { PollClicks(); } RefreshFromServer(); ApplyNativeState(); EnforceTexts(); if (_active && _layoutFrames > 0) { _layoutFrames--; RebuildLayout(); } } } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] tick: " + ex.Message)); } } private static void ApplyNativeState() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown int num = -1; try { num = _menu.CurrentTab; } catch { } _lastTab = num; if (!_nativeTab || _tabIndex < 0) { return; } bool flag = num == _tabIndex; if (flag && !_active) { _active = true; Rebuild(ReadServerSections()); _layoutFrames = 3; if (Time.time - _lastDataTime > 10f) { ChatSync.Request(); } LogLayout(); ManualLogSource l = Plugin.L; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BuffsTab] opened by the game (tab="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(_tabIndex); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")"); } l.LogInfo(val); } else if (!flag && _active) { _active = false; } } private static void RefreshFromServer() { if (!_active || Time.time < _nextRefresh) { return; } _nextRefresh = Time.time + 1f; DateTime dateTime = DateTime.MinValue; string path = DataFileFor(_localId); try { if (File.Exists(path)) { dateTime = File.GetLastWriteTimeUtc(path); } } catch { } if (dateTime != _fileStamp) { _fileStamp = dateTime; List<Section> sections = ReadServerSections(); if (Signature(sections) != _signature) { Rebuild(sections); } } else if (Enforced.Count == 0) { Rebuild(ReadServerSections()); } if (_remoteSections.Count == 0 || Time.time - _lastDataTime > 10f) { ChatSync.Request(); } } private static void EnforceTexts() { if (!_active || Enforced.Count == 0 || Time.time < _nextEnforce) { return; } _nextEnforce = Time.time + 0.25f; for (int i = 0; i < Enforced.Count; i++) { (TMP_Text, string) tuple = Enforced[i]; if (!((Object)(object)tuple.Item1 == (Object)null) && tuple.Item1.text != tuple.Item2) { tuple.Item1.text = tuple.Item2; } } } private static void ResetState() { _built = false; _active = false; _nativeTab = false; _tabIndex = -1; _built = false; _root = null; _content = null; _button = null; _buttonLabel = null; _buttonRect = null; _highlight = null; _windowGroup = null; _headerTemplate = null; _dividerTemplate = null; _rowTemplate = null; VanillaButtons.Clear(); Enforced.Clear(); } private static void TryBuild() { //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_019f: 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_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) try { CleanupExisting(_menu); } catch { } Il2CppReferenceArray<SimpleStunButton> tabButtons = _menu.TabButtons; Il2CppReferenceArray<RectTransform> tabs = _menu.Tabs; if (tabButtons == null || ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length == 0 || tabs == null || ((Il2CppArrayBase<RectTransform>)(object)tabs).Length == 0) { return; } int num = ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length - 1; SimpleStunButton val = ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[num]; Transform parent = ((Component)val).transform.parent; int num2 = 0; try { num2 = Mathf.Clamp(_menu.CurrentTab, 0, num); } catch { } Image component = ((Component)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[num2]).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { _selectedSprite = component.sprite; } for (int i = 0; i < ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length; i++) { Image val2 = (((Object)(object)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[i] == (Object)null) ? null : ((Component)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[i]).GetComponent<Image>()); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.sprite == (Object)null) && (Object)(object)_selectedSprite != (Object)null && (Object)(object)val2.sprite != (Object)(object)_selectedSprite) { _normalSprite = val2.sprite; break; } } if ((Object)(object)_selectedSprite == (Object)null) { _selectedSprite = _normalSprite; } if ((Object)(object)_normalSprite == (Object)null) { _normalSprite = _selectedSprite; } TMP_Text componentInChildren = ((Component)val).GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { _selectedColor = ((Graphic)componentInChildren).color; } TMP_Text componentInChildren2 = ((Component)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[0]).GetComponentInChildren<TMP_Text>(true); _normalColor = (((Object)(object)componentInChildren2 != (Object)null && ((Graphic)componentInChildren2).color != _selectedColor) ? ((Graphic)componentInChildren2).color : _selectedColor); Color? val3 = FindGreenValue(((Il2CppArrayBase<RectTransform>)(object)tabs)[num]); if (val3.HasValue) { _green = val3.Value; } GameObject obj3 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent); ((Object)obj3).name = "BloodTabButton"; obj3.SetActive(true); _button = obj3.GetComponent<SimpleStunButton>(); _buttonRect = obj3.GetComponent<RectTransform>(); _buttonLabel = obj3.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)_buttonLabel != (Object)null) { _buttonLabel.text = Localization.TabTitle; _buttonLabel.enableWordWrapping = false; _buttonLabel.enableAutoSizing = true; _buttonLabel.fontSizeMin = 9f; _buttonLabel.fontSizeMax = 20f; _buttonLabel.overflowMode = (TextOverflowModes)0; ((Graphic)_buttonLabel).color = _normalColor; } obj3.transform.SetAsLastSibling(); _highlight = CreateHighlight(obj3.transform); try { ((UnityEventBase)_button.onClick).RemoveAllListeners(); } catch { } for (int j = 0; j < ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length; j++) { VanillaButtons.Add(((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[j]); } ShrinkTabStrip(parent, tabButtons); GameObject gameObject = ((Component)((Il2CppArrayBase<RectTransform>)(object)tabs)[num]).gameObject; _root = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent); ((Object)_root).name = "BloodTab"; _root.SetActive(false); _windowGroup = (((Object)(object)gameObject.transform.parent == (Object)null) ? null : ((Component)gameObject.transform.parent).GetComponent<CanvasGroup>()); AddBackground(_root.transform); _content = FindDeep(_root.transform, "AttributesTabContent"); if ((Object)(object)_content == (Object)null) { Plugin.L.LogWarning((object)"[BuffsTab] AttributesTabContent not found - the tab clone was not built"); return; } ClearContent(); RegisterAsNativeTab(tabButtons, tabs); _built = true; ManualLogSource l = Plugin.L; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(40, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[BuffsTab] tab built (buttons="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", native="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>(_nativeTab); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(")"); } l.LogInfo(val4); Rebuild(ReadServerSections()); } private static void RegisterAsNativeTab(Il2CppReferenceArray<SimpleStunButton> buttons, Il2CppReferenceArray<RectTransform> tabs) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown try { int num = (_tabIndex = ((Il2CppArrayBase<SimpleStunButton>)(object)buttons).Length); Il2CppReferenceArray<SimpleStunButton> val = new Il2CppReferenceArray<SimpleStunButton>((long)(num + 1)); for (int i = 0; i < num; i++) { ((Il2CppArrayBase<SimpleStunButton>)(object)val)[i] = ((Il2CppArrayBase<SimpleStunButton>)(object)buttons)[i]; } ((Il2CppArrayBase<SimpleStunButton>)(object)val)[num] = _button; Il2CppReferenceArray<RectTransform> val2 = new Il2CppReferenceArray<RectTransform>((long)(num + 1)); for (int j = 0; j < ((Il2CppArrayBase<RectTransform>)(object)tabs).Length; j++) { ((Il2CppArrayBase<RectTransform>)(object)val2)[j] = ((Il2CppArrayBase<RectTransform>)(object)tabs)[j]; } ((Il2CppArrayBase<RectTransform>)(object)val2)[num] = _root.GetComponent<RectTransform>(); _menu.TabButtons = val; _menu.Tabs = val2; _nativeTab = true; ManualLogSource l = Plugin.L; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(58, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[BuffsTab] tab registered with the game as index "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(_tabIndex); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" (total "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num + 1); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(")"); } l.LogInfo(val3); } catch (Exception ex) { _nativeTab = false; _tabIndex = -1; _built = false; Plugin.L.LogWarning((object)("[BuffsTab] native registration failed, falling back to overlay: " + ex.Message)); } } private static void ShrinkTabStrip(Transform strip, Il2CppReferenceArray<SimpleStunButton> tabButtons) { //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) if ((Object)(object)strip == (Object)null || tabButtons == null) { return; } int num = ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length + 1; RectTransform component = ((Component)strip).GetComponent<RectTransform>(); HorizontalLayoutGroup component2 = ((Component)strip).GetComponent<HorizontalLayoutGroup>(); float num2 = (((Object)(object)component2 != (Object)null) ? ((HorizontalOrVerticalLayoutGroup)component2).spacing : 0f); float num3; if (!((Object)(object)component != (Object)null)) { num3 = 110f; } else { Rect rect = component.rect; num3 = (((Rect)(ref rect)).width - num2 * (float)(num - 1)) / (float)num; } float num4 = num3; if (num4 < 84f) { num4 = 84f; } List<Transform> list = new List<Transform>(); for (int i = 0; i < ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length; i++) { if ((Object)(object)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[i] != (Object)null) { list.Add(((Component)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[i]).transform); } } if ((Object)(object)_button != (Object)null) { list.Add(((Component)_button).transform); } foreach (Transform item in list) { if (!((Object)(object)item == (Object)null)) { LayoutElement val = ((Component)item).GetComponent<LayoutElement>(); if ((Object)(object)val == (Object)null) { val = ((Component)item).gameObject.AddComponent<LayoutElement>(); } val.preferredWidth = num4; val.flexibleWidth = 0f; TMP_Text componentInChildren = ((Component)item).GetComponentInChildren<TMP_Text>(true); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.enableAutoSizing = true; componentInChildren.fontSizeMin = 9f; componentInChildren.fontSizeMax = 20f; componentInChildren.enableWordWrapping = false; componentInChildren.overflowMode = (TextOverflowModes)0; } } } } private static Image CreateHighlight(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002a: 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_004a: 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_0091: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = new GameObject("BloodTabHighlight"); val.transform.SetParent(parent, false); val.transform.SetAsFirstSibling(); RectTransform obj = val.AddComponent<RectTransform>(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = new Vector2(3f, 4f); obj.offsetMax = new Vector2(-3f, -3f); Image obj2 = val.AddComponent<Image>(); obj2.sprite = null; obj2.type = (Type)0; ((Graphic)obj2).color = new Color(0.62f, 0.1f, 0.12f, 1f); ((Graphic)obj2).raycastTarget = false; val.SetActive(false); return obj2; } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] highlight: " + ex.Message)); return null; } } private static void AddBackground(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_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_0034: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = new GameObject("BloodTabBackground"); val.transform.SetParent(parent, false); val.transform.SetAsFirstSibling(); RectTransform obj = val.AddComponent<RectTransform>(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; Image obj2 = val.AddComponent<Image>(); obj2.sprite = null; obj2.type = (Type)0; ((Graphic)obj2).color = new Color(0.043f, 0.043f, 0.055f, 1f); ((Graphic)obj2).raycastTarget = false; } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] background: " + ex.Message)); } } private static void PollClicks() { //IL_0034: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) try { Mouse current = Mouse.current; if (current == null || !current.leftButton.wasPressedThisFrame) { return; } int frameCount = Time.frameCount; if (frameCount == _lastClickFrame) { return; } Vector2 val = ((InputControl<Vector2>)(object)((Pointer)current).position).ReadValue(); Camera val2 = null; Canvas val3 = (((Object)(object)_button != (Object)null) ? ((Component)_button).GetComponentInParent<Canvas>() : null); if ((Object)(object)val3 != (Object)null && (int)val3.renderMode != 0) { val2 = val3.worldCamera; } if ((Object)(object)_buttonRect != (Object)null && RectTransformUtility.RectangleContainsScreenPoint(_buttonRect, val, val2)) { _lastClickFrame = frameCount; if (_nativeTab) { try { _menu.CurrentTab = _tabIndex; return; } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] native switch failed: " + ex.Message)); _nativeTab = false; return; } } if (!_active) { ActivateOverlay(); } return; } for (int i = 0; i < VanillaButtons.Count; i++) { SimpleStunButton val4 = VanillaButtons[i]; if ((Object)(object)val4 == (Object)null) { continue; } RectTransform component = ((Component)val4).GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null) && RectTransformUtility.RectangleContainsScreenPoint(component, val, val2)) { _lastClickFrame = frameCount; if (!_nativeTab && _active) { DeactivateOverlay(); } break; } } } catch (Exception ex2) { Plugin.L.LogWarning((object)("[BuffsTab] clicks: " + ex2.Message)); } } private static void ActivateOverlay() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) try { if (_built && !((Object)(object)_root == (Object)null)) { Rebuild(ReadServerSections()); _root.SetActive(true); _root.transform.SetAsLastSibling(); _active = true; _layoutFrames = 3; if ((Object)(object)_highlight != (Object)null) { ((Component)_highlight).gameObject.SetActive(true); } if ((Object)(object)_buttonLabel != (Object)null) { ((Graphic)_buttonLabel).color = Color.white; } LogLayout(); } } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] activate: " + ex.Message)); } } private static void DeactivateOverlay() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } _active = false; if ((Object)(object)_highlight != (Object)null) { ((Component)_highlight).gameObject.SetActive(false); } if ((Object)(object)_buttonLabel != (Object)null) { ((Graphic)_buttonLabel).color = _normalColor; } } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] deactivate: " + ex.Message)); } } private static void WarmUpTemplates() { //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown try { if (_warmStage == 2 || _active) { return; } if (_warmStage == 0) { if ((Object)(object)FindRowTemplate() != (Object)null) { _warmStage = 2; } else if (Time.frameCount >= _warmRetryAt) { _warmPrevTab = 0; try { _warmPrevTab = _menu.CurrentTab; } catch { } try { _menu.CurrentTab = 3; } catch { _warmStage = 2; return; } _warmFrame = Time.frameCount; _warmStage = 1; } } else if (_warmStage == 1 && Time.frameCount > _warmFrame + 4) { try { _menu.CurrentTab = _warmPrevTab; } catch { } _warmStage = 2; _rowTemplate = FindRowTemplate(); _headerTemplate = FindTemplate("AttributesHeader"); _dividerTemplate = FindTemplate("HDiv"); ManualLogSource l = Plugin.L; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BuffsTab] templates warmed up: row="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)(object)_rowTemplate == (Object)null) ? "null" : ((Object)_rowTemplate).name); } l.LogInfo(val); if ((Object)(object)_rowTemplate == (Object)null) { _warmStage = 0; _warmRetryAt = Time.frameCount + 90; } } } catch (Exception ex) { _warmStage = 2; Plugin.L.LogWarning((object)("[BuffsTab] warmup: " + ex.Message)); } } private static GameObject FindRowTemplate() { List<CharacterAttributeSection> attributeSections = _menu.AttributeSections; if (attributeSections == null) { return null; } for (int i = 0; i < 3; i++) { for (int j = 0; j < attributeSections.Count; j++) { CharacterAttributeSection val = attributeSections[j]; if ((Object)(object)val == (Object)null) { continue; } Transform val2 = FindDeep(((Component)val).transform, "AttributesContainer"); if ((Object)(object)val2 == (Object)null) { continue; } for (int k = 0; k < val2.childCount; k++) { Transform child = val2.GetChild(k); if (((Component)child).gameObject.activeSelf) { bool flag = ((Object)child).name.EndsWith("(Clone)"); if ((i != 0 || (flag && HasFilledText(child))) && (i != 1 || flag)) { return ((Component)child).gameObject; } } } } } return null; } private static bool HasFilledText(Transform row) { foreach (TMP_Text componentsInChild in ((Component)row).GetComponentsInChildren<TMP_Text>(true)) { if (!((Object)(object)componentsInChild == (Object)null)) { string text = componentsInChild.text; if (!string.IsNullOrEmpty(text) && !text.StartsWith("{") && !(text == "Weapon Level")) { return true; } } } return false; } private static GameObject FindTemplate(string name) { List<CharacterAttributeSection> attributeSections = _menu.AttributeSections; if (attributeSections != null) { for (int i = 0; i < attributeSections.Count; i++) { if (!((Object)(object)attributeSections[i] == (Object)null)) { Transform val = FindDeep(((Component)attributeSections[i]).transform, name); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } } } } Il2CppReferenceArray<RectTransform> tabs = _menu.Tabs; if (tabs == null) { return null; } for (int j = 0; j < ((Il2CppArrayBase<RectTransform>)(object)tabs).Length; j++) { if (!((Object)(object)((Il2CppArrayBase<RectTransform>)(object)tabs)[j] == (Object)null)) { Transform val2 = FindDeep((Transform)(object)((Il2CppArrayBase<RectTransform>)(object)tabs)[j], name); if ((Object)(object)val2 != (Object)null) { return ((Component)val2).gameObject; } } } return null; } private static string DataFileFor(ulong id) { string path = Plugin.SyncDirectory(); if (id != 0L) { string text = Path.Combine(path, $"{"universalcooldown_buffs"}_{id}.txt"); if (File.Exists(text)) { return text; } } return Path.Combine(path, "universalcooldown_buffs.txt"); } private static void TryResolveLocalId(World world) { //IL_001e: 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) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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) //IL_0053: 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_005c: 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_0069: 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) //IL_0070: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown if (Time.time < _nextIdTry) { return; } _nextIdTry = Time.time + 5f; try { EntityManager entityManager = world.EntityManager; EntityQuery val = ((EntityManager)(ref entityManager)).CreateEntityQuery((ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly<LocalUser>() }); NativeArray<Entity> val2 = ((EntityQuery)(ref val)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); try { bool flag = default(bool); for (int i = 0; i < val2.Length; i++) { Entity val3 = val2[i]; if (!((EntityManager)(ref entityManager)).HasComponent<User>(val3)) { continue; } User componentData = ((EntityManager)(ref entityManager)).GetComponentData<User>(val3); if (componentData.PlatformId != 0L) { _localId = componentData.PlatformId; _fileStamp = DateTime.MinValue; ManualLogSource l = Plugin.L; BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(34, 0, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[BuffsTab] local steam id resolved"); } l.LogInfo(val4); break; } } } finally { val2.Dispose(); ((EntityQuery)(ref val)).Dispose(); } } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] local id: " + ex.Message)); } } private static void CleanupExisting(InventorySubMenu menu) { if ((Object)(object)menu == (Object)null) { return; } Il2CppReferenceArray<SimpleStunButton> tabButtons = menu.TabButtons; Il2CppReferenceArray<RectTransform> tabs = menu.Tabs; if (tabs != null) { for (int i = 0; i < ((Il2CppArrayBase<RectTransform>)(object)tabs).Length; i++) { RectTransform val = ((Il2CppArrayBase<RectTransform>)(object)tabs)[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && !(((Object)((Component)val).gameObject).name != "BloodTab")) { ((Component)val).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)val).gameObject); } } } Transform val2 = null; if (tabButtons != null) { for (int j = 0; j < ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length; j++) { if (!((Object)(object)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[j] == (Object)null)) { val2 = ((Component)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[j]).transform.parent; break; } } } if ((Object)(object)val2 != (Object)null) { for (int num = val2.childCount - 1; num >= 0; num--) { Transform child = val2.GetChild(num); if (!((Object)(object)child == (Object)null) && !(((Object)child).name != "BloodTabButton")) { ((Component)child).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)child).gameObject); } } } menu.TabButtons = WithoutOurButtons(tabButtons); menu.Tabs = WithoutOurTabs(tabs); } private static Il2CppReferenceArray<SimpleStunButton> WithoutOurButtons(Il2CppReferenceArray<SimpleStunButton> buttons) { if (buttons == null) { return null; } int num = 0; for (int i = 0; i < ((Il2CppArrayBase<SimpleStunButton>)(object)buttons).Length; i++) { if ((Object)(object)((Il2CppArrayBase<SimpleStunButton>)(object)buttons)[i] != (Object)null && ((Object)((Component)((Il2CppArrayBase<SimpleStunButton>)(object)buttons)[i]).gameObject).name != "BloodTabButton") { num++; } } Il2CppReferenceArray<SimpleStunButton> val = new Il2CppReferenceArray<SimpleStunButton>((long)num); int num2 = 0; for (int j = 0; j < ((Il2CppArrayBase<SimpleStunButton>)(object)buttons).Length; j++) { if (!((Object)(object)((Il2CppArrayBase<SimpleStunButton>)(object)buttons)[j] == (Object)null) && !(((Object)((Component)((Il2CppArrayBase<SimpleStunButton>)(object)buttons)[j]).gameObject).name == "BloodTabButton")) { ((Il2CppArrayBase<SimpleStunButton>)(object)val)[num2++] = ((Il2CppArrayBase<SimpleStunButton>)(object)buttons)[j]; } } return val; } private static Il2CppReferenceArray<RectTransform> WithoutOurTabs(Il2CppReferenceArray<RectTransform> tabs) { if (tabs == null) { return null; } int num = 0; for (int i = 0; i < ((Il2CppArrayBase<RectTransform>)(object)tabs).Length; i++) { if ((Object)(object)((Il2CppArrayBase<RectTransform>)(object)tabs)[i] != (Object)null && ((Object)((Component)((Il2CppArrayBase<RectTransform>)(object)tabs)[i]).gameObject).name != "BloodTab") { num++; } } Il2CppReferenceArray<RectTransform> val = new Il2CppReferenceArray<RectTransform>((long)num); int num2 = 0; for (int j = 0; j < ((Il2CppArrayBase<RectTransform>)(object)tabs).Length; j++) { if (!((Object)(object)((Il2CppArrayBase<RectTransform>)(object)tabs)[j] == (Object)null) && !(((Object)((Component)((Il2CppArrayBase<RectTransform>)(object)tabs)[j]).gameObject).name == "BloodTab")) { ((Il2CppArrayBase<RectTransform>)(object)val)[num2++] = ((Il2CppArrayBase<RectTransform>)(object)tabs)[j]; } } return val; } internal static void OnRemotePayload(string payload) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown try { List<Section> list = ParseSections(payload); if (list.Count != 0) { _remoteSections = list; _lastSections = list; _lastDataTime = Time.time; if (_active) { Rebuild(list); } ManualLogSource l = Plugin.L; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(46, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BuffsTab] data received over chat ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" sections)"); } l.LogInfo(val); } } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] remote data: " + ex.Message)); } } private static List<Section> ReadServerSections() { List<Section> list = new List<Section>(); try { string path = DataFileFor(_localId); if (File.Exists(path)) { list = ParseSections(File.ReadAllText(path, Encoding.UTF8)); } } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] read: " + ex.Message)); } if (list.Count > 0) { return list; } return _remoteSections; } private static List<Section> ParseSections(string text) { List<Section> list = new List<Section>(); try { Section section = null; string[] array = (text ?? string.Empty).Split('\n'); for (int i = 0; i < array.Length; i++) { string text2 = array[i].TrimEnd(); if (text2.Length == 0) { continue; } string[] array2 = text2.Split('|'); if (array2[0] == "V") { continue; } if (array2[0] == "S") { section = new Section(); string text3 = ((array2.Length >= 2) ? array2[1] : string.Empty); string arg = ((array2.Length >= 3) ? array2[2] : string.Empty); if (text3 == "meta") { section = null; continue; } if (IsKnownKind(text3)) { section.Kind = text3; section.Title = Localization.SectionTitle(text3, arg); } else if (array2.Length == 2) { section.Title = array2[1]; } list.Add(section); } else if (!(array2[0] != "R")) { if (array2.Length >= 2 && array2[1] == "rates") { ApplyRates(array2); } else if (section != null) { AddRow(section, array2); } } } } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] parse: " + ex.Message)); } for (int j = 0; j < list.Count; j++) { if (list[j].Rows.Count <= 0) { list[j].Rows.Add(new KeyValuePair<string, string>(Localization.EmptyHint(list[j].Kind), "—")); } } return list; } private static bool IsKnownKind(string kind) { switch (kind) { default: return kind == "weapon"; case "general": case "class": case "blood": return true; } } private static void ApplyRates(string[] parts) { if (parts.Length >= 5) { if (float.TryParse(parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { Plugin.ServerSpell = result; } if (float.TryParse(parts[3], NumberStyles.Float, CultureInfo.InvariantCulture, out result)) { Plugin.ServerWeapon = result; } if (float.TryParse(parts[4], NumberStyles.Float, CultureInfo.InvariantCulture, out result)) { Plugin.ServerUltimate = result; } } } private static void AddRow(Section section, string[] parts) { if (parts.Length < 2) { return; } string text = parts[1]; if (text == "shroud" && parts.Length == 2) { section.Rows.Add(new KeyValuePair<string, string>(Localization.Shroud, Localization.ShroudOn)); } else if (text == "prestige" && parts.Length >= 4) { if (int.TryParse(parts[3], out var result)) { section.Rows.Add(new KeyValuePair<string, string>(Localization.PrestigeName(parts[2]), Localization.PrestigeLevel(result))); } } else if (text == "synergy" && parts.Length >= 4) { if (float.TryParse(parts[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { section.Rows.Add(new KeyValuePair<string, string>(Localization.Stat(parts[2]), Localization.FormatMultiplier(result2))); } } else if (text == "stat" && parts.Length >= 4) { if (float.TryParse(parts[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { section.Rows.Add(new KeyValuePair<string, string>(Localization.Stat(parts[2]), Localization.FormatStat(parts[2], result3))); } } else if (parts.Length >= 3) { section.Rows.Add(new KeyValuePair<string, string>(parts[1], parts[2])); } } private static string Signature(List<Section> sections) { StringBuilder stringBuilder = new StringBuilder(); foreach (Section section in sections) { stringBuilder.Append(section.Title).Append('|'); foreach (KeyValuePair<string, string> row in section.Rows) { stringBuilder.Append(row.Key).Append('=').Append(row.Value) .Append(';'); } stringBuilder.Append('\n'); } return stringBuilder.ToString(); } private static void ClearContent() { if (!((Object)(object)_content == (Object)null)) { for (int num = _content.childCount - 1; num >= 0; num--) { GameObject gameObject = ((Component)_content.GetChild(num)).gameObject; gameObject.SetActive(false); Object.Destroy((Object)(object)gameObject); } } } private static void Rebuild(List<Section> sections) { if ((Object)(object)_content == (Object)null) { return; } ClearContent(); Enforced.Clear(); _rowTemplate = (((Object)(object)_rowTemplate != (Object)null) ? _rowTemplate : FindRowTemplate()); _headerTemplate = (((Object)(object)_headerTemplate != (Object)null) ? _headerTemplate : FindTemplate("AttributesHeader")); _dividerTemplate = (((Object)(object)_dividerTemplate != (Object)null) ? _dividerTemplate : FindTemplate("HDiv")); if (sections.Count == 0 && _lastSections.Count > 0) { sections = _lastSections; } else if (sections.Count > 0) { _lastSections = sections; } if (sections.Count == 0) { sections = new List<Section> { new Section { Kind = "", Title = "", Rows = { new KeyValuePair<string, string>(Localization.Loading, "") } } }; } foreach (Section section in sections) { AddSection(section); } _signature = Signature(sections); RebuildLayout(); } private static void AddSection(Section section) { bool flag = section.Rows.Count == 1 && string.IsNullOrEmpty(section.Rows[0].Value); Transform container; GameObject val = BuildSection(section.Title, out container, flag); if ((Object)(object)val == (Object)null) { return; } if (flag) { AddPlainText(val.transform, section.Rows[0].Key); return; } foreach (KeyValuePair<string, string> row in section.Rows) { AddRowView(container, row.Key, row.Value); } } private static void AddPlainText(Transform parent, string text) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0037: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = new GameObject("BuffsPlainText"); val.transform.SetParent(parent, false); val.AddComponent<RectTransform>(); TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).text = text; ((TMP_Text)val2).fontSize = 18f; ((Graphic)val2).color = TextColor; ((TMP_Text)val2).alignment = (TextAlignmentOptions)513; ((TMP_Text)val2).enableWordWrapping = true; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; Enforced.Add(((TMP_Text)(object)val2, text)); } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] plain text: " + ex.Message)); } } private static GameObject BuildSection(string title, out Transform container, bool withoutGrid = false) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0030: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) container = null; GameObject val = new GameObject("BuffsSection"); val.transform.SetParent(_content, false); RectTransform obj = val.AddComponent<RectTransform>(); obj.anchorMin = new Vector2(0f, 1f); obj.anchorMax = new Vector2(1f, 1f); obj.pivot = new Vector2(0.5f, 1f); VerticalLayoutGroup obj2 = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f; ((LayoutGroup)obj2).padding = new RectOffset { left = 12, right = 12, top = 10, bottom = 10 }; ((LayoutGroup)obj2).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; if ((Object)(object)_headerTemplate != (Object)null && !string.IsNullOrEmpty(title)) { GameObject val2 = Object.Instantiate<GameObject>(_headerTemplate, val.transform); val2.SetActive(true); ((Object)val2).name = "BuffsHeader"; StripInteractive(val2); TMP_Text val3 = val2.GetComponent<TMP_Text>(); if ((Object)(object)val3 == (Object)null) { val3 = val2.GetComponentInChildren<TMP_Text>(true); } if ((Object)(object)val3 != (Object)null) { val3.text = title; val3.enableWordWrapping = false; Enforced.Add((val3, title)); } } if ((Object)(object)_dividerTemplate != (Object)null) { GameObject obj3 = Object.Instantiate<GameObject>(_dividerTemplate, val.transform); obj3.SetActive(true); ((Object)obj3).name = "BuffsDivider"; } if (withoutGrid) { return val; } GameObject val4 = new GameObject("BuffsGrid"); val4.transform.SetParent(val.transform, false); val4.AddComponent<RectTransform>(); GridLayoutGroup obj4 = val4.AddComponent<GridLayoutGroup>(); obj4.cellSize = new Vector2(280f, 40f); obj4.spacing = new Vector2(10f, 4f); obj4.constraint = (Constraint)1; obj4.constraintCount = 2; ((LayoutGroup)obj4).childAlignment = (TextAnchor)3; val4.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; container = val4.transform; return val; } private static void AddRowView(Transform container, string name, string value) { //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) GameObject val = (((Object)(object)_rowTemplate != (Object)null) ? _rowTemplate : FindRowTemplate()); if ((Object)(object)val == (Object)null || (Object)(object)container == (Object)null) { return; } GameObject val2 = Object.Instantiate<GameObject>(val, container); ((Object)val2).name = "BuffRow"; val2.SetActive(true); StripInteractive(val2); List<TMP_Text> list = new List<TMP_Text>(); foreach (TMP_Text componentsInChild in val2.GetComponentsInChildren<TMP_Text>(true)) { if ((Object)(object)componentsInChild != (Object)null) { list.Add(componentsInChild); } } TMP_Text val3 = null; TMP_Text val4 = null; for (int i = 0; i < list.Count; i++) { string name2 = ((Object)((Component)list[i]).gameObject).name; if ((Object)(object)val3 == (Object)null && name2.StartsWith("AttributeName")) { val3 = list[i]; } else if ((Object)(object)val4 == (Object)null && name2.StartsWith("AttributeValue")) { val4 = list[i]; } } if ((Object)(object)val3 == (Object)null && list.Count > 0) { val3 = list[0]; } if ((Object)(object)val4 == (Object)null && list.Count > 1) { val4 = list[1]; } for (int j = 0; j < list.Count; j++) { if (!((Object)(object)list[j] == (Object)(object)val3) && !((Object)(object)list[j] == (Object)(object)val4)) { Object.Destroy((Object)(object)((Component)list[j]).gameObject); } } LayoutRow(val3, val4); if ((Object)(object)val3 != (Object)null) { val3.text = name; ((Graphic)val3).color = TextColor; val3.enableWordWrapping = false; val3.enableAutoSizing = true; val3.fontSizeMin = 9f; val3.fontSizeMax = 15f; val3.overflowMode = (TextOverflowModes)1; val3.alignment = (TextAlignmentOptions)513; Enforced.Add((val3, name)); } if ((Object)(object)val4 != (Object)null) { val4.text = value; ((Graphic)val4).color = (value.StartsWith("+") ? _green : TextColor); val4.enableWordWrapping = false; val4.enableAutoSizing = true; val4.fontSizeMin = 10f; val4.fontSizeMax = 16f; val4.alignment = (TextAlignmentOptions)516; Enforced.Add((val4, value)); } Transform val5 = FindDeep(val2.transform, "ProgressBar"); if ((Object)(object)val5 != (Object)null) { Object.Destroy((Object)(object)((Component)val5).gameObject); } Transform val6 = FindDeep(val2.transform, "BorderFocus"); if ((Object)(object)val6 != (Object)null) { Object.Destroy((Object)(object)((Component)val6).gameObject); } } private static void LayoutRow(TMP_Text nameText, TMP_Text valueText) { try { if ((Object)(object)nameText != (Object)null && (Object)(object)nameText.transform.parent != (Object)null) { HorizontalLayoutGroup component = ((Component)nameText.transform.parent).GetComponent<HorizontalLayoutGroup>(); if ((Object)(object)component != (Object)null) { ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false; ((LayoutGroup)component).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)component).spacing = 4f; } } ApplyLayout(nameText, 1f, -1f, 40f); ApplyLayout(valueText, 0f, 72f, -1f); } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] row layout: " + ex.Message)); } } private static void ApplyLayout(TMP_Text text, float flexible, float preferred, float min) { if (!((Object)(object)text == (Object)null)) { LayoutElement val = ((Component)text).GetComponent<LayoutElement>(); if ((Object)(object)val == (Object)null) { val = ((Component)text).gameObject.AddComponent<LayoutElement>(); } val.flexibleWidth = flexible; if (preferred > 0f) { val.preferredWidth = preferred; } if (min > 0f) { val.minWidth = min; } } } private static void StripInteractive(GameObject go) { try { foreach (Component componentsInChild in go.GetComponentsInChildren<Component>(true)) { if (!((Object)(object)componentsInChild == (Object)null)) { switch (((MemberInfo)((Object)componentsInChild).GetIl2CppType()).Name) { case "CharacterAttributeEntry": case "SimpleStunButton": case "Tooltip": case "LocalizedText": Object.Destroy((Object)(object)componentsInChild); break; } } } } catch (Exception ex) { Plugin.L.LogWarning((object)("[BuffsTab] strip: " + ex.Message)); } } private static void RebuildLayout() { try { Transform content = _content; RectTransform val = (RectTransform)(object)((content is RectTransform) ? content : null); if (!((Object)(object)val == (Object)null)) { LayoutRebuilder.ForceRebuildLayoutImmediate(val); if ((Object)(object)((Transform)val).parent != (Object)null) { Transform parent = ((Transform)val).parent; LayoutRebuilder.MarkLayoutForRebuild((RectTransform)(object)((parent is RectTransform) ? parent : null)); } } } catch { } } private static void LogLayout() { //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)_content == (Object)null) { return; } StringBuilder stringBuilder = new StringBuilder("[BuffsTab] layout:"); Rect rect; StringBuilder stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler; for (int i = 0; i < _content.childCount; i++) { Transform child = _content.GetChild(i); if (!((Object)(object)child == (Object)null) && ((Component)child).gameObject.activeSelf) { RectTransform component = ((Component)child).GetComponent<RectTransform>(); int value = 0; Transform val = FindDeep(child, "BuffsGrid"); if ((Object)(object)val != (Object)null) { value = val.childCount; } stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(10, 3, stringBuilder2); handler.AppendLiteral(" ["); float value2; if (!((Object)(object)component != (Object)null)) { value2 = -1f; } else { rect = component.rect; value2 = ((Rect)(ref rect)).width; } handler.AppendFormatted(value2, "0"); handler.AppendLiteral("x"); float value3; if (!((Object)(object)component != (Object)null)) { value3 = -1f; } else { rect = component.rect; value3 = ((Rect)(ref rect)).height; } handler.AppendFormatted(value3, "0"); handler.AppendLiteral(" rows="); handler.AppendFormatted(value); handler.AppendLiteral("]"); stringBuilder3.Append(ref handler); } } stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(7, 1, stringBuilder2); handler.AppendLiteral(" tab="); float value4; if (!((Object)(object)_buttonRect != (Object)null)) { value4 = -1f; } else { rect = _buttonRect.rect; value4 = ((Rect)(ref rect)).width; } handler.AppendFormatted(value4, "0"); handler.AppendLiteral("px"); stringBuilder4.Append(ref handler); Plugin.L.LogInfo((object)stringBuilder.ToString()); } catch { } } private static Color? FindGreenValue(RectTransform tab) { //IL_0054: 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_005b: 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_006b: 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_007b: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)tab == (Object)null) { return null; } foreach (TMP_Text componentsInChild in ((Component)tab).GetComponentsInChildren<TMP_Text>(false)) { if ((Object)(object)componentsInChild == (Object)null) { continue; } string text = componentsInChild.text; if (!string.IsNullOrEmpty(text) && text.Contains("+")) { Color color = ((Graphic)componentsInChild).color; if (color.g > color.r && color.g > color.b) { return color; } } } } catch { } return null; } private static Transform FindDeep(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } if (((Object)root).name == name) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindDeep(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } } internal static class ChatSync { private const string ProtocolPrefix = "UCUI|"; private const string RequestCommand = ".ucui d"; private static World _world; private static Entity _localUser; private static Entity _localCharacter; private static bool _resolved; private static float _nextRequest; private static readonly List<string> Parts = new List<string>(); private static int _expected; private static int _received; private static float _nextAuto; internal static void Install(Harmony harmony) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("ProjectM.UI.ClientChatSystem"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "OnUpdate", (Type[])null, (Type[])null)); if (methodInfo == null) { Plugin.L.LogWarning((object)"[ChatSync] ClientChatSystem.OnUpdate not found - chat sync disabled"); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ChatSync).GetMethod("OnChatUpdate", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.L.LogInfo((object)"[ChatSync] chat hooked"); } catch (Exception ex) { Plugin.L.LogWarning((object)("[ChatSync] install: " + ex.Message)); } } internal static void ResetSession() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //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_0015: Unknown result type (might be due to invalid IL or missing references) _resolved = false; _localUser = Entity.Null; _localCharacter = Entity.Null; _world = null; _nextAuto = 0f; _nextRequest = 0f; Parts.Clear(); _expected = 0; _received = 0; } internal static void SetWorld(World world) { if (_world == null && world != null) { _world = world; } } internal static void AutoPoll() { if (_world != null && !(Time.time < _nextAuto)) { int num = 20; try { num = Plugin.PollSeconds.Value; } catch { } if (num <= 0) { _nextAuto = float.MaxValue; return; } _nextAuto = Time.time + (float)Mathf.Clamp(num, 5, 300); Request(); } } internal static void Request() { if (_world != null && !(Time.time < _nextRequest)) { _nextRequest = Time.time + 8f; Send(".ucui d"); } } private static void ResolveLocalEntities(EntityManager em) { //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) //IL_0022: 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_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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0098: Unknown result type (might be due to invalid IL or missing references) if (_resolved) { return; } _resolved = true; try { EntityQuery val = ((EntityManager)(ref em)).CreateEntityQuery((ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly<LocalUser>() }); NativeArray<Entity> val2 = ((EntityQuery)(ref val)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); try { if (val2.Length > 0) { _localUser = val2[0]; } } finally { val2.Dispose(); ((EntityQuery)(ref val)).Dispose(); } EntityQuery val3 = ((EntityManager)(ref em)).CreateEntityQuery((ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly<LocalCharacter>() }); NativeArray<Entity> val4 = ((EntityQuery)(ref val3)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); try { if (val4.Length > 0) { _localCharacter = val4[0]; } } finally { val4.Dispose(); ((EntityQuery)(ref val3)).Dispose(); } } catch (Exception ex) { Plugin.L.LogWarning((object)("[ChatSync] local entities: " + ex.Message)); } } private static void Send(string text) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) //IL_0016: 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_0027: 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_0045: 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) //IL_0058: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) //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_009f: 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_00a4: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) try { EntityManager entityManager = _world.EntityManager; ResolveLocalEntities(entityManager); if (!(_localUser == Entity.Null) && !(_localCharacter == Entity.Null)) { ComponentType[] array = (ComponentType[])(object)new ComponentType[4] { ComponentType.ReadOnly<FromCharacter>(), ComponentType.ReadOnly<NetworkEventType>(), ComponentType.ReadOnly<SendNetworkEventTag>(), ComponentType.ReadOnly<ChatMessageEvent>() }; ChatMessageEvent val = new ChatMessageEvent { MessageText = FixedString512Bytes.op_Implicit(text), MessageType = (ChatMessageType)4, ReceiverEntity = ((EntityManager)(ref entityManager)).GetComponentData<NetworkId>(_localUser) }; NetworkEventType val2 = new NetworkEventType { IsAdminEvent = false, EventId = NetworkEvents.EventId_ChatMessageEvent, IsDebugEvent = false }; Entity val3 = ((EntityManager)(ref entityManager)).CreateEntity(array); ((EntityManager)(ref entityManager)).SetComponentData<FromCharacter>(val3, new FromCharacter { Character = _localCharacter, User = _localUser }); ((EntityManager)(ref entityManager)).SetComponentData<NetworkEventType>(val3, val2); ((EntityManager)(ref entityManager)).SetComponentData<ChatMessageEvent>(val3, val); Plugin.L.LogInfo((object)"[ChatSync] data requested"); } } catch (Exception ex) { Plugin.L.LogWarning((object)("[ChatSync] send: " + ex.Message)); } } private unsafe static void OnChatUpdate() { //IL_001d: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_003c: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0068: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) try { if (_world == null || !_world.IsCreated) { return; } EntityManager entityManager = _world.EntityManager; EntityQuery val = ((EntityManager)(ref entityManager)).CreateEntityQuery((ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly<ChatMessageServerEvent>() }); NativeArray<Entity> val2 = ((EntityQuery)(ref val)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); try { for (int i = 0; i < val2.Length; i++) { Entity val3 = val2[i]; if (!((EntityManager)(ref entityManager)).HasComponent<ChatMessageServerEvent>(val3)) { continue; } ChatMessageServerEvent componentData = ((EntityManager)(ref entityManager)).GetComponentData<ChatMessageServerEvent>(val3); string text = ((object)(*(FixedString512Bytes*)(&componentData.MessageText))/*cast due to .constrained prefix*/).ToString(); if (!string.IsNullOrEmpty(text)) { if (text.StartsWith("UCUI|", StringComparison.Ordinal)) { HandlePart(text); ((EntityManager)(ref entityManager)).DestroyEntity(val3); } else if (text.Trim().StartsWith(".ucui d", StringComparison.OrdinalIgnoreCase)) { ((EntityManager)(ref entityManager)).DestroyEntity(val3); } } } } finally { val2.Dispose(); ((EntityQuery)(ref val)).Dispose(); } } catch (Exception ex) { Plugin.L.LogWarning((object)("[ChatSync] read: " + ex.Message)); } } private static void HandlePart(string text) { try { string[] array = text.Split(new char[1] { '|' }, 4); if (array.Length >= 4 && int.TryParse(array[1], out var result) && int.TryParse(array[2], out var result2) && result2 > 0 && result > 0) { if (result2 != _expected || result == 1) { Parts.Clear(); _expected = result2; _received = 0; } Parts.Add(array[3]); _received++; if (_received >= _expected) { string payload = string.Concat(Parts).Replace('~', '\n'); Parts.Clear(); _expected = 0; _received = 0; BuffsTab.OnRemotePayload(payload); } } } catch (Exception ex) { Plugin.L.LogWarning((object)("[ChatSync] part: " + ex.Message)); } } } internal static class Localization { internal enum Lang { English, Russian } internal static Lang Current = Lang.English; private static readonly Dictionary<string, string> StatEn = new Dictionary<string, string> { ["MaxHealth"] = "Max health", ["MovementSpeed"] = "Movement speed", ["PrimaryAttackSpeed"] = "Attack speed", ["PhysicalLifeLeech"] = "Physical life leech", ["SpellLifeLeech"] = "Spell life leech", ["PrimaryLifeLeech"] = "Primary attack leech", ["PhysicalPower"] = "Physical power", ["SpellPower"] = "Spell power", ["PhysicalCritChance"] = "Physical crit chance", ["PhysicalCritDamage"] = "Physical crit damage", ["SpellCritChance"] = "Spell crit chance", ["SpellCritDamage"] = "Spell crit damage", ["HealingReceived"] = "Healing received", ["DamageReduction"] = "Damage reduction", ["PhysicalResistance"] = "Physical resistance", ["SpellResistance"] = "Spell resistance", ["ResourceYield"] = "Resource yield", ["ReducedBloodDrain"] = "Blood drain reduction", ["SpellCooldownRecoveryRate"] = "Spell cooldown rate", ["WeaponCooldownRecoveryRate"] = "Weapon cooldown rate", ["UltimateCooldownRecoveryRate"] = "Ultimate cooldown rate", ["MinionDamage"] = "Minion damage", ["AbilityAttackSpeed"] = "Ability attack speed", ["CorruptionDamageReduction"] = "Corruption resistance" }; private static readonly Dictionary<string, string> StatRu = new Dictionary<string, string> { ["MaxHealth"] = "Макс. здоровье", ["MovementSpeed"] = "Скорость движения", ["PrimaryAttackSpeed"] = "Скорость атаки", ["PhysicalLifeLeech"] = "Вампиризм (физ.)", ["SpellLifeLeech"] = "Вампиризм (маг.)", ["PrimaryLifeLeech"] = "Вампиризм осн. атаки", ["PhysicalPower"] = "Физическая сила", ["SpellPower"] = "Сила магии", ["PhysicalCritChance"] = "Шанс крит. удара (физ.)", ["PhysicalCritDamage"] = "Крит. урон (физ.)", ["SpellCritChance"] = "Шанс крит. удара (маг.)", ["SpellCritDamage"] = "Крит. урон (маг.)", ["HealingReceived"] = "Исцеление", ["DamageReduction"] = "Снижение урона", ["PhysicalResistance"] = "Сопротивление физ.", ["SpellResistance"] = "Сопротивление маг.", ["ResourceYield"] = "Добыча", ["ReducedBloodDrain"] = "Расход крови", ["SpellCooldownRecoveryRate"] = "КД заклинаний", ["WeaponCooldownRecoveryRate"] = "КД оружия", ["UltimateCooldownRecoveryRate"] = "КД ультимейта", ["MinionDamage"] = "Урон приспешников", ["AbilityAttackSpeed"] = "Скорость способностей", ["CorruptionDamageReduction"] = "Сопротивление порче" }; private static readonly Dictionary<string, string> ClassEn = new Dictionary<string, string> { ["BloodKnight"] = "Blood Knight", ["DemonHunter"] = "Demon Hunter", ["VampireLord"] = "Vampire Lord", ["ShadowBlade"] = "Shadow Blade", ["ArcaneSorcerer"] = "Arcane Sorcerer", ["DeathMage"] = "Death Mage" }; private static readonly Dictionary<string, string> ClassRu = new Dictionary<string, string> { ["BloodKnight"] = "Кровавый рыцарь", ["DemonHunter"] = "Охотник на демонов", ["VampireLord"] = "Владыка вампиров", ["ShadowBlade"] = "Теневая грань", ["ArcaneSorcerer"] = "Тайный чародей", ["DeathMage"] = "Маг смерти" }; private static readonly Dictionary<string, string> BloodEn = new Dictionary<string, string> { ["Worker"] = "Worker", ["Warrior"] = "Warrior", ["Scholar"] = "Scholar", ["Rogue"] = "Rogue", ["Mutant"] = "Mutant", ["VBlood"] = "V Blood", ["None"] = "None", ["GateBoss"] = "Gate boss", ["Draculin"] = "Draculin", ["Immortal"] = "Immortal", ["Creature"] = "Creature", ["Brute"] = "Brute", ["Corruption"] = "Corruption" }; private static readonly Dictionary<string, string> BloodRu = new Dictionary<string, string> { ["Worker"] = "Рабочая", ["Warrior"] = "Воительская", ["Scholar"] = "Учёная", ["Rogue"] = "Разбойничья", ["Mutant"] = "Мутантская", ["VBlood"] = "Кровь V", ["None"] = "Нет", ["GateBoss"] = "Кровь стража", ["Draculin"] = "Дракулинская", ["Immortal"] = "Бессмертная", ["Creature"] = "Звериная", ["Brute"] = "Грубая", ["Corruption"] = "Порченая" }; private static readonly Dictionary<string, string> WeaponEn = new Dictionary<string, string> { ["Sword"] = "Sword", ["Axe"] = "Axe", ["Mace"] = "Mace", ["Spear"] = "Spear", ["Crossbow"] = "Crossbow", ["GreatSword"] = "Greatsword", ["Slashers"] = "Slashers", ["Pistols"] = "Pistols", ["Reaper"] = "Reaper", ["Longbow"] = "Longbow", ["Whip"] = "Whip", ["Unarmed"] = "Unarmed", ["FishingPole"] = "Fishing pole", ["TwinBlades"] = "Twin blades", ["Daggers"] = "Daggers", ["Claws"] = "Claws" }; private static readonly Dictionary<string, string> WeaponRu = new Dictionary<string, string> { ["Sword"] = "Меч", ["Axe"] = "Топор", ["Mace"] = "Булава", ["Spear"] = "Копьё", ["Crossbow"] = "Арбалет", ["GreatSword"] = "Двуручный меч", ["Slashers"] = "Клинки", ["Pistols"] = "Пистолеты", ["Reaper"] = "Коса", ["Longbow"] = "Длинный лук", ["Whip"] = "Хлыст", ["Unarmed"] = "Без оружия", ["FishingPole"] = "Удочка", ["TwinBlades"] = "Парные клинки", ["Daggers"] = "Кинжалы", ["Claws"] = "Когти" }; private static bool Ru => Current == Lang.Russian; internal static string TabTitle => "Blood"; internal static string Loading { get { if (!Ru) { return "Loading server data…"; } return "Данные загружаются…"; } } internal static string LoadingHint { get { if (!Ru) { return "a few seconds"; } return "подождите пару секунд"; } } internal static string Shroud { get { if (!Ru) { return "Blood shroud"; } return "Плащ крови"; } } internal static string ShroudOn { get { if (!Ru) { return "enabled"; } return "включён"; } } private static CultureInfo NumberFormat { get { if (!Ru) { return CultureInfo.InvariantCulture; } return CultureInfo.GetCultureInfo("ru-RU"); } } internal static void Init(string configured) { switch ((configured ?? "auto").Trim().ToLowerInvariant()) { case "en": case "english": Current = Lang.English; return; case "ru": case "russian": Current = Lang.Russian; return; } try { Current = ((CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "ru") ? Lang.Russian : Lang.English); } catch { Current = Lang.English; } } internal static string SectionTitle(string kind, string arg) { switch (kind) { case "general": if (!Ru) { return "General"; } return "Общие"; case "class": return string.Format(Ru ? "Класс: {0} (синергии)" : "Class: {0} (synergies)", ClassName(arg)); case "blood": return string.Format(Ru ? "Кровь: {0}" : "Blood: {0}", BloodName(arg)); case "weapon": return string.Format(Ru ? "Оружие: {0}" : "Weapon: {0}", WeaponName(arg)); default: return kind; } } internal static string EmptyHint(string kind) { switch (kind) { case "general": if (!Ru) { return "No permanent buffs"; } return "Постоянных баффов нет"; case "class": if (!Ru) { return "No class selected"; } return "Класс не выбран"; case "blood": if (!Ru) { return "No blood bonuses selected"; } return "Бонусы крови не выбраны"; case "weapon": if (!Ru) { return "No weapon stats selected"; } return "Опыт оружия не выбран"; default: if (!Ru) { return "No data"; } return "Нет данных"; } } internal static string PrestigeName(string prefab) { return Humanize(prefab); } internal static string PrestigeLevel(int level) { if (Ru) { return $"ур. {level}"; } return $"lvl {level}"; } internal static bool IsPercent(string key) { switch (key) { case "MaxHealth": case "PhysicalPower": case "SpellPower": return false; default: return true; } } internal static string FormatStat(string key, float value) { if (IsPercent(key)) { return "+" + (value * 100f).ToString("0.#", NumberFormat) + "%"; } return "+" + value.ToString("0.#", NumberFormat); } internal static string FormatMultiplier(float value) { return "×" + value.ToString("0.##", NumberFormat); } internal static string Stat(string key) { if (Ru) { if (!StatRu.TryGetValue(key, out var value)) { return Humanize(key); } return value; } if (!StatEn.TryGetValue(key, out var value2)) { return Humanize(key); } return value2; } internal static string ClassName(string key) { if (string.IsNullOrEmpty(key) || key == "none") { if (!Ru) { return "none"; } return "не выбран"; } if (!(Ru ? ClassRu : ClassEn).TryGetValue(key, out var value)) { return Humanize(key); } return value; } internal static string BloodName(string key) { if (string.IsNullOrEmpty(key) || key == "none") { if (!Ru) { return "none"; } return "нет"; } if (!(Ru ? BloodRu : BloodEn).TryGetValue(key, out var value)) { return Humanize(key); } return value; } internal static string WeaponName(string key) { if (string.IsNullOrEmpty(key)) { if (!Ru) { return "none"; } return "нет"; } if (!(Ru ? WeaponRu : WeaponEn).TryGetValue(key, out var value)) { return Humanize(key); } return value; } internal static string Humanize(string name) { if (string.IsNullOrEmpty(name)) { return name; } StringBuilder stringBuilder = new StringBuilder(name.Length + 6); for (int i = 0; i < name.Length; i++) { char c = name[i]; if (i > 0 && char.IsUpper(c) && !char.IsUpper(name[i - 1])) { stringBuilder.Append(' '); } stringBuilder.Append(c); } return stringBuilder.ToString(); } } internal static class MenuProbe { internal static InventorySubMenu Menu; private static bool _dumpedMenu; private static bool _dumpedContent; private static int _tick; private static readonly StringBuilder Sb = new StringBuilder(); internal static void Install(Harmony harmony) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("ProjectM.UI.InventorySubMenuMapper"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "InitializeUI", (Type[])null, (Type[])null)); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(MenuProbe).GetMethod("OnInitializeUI", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.L.LogInfo((object)"[Probe] InitializeUI hooked"); } else { Plugin.L.LogWarning((object)"[Probe] InventorySubMenuMapper.InitializeUI not found"); } Type type2 = AccessTools.TypeByName("ProjectM.UI.UICanvasSystem"); MethodInfo methodInfo2 = ((type2 == null) ? null : AccessTools.Method(type2, "UpdateHideIfDisabled", (Type[])null, (Type[])null)); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(MenuProbe).GetMethod("OnCanvasUpdate", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.L.LogInfo((object)"[Probe] canvas update hooked"); } else { Plugin.L.LogWarning((object)"[Probe] UICanvasSystem.UpdateHideIfDisabled not found"); } } catch (Exception ex) { Plugin.L.LogWarning((object)("[Probe] install: " + ex)); } } private static void OnInitializeUI(InventorySubMenu menu) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown bool flag = (Object)(object)Menu == (Object)null || (Object)(object)menu == (Object)null || ((Il2CppObjectBase)Menu).Pointer != ((Il2CppObjectBase)menu).Pointer; if ((Object)(object)Menu == (Object)null) { ManualLogSource l = Plugin.L; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(34, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Probe] character window found: '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)((Component)menu).gameObject).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'"); } l.LogInfo(val); } else if (flag) { Plugin.L.LogInfo((object)"[Probe] character window re-created - rebinding"); } Menu = menu; if (flag) { ChatSync.ResetSession(); BuffsTab.Rebind(menu); } else { BuffsTab.Bind(menu); } } private static void OnCanvasUpdate(UICanvasSystem __instance) { try { BuffsTab.Tick((__instance == null) ? null : ((ComponentSystemBase)__instance).World); if (!((Object)(object)Menu == (Object)null) && ++_tick % 15 == 0 && Plugin.Probe.Value) { if (!_dumpedMenu) { _dumpedMenu = true; DumpMenu(); } if (((Component)Menu).gameObject.activeInHierarchy && !_dumpedContent) { _dumpedContent = true; DumpContents(); } } } catch (Exception ex) { Plugin.L.LogWarning((object)("[Probe] poll: " + ex.Message)); } } private static void DumpMenu() { Sb.Clear(); Sb.AppendLine("[Probe] ===== MENU ====="); StringBuilder sb = Sb; StringBuilder stringBuilder = sb; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(25, 2, sb); handler.AppendLiteral("[Probe] tabButtons="); handler.AppendFormatted(((Il2CppArrayBase<SimpleStunButton>)(object)Menu.TabButtons)?.Length); handler.AppendLiteral(" tabs="); handler.AppendFormatted(((Il2CppArrayBase<RectTransform>)(object)Menu.Tabs)?.Length); stringBuilder.AppendLine(ref handler); Il2CppReferenceArray<SimpleStunButton> tabButtons = Menu.TabButtons; if (tabButtons != null) { for (int i = 0; i < ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length; i++) { if (!((Object)(object)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[i] == (Object)null)) { TMP_Text componentInChildren = ((Component)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[i]).GetComponentInChildren<TMP_Text>(true); sb = Sb; StringBuilder stringBuilder2 = sb; handler = new StringBuilder.AppendInterpolatedStringHandler(27, 3, sb); handler.AppendLiteral("[Probe] tab["); handler.AppendFormatted(i); handler.AppendLiteral("] '"); handler.AppendFormatted(((Object)((Component)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[i]).gameObject).name); handler.AppendLiteral("' label='"); handler.AppendFormatted(Trunc((componentInChildren != null) ? componentInChildren.text : null)); handler.AppendLiteral("'"); stringBuilder2.AppendLine(ref handler); } } } Il2CppReferenceArray<RectTransform> tabs = Menu.Tabs; if (tabs != null) { for (int j = 0; j < ((Il2CppArrayBase<RectTransform>)(object)tabs).Length; j++) { if (!((Object)(object)((Il2CppArrayBase<RectTransform>)(object)tabs)[j] == (Object)null)) { sb = Sb; StringBuilder stringBuilder3 = sb; handler = new StringBuilder.AppendInterpolatedStringHandler(30, 3, sb); handler.AppendLiteral("[Probe] content["); handler.AppendFormatted(j); handler.AppendLiteral("] '"); handler.AppendFormatted(((Object)((Component)((Il2CppArrayBase<RectTransform>)(object)tabs)[j]).gameObject).name); handler.AppendLiteral("' active="); handler.AppendFormatted(((Component)((Il2CppArrayBase<RectTransform>)(object)tabs)[j]).gameObject.activeSelf); stringBuilder3.AppendLine(ref handler); } } } if (tabButtons != null && ((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons).Length > 0 && (Object)(object)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[0] != (Object)null) { Sb.AppendLine("[Probe] --- tab strip ---"); DumpTree(((Component)((Il2CppArrayBase<SimpleStunButton>)(object)tabButtons)[0]).transform.parent, 0, 80); } Sb.AppendLine("[Probe] ===== END ====="); Plugin.L.LogInfo((object)Sb.ToString()); } private static void DumpContents() { Il2CppReferenceArray<RectTransform> tabs = Menu.Tabs; if (tabs == null) { return; } for (int i = 0; i < ((Il2CppArrayBase<RectTransform>)(object)tabs).Length; i++) { if (!((Object)(object)((Il2CppArrayBase<RectTransform>)(object)tabs)[i] == (Object)null)) { Sb.Clear(); StringBuilder sb = Sb; StringBuilder stringBuilder = sb; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(31, 2, sb); handler.AppendLiteral("[Probe] ===== CONTENT "); handler.AppendFormatted(i); handler.AppendLiteral(" '"); handler.AppendFormatted(((Object)((Component)((Il2CppArrayBase<RectTransform>)(object)tabs)[i]).gameObject).name); handler.AppendLiteral("' ====="); stringBuilder.AppendLine(ref handler); DumpTree((Transform)(object)((Il2CppArrayBase<RectTransform>)(object)tabs)[i], 0, 400); sb = Sb; StringBuilder stringBuilder2 = sb; handler = new StringBuilder.AppendInterpolatedStringHandler(32, 1, sb); handler.AppendLiteral("[Probe] ===== CONTENT "); handler.AppendFormatted(i); handler.AppendLiteral(" END ====="); stringBuilder2.AppendLine(ref handler); Plugin.L.LogInfo((object)Sb.ToString()); } } } private static string Trunc(string s) { if (s == null) { return "<null>"; } s = s.Replace("\r", " ").Replace("\n", "\\n"); if (s.Length <= 90) { return s; } return s.Substring(0, 90) + "..."; } private static void DumpTree(Transform t, int depth, int budget) { //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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null || budget <= 0 || Sb.Length > 90000) { return; } string text = ""; RectTransform component = ((Component)t).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(7, 2); defaultInterpolatedStringHandler.AppendLiteral(" size="); Rect rect = component.rect; defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).width, "0"); defaultInterpolatedStringHandler.AppendLiteral("x"); rect = component.rect; defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).height, "0"); text = defaultInterpolatedStringHandler.ToStringAndClear(); if ((Object)(object)((Component)t).GetComponent<HorizontalLayoutGroup>() != (Object)null) { text += " [HLG]"; } if ((Object)(object)((Component)t).GetComponent<VerticalLayoutGroup>() != (Object)null) { text += " [VLG]"; } if ((Object)(object)((Component)t).GetComponent<GridLayoutGroup>() != (Object)null) { text += " [GLG]"; } } Image component2 = ((Component)t).GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { text = text + " [Image " + (((Object)(object)component2.sprite == (Object)null) ? "-" : ((Object)component2.sprite).name) + "]"; } string value = ""; TMP_Text component3 = ((Component)t).GetComponent<TMP_Text>(); if ((Object)(object)component3 != (Object)null) { value = " text='" + Trunc(component3.text) + "'"; } StringBuilder sb = Sb; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(15, 5, sb); handler.AppendLiteral("[Probe] "); handler.AppendFormatted(new string(' ', Math.Min(depth * 2, 40))); handler.AppendLiteral("- "); handler.AppendFormatted(((Object)((Component)t).gameObject).name); handler.AppendLiteral(" act="); handler.AppendFormatted(((Component)t).gameObject.activeSelf); handler.AppendFormatted(text); handler.AppendFormatted(value); sb.AppendLine(ref handler); int childCount = t.childCount; for (int i = 0; i < childCount && i < 40; i++) { DumpTree(t.GetChild(i), depth + 1, budget - 1); } } } [BepInPlugin("universalcooldown.ui", "Universal Cooldown UI", "1.1.5")] public class Plugin : BasePlugin { public const string PluginGuid = "universalcooldown.ui"; public const string PluginName = "Universal Cooldown UI"; public const string PluginVersion = "1.1.5"; internal static ManualLogSource L; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<string> Language; internal static ConfigEntry<bool> BloodTab; internal static ConfigEntry<bool> Probe; internal static ConfigEntry<float> SpellRate; internal static ConfigEntry<float> WeaponRate; internal static ConfigEntry<float> UltimateRate; internal static ConfigEntry<string> RatesFile; internal static ConfigEntry<int> PollSeconds; internal static float ServerSpell = -1f; internal static float ServerWeapon = -1f; internal static float ServerUltimate = -1f; internal static float ServerPhysPower; internal static float ServerSpellPower; internal static Dictionary<string, float> ServerExtraStats = new Dictionary<string, float>(); private static DateTime _lastRead = DateTime.MinValue; public override void Load() { //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Expected O, but got Unknown //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Expected O, but got Unknown L = ((BasePlugin)this).Log; Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show Bloodcraft bonuses in tooltips and the character window."); Language = ((BasePlugin)this).Config.Bind<string>("General", "Language", "auto", "UI language: auto, en or ru."); BloodTab = ((BasePlugin)this).Config.Bind<bool>("Tab", "BloodTab", true, "Add the 'Blood' tab to the character window."); PollSeconds = ((BasePlugin)this).Config.Bind<int>("Sync", "PollSeconds", 20, "How often the client asks the server for fresh data over chat (seconds). 0 disables polling and relies on server pushes only."); SpellRate = ((BasePlugin)this).Config.Bind<float>("Rates", "Spell", 0.14f, "Spell cooldown rate fallback (used when the server file is missing)."); WeaponRate = ((BasePlugin)this).Config.Bind<float>("Rates", "Weapon", 0.21f, "Weapon cooldown rate fallback."); UltimateRate = ((BasePlugin)this).Config.Bind<float>("Rates", "Ultimate", 0.14f, "Ultimate cooldown rate fallback."); RatesFile = ((BasePlugin)this).Config.Bind<string>("Sync", "RatesFile", "", "Server file with cooldown rates (universalcooldown_rates.txt). Empty = BepInEx/config/<file>. The Blood tab data files are read from the same folder."); Probe = ((BasePlugin)this).Config.Bind<bool>("Debug", "ProbeMenu", false, "Dump the character window hierarchy into the log."); Localization.Init(Language.Value); Harmony val = new Harmony("local.universalcooldownui"); MethodInfo method = typeof(TooltipPatch).GetMethod("ApplyFromProperty", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method2 = typeof(TooltipPatch).GetMethod("ApplyFromText", BindingFlags.Static | BindingFlags.NonPublic); try { MethodInfo methodInfo = typeof(TMP_Text).GetProperty("text")?.GetSetMethod(nonPublic: true); if (methodInfo != null) { val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex) { L.LogWarning((object)("text setter patch failed: " + ex.Message)); } int num = 0; MethodInfo[] methods = typeof(TMP_Text).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != "SetText")) { try { val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch { } } } MenuProbe.Install(val); ChatSync.Install(val); ManualLogSource l = L; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(53, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("UniversalCooldownUI loaded (lang="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Localization.Lang>(Localization.Current); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("), SetText patched: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); } l.LogInfo(val2); } internal static string RatesPath() { string value = RatesFile.Value; if (!string.IsNullOrWhiteSpace(value)) { return value; } return Path.Combine(Paths.ConfigPath, "universalcooldown_rates.txt"); } internal static string SyncDirectory() { try { string directoryName = Path.GetDirectoryName(RatesPath()); if (!string.IsNullOrEmpty(directoryName)) { return directoryName; } } catch { } return Paths.ConfigPath; } internal static void TryReadServerRates() { if ((DateTime.UtcNow - _lastRead).TotalSeconds < 3.0) { return; } _lastRead = DateTime.UtcNow; try { string path = RatesPath(); try { ulong localSteamId = BuffsTab.LocalSteamId; if (localSteamId != 0L) { string directoryName = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(directoryName)) { string text = Path.Combine(directoryName, $"universalcooldown_rates_{localSteamId}.txt"); if (File.Exists(text)) { path = text; } } } } catch { } if (!File.Exists(path)) { return; } string[] array = File.ReadAllText(path).Trim().Split('|'); if (array.Length < 3) { return; } if (float.TryParse(array[0].Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array[1].Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array[2].Replace(',', '.'), Num