Decompiled source of SkulInsight QoL v0.10.2

plugins/DamageInsight.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Characters;
using Characters.AI;
using Characters.AI.Behaviours;
using Characters.AI.Pope;
using Characters.AI.TwinSister;
using Characters.AI.YggdrasillElderEnt;
using Characters.Abilities;
using Characters.Abilities.CharacterStat;
using Characters.Abilities.Statuses;
using Characters.Actions;
using Characters.Cooldowns;
using Characters.Gear;
using Characters.Gear.Items;
using Characters.Gear.Quintessences;
using Characters.Gear.Synergy;
using Characters.Gear.Synergy.Inscriptions;
using Characters.Gear.Synergy.Inscriptions.FairyTaleSummon;
using Characters.Gear.Upgrades;
using Characters.Gear.Weapons;
using Characters.Operations;
using Characters.Operations.Attack;
using Characters.Player;
using Characters.Projectiles;
using DamageInsight.Codex;
using DamageInsight.Describe;
using DamageInsight.Lang;
using DamageInsight.Patches;
using DamageInsight.Recording;
using DamageInsight.Tools;
using DamageInsight.UI;
using Data;
using GameResources;
using HarmonyLib;
using Level;
using Microsoft.CodeAnalysis;
using Scenes;
using Services;
using Singletons;
using Spine;
using Spine.Unity;
using TMPro;
using UI;
using UI.GearPopup;
using UI.Hud;
using UI.Inventory;
using UI.Pause;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("BehaviorDesigner.Runtime")]
[assembly: IgnoresAccessChecksTo("Plugins.Common")]
[assembly: IgnoresAccessChecksTo("Plugins.Singletons")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DocRun")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Real damage numbers, a combat log with per-hit calculations and build planning for Skul: The Hero Slayer.")]
[assembly: AssemblyFileVersion("0.10.2.0")]
[assembly: AssemblyInformationalVersion("0.10.2+92a1ab80a267f3036b679405ed237e470dcfbb12")]
[assembly: AssemblyProduct("SkulInsight QoL")]
[assembly: AssemblyTitle("DamageInsight")]
[assembly: InternalsVisibleTo("DamageInsight.Tests")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.10.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DamageInsight
{
	public enum DamageSource
	{
		Basic,
		Skill,
		Item,
		Quintessence,
		Poison,
		Burn,
		Bleed,
		Shock,
		Ember,
		Status,
		Dash,
		Swap,
		DarkAbility,
		Other
	}
	public static class DamageSources
	{
		internal static DamageSource? CurrentStatus;

		public static DamageSource Classify(in Damage damage)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected I4, but got Unknown
			MotionType motionType = damage.motionType;
			return (int)motionType switch
			{
				0 => DamageSource.Basic, 
				1 => DamageSource.Skill, 
				2 => DamageSource.Item, 
				3 => DamageSource.Quintessence, 
				5 => DamageSource.Dash, 
				6 => DamageSource.Swap, 
				7 => DamageSource.DarkAbility, 
				4 => CurrentStatus ?? DamageSource.Status, 
				_ => DamageSource.Other, 
			};
		}

		public static string Label(DamageSource source)
		{
			return source switch
			{
				DamageSource.Basic => Loc.T("ATK"), 
				DamageSource.Skill => Loc.T("SKILL"), 
				DamageSource.Item => Loc.T("ITEM"), 
				DamageSource.Quintessence => Loc.T("ESSENCE"), 
				DamageSource.Poison => Loc.T("POISON"), 
				DamageSource.Burn => Loc.T("BURN"), 
				DamageSource.Bleed => Loc.T("BLEED"), 
				DamageSource.Shock => Loc.T("SHOCK"), 
				DamageSource.Ember => Loc.T("EMBER"), 
				DamageSource.Status => Loc.T("STATUS"), 
				DamageSource.Dash => Loc.T("DASH"), 
				DamageSource.Swap => Loc.T("SWAP"), 
				DamageSource.DarkAbility => Loc.T("DARK"), 
				_ => "", 
			};
		}

		public static string Title(DamageSource source)
		{
			return source switch
			{
				DamageSource.Basic => Loc.T("Basic"), 
				DamageSource.Skill => Loc.T("Skill"), 
				DamageSource.Item => Loc.T("Item"), 
				DamageSource.Quintessence => Loc.T("Essence"), 
				DamageSource.Poison => Loc.T("Poison"), 
				DamageSource.Burn => Loc.T("Burn"), 
				DamageSource.Bleed => Loc.T("Bleed"), 
				DamageSource.Shock => Loc.T("Shock"), 
				DamageSource.Ember => Loc.T("Ember"), 
				DamageSource.Status => Loc.T("Status"), 
				DamageSource.Dash => Loc.T("Dash"), 
				DamageSource.Swap => Loc.T("Swap"), 
				DamageSource.DarkAbility => Loc.T("Dark"), 
				_ => Loc.T("Other"), 
			};
		}

		public static string AttributeColorHex(Attribute attribute)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			if ((int)attribute != 0)
			{
				if ((int)attribute == 1)
				{
					return "#3FD0FF";
				}
				return "#DDDDDD";
			}
			return "#FF9A3C";
		}

		public static string ColorHex(DamageSource source)
		{
			return source switch
			{
				DamageSource.Basic => "#FFFFFF", 
				DamageSource.Skill => "#FFC83D", 
				DamageSource.Item => "#4FE0C8", 
				DamageSource.Quintessence => "#C49BFF", 
				DamageSource.Poison => "#96E03A", 
				DamageSource.Burn => "#FF6A2B", 
				DamageSource.Bleed => "#E8334F", 
				DamageSource.Shock => "#FFF36B", 
				DamageSource.Ember => "#FFA05E", 
				DamageSource.Status => "#D0D0D0", 
				DamageSource.Dash => "#7FB8FF", 
				DamageSource.Swap => "#FF77DD", 
				DamageSource.DarkAbility => "#9A6BFF", 
				_ => "#A0A0A0", 
			};
		}

		public static Color Color(DamageSource source)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return ParseHex(ColorHex(source));
		}

		public static Color AttributeColor(Attribute attribute)
		{
			//IL_0000: 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)
			return ParseHex(AttributeColorHex(attribute));
		}

		private static Color ParseHex(string hex)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			ColorUtility.TryParseHtmlString(hex, ref result);
			return result;
		}
	}
	[BepInPlugin("docrun.skulinsight_qol", "SkulInsight QoL", "0.10.2")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<string> Language;

		internal static ConfigEntry<bool> DamageSourceTags;

		internal static ConfigEntry<bool> DamageSourceIcons;

		internal static ConfigEntry<float> DamageNumberHoldTime;

		internal static ConfigEntry<float> DamageNumberFadeTime;

		internal static ConfigEntry<bool> BossHealthNumbers;

		internal static ConfigEntry<bool> DescriptionNumbers;

		internal static ConfigEntry<KeyboardShortcut> CombatLogKey;

		internal static ConfigEntry<bool> CombatLogUseDialogueBackground;

		internal static ConfigEntry<float> CombatLogOpacity;

		internal static ConfigEntry<string> CombatLogWindowRect;

		internal static ConfigEntry<bool> MiniLogEnabled;

		internal static ConfigEntry<int> MiniLogLines;

		internal static ConfigEntry<float> MiniLogIdleSeconds;

		internal static ConfigEntry<bool> MiniLogPie;

		internal static ConfigEntry<float> MiniLogOffsetY;

		internal static ConfigEntry<bool> PickupPreview;

		internal static ConfigEntry<bool> CombatLogCalculations;

		internal static ConfigEntry<bool> CombatLogToFile;

		internal static ConfigEntry<bool> CooldownTicker;

		internal static ConfigEntry<float> CooldownTickerOpacity;

		internal static ConfigEntry<bool> CodexEnabled;

		internal static ConfigEntry<KeyboardShortcut> CodexKey;

		internal static ConfigEntry<bool> CodexRecordFights;

		internal static ConfigEntry<bool> CodexMoveHints;

		internal static ConfigEntry<bool> CodexMoveCounter;

		internal static ConfigEntry<bool> CodexRunLog;

		internal static ConfigEntry<bool> PreferNewMoves;

		private void Awake()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Language = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Language", "auto", new ConfigDescription("Language of the mod's texts. auto = the game's language (changes with it); or one of: " + string.Join(", ", Loc.Languages.Select(((string code, string name) l) => l.code)) + ".", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[1] { "auto" }.Concat(Loc.Languages.Select(((string code, string name) l) => l.code)).ToArray()), Array.Empty<object>()));
			Loc.OverrideFolder = Path.Combine(Paths.BepInExRootPath, "DamageInsight", "Lang");
			DamageSourceTags = ((BaseUnityPlugin)this).Config.Bind<bool>("Damage Numbers", "ShowSourceTag", true, "Mark damage numbers with where the damage came from (icon or ATK, SKILL, ITEM, ...).");
			DamageSourceIcons = ((BaseUnityPlugin)this).Config.Bind<bool>("Damage Numbers", "UseIcons", true, "Use icons instead of text tags where an icon is configured (see [Damage Icons]).");
			IconLibrary.Bind(((BaseUnityPlugin)this).Config);
			DamageNumberHoldTime = ((BaseUnityPlugin)this).Config.Bind<float>("Damage Numbers", "HoldSeconds", 0.8f, "How long a damage number stays fully visible after popping up. (Game default: about 0.15)");
			DamageNumberFadeTime = ((BaseUnityPlugin)this).Config.Bind<float>("Damage Numbers", "FadeSeconds", 0.7f, "How long a damage number takes to fade out.");
			BossHealthNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("Boss Health Bar", "ShowNumbers", true, "Show current / maximum HP as text on boss, adventurer and dark enemy health bars.");
			DescriptionNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("Descriptions", "ShowDamageNumbers", true, "Add real damage numbers (with your current stats) to skull, skill, swap, item, essence and inscription descriptions.");
			PickupPreview = ((BaseUnityPlugin)this).Config.Bind<bool>("Descriptions", "PreviewPickup", true, "Items on the ground, in shops and in the swap menu show their numbers as if you had picked them up (their stats and inscription steps included).");
			CombatLogKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Combat Log", "ToggleKey", new KeyboardShortcut((KeyCode)108, Array.Empty<KeyCode>()), "Key that opens and closes the combat log.");
			CombatLogUseDialogueBackground = ((BaseUnityPlugin)this).Config.Bind<bool>("Combat Log", "UseDialogueBackground", true, "Use the NPC dialogue box artwork as the window background (false = plain dark panel).");
			CombatLogOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Combat Log", "BackgroundOpacity", 0.85f, "Opacity of the dialogue background, 0 = invisible, 1 = solid.");
			CombatLogWindowRect = ((BaseUnityPlugin)this).Config.Bind<string>("Combat Log", "WindowRect", "", "Position and size of the log window (left,top,width,height at 1920x1080). Saved automatically; empty = default.");
			CombatLogCalculations = ((BaseUnityPlugin)this).Config.Bind<bool>("Combat Log", "RecordCalculations", true, "Record how every hit's number came about (stats, items, inscriptions, dark abilities, crits, debuffs); hover a log line to see it.");
			CombatLogToFile = ((BaseUnityPlugin)this).Config.Bind<bool>("Combat Log", "SaveToFile", true, "Also write every hit (with its calculation) to BepInEx\\DamageInsight\\CombatLogs, one file per game session (the newest 30 are kept).");
			MiniLogEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Mini Log", "Enabled", false, "Show a few log lines above the minimap. Can also be toggled in the combat log window.");
			MiniLogLines = ((BaseUnityPlugin)this).Config.Bind<int>("Mini Log", "Lines", 4, "Number of lines (1-8).");
			MiniLogIdleSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Mini Log", "HideAfterSeconds", 5f, "Hide the mini log when no new damage came in for this many seconds.");
			MiniLogPie = ((BaseUnityPlugin)this).Config.Bind<bool>("Mini Log", "ShowPie", true, "Show a tiny pie chart at the right of the mini log.");
			MiniLogOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Mini Log", "GapAboveMinimap", 40f, "Distance between the minimap and the mini log (reference pixels at 1920x1080).");
			CooldownTicker = ((BaseUnityPlugin)this).Config.Bind<bool>("Cooldown Ticker", "Enabled", true, "Show the remaining seconds on the skill, swap, quintessence, item and ability icons (83s, 2m+, 10m). Cooldown speed bonuses are included.");
			CooldownTickerOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Cooldown Ticker", "Opacity", 0.55f, "Opacity of the numbers (0-1).");
			CodexEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Codex", "Enabled", true, "Record your progress for the Codex (enemies met and killed, gear found) and capture enemy portraits.");
			CodexKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Codex", "ToggleKey", new KeyboardShortcut((KeyCode)107, Array.Empty<KeyCode>()), "Key that opens and closes the Codex book.");
			CodexMoveHints = ((BaseUnityPlugin)this).Config.Bind<bool>("Codex", "ShowMoveHints", true, "Under a boss move in the Codex: when the boss uses it (HP range, distance, cooldown...), read from its AI. Shown once you have beaten the boss.");
			CodexRecordFights = ((BaseUnityPlugin)this).Config.Bind<bool>("Codex", "FilmBossAttacks", true, "Film each boss attack once (a small picture 10 times a second, effects included) to show it in the Codex.");
			CodexBalance.Bind(((BaseUnityPlugin)this).Config);
			SelfTest.ReportPatches(PatchRegistry.ApplyAll(new Harmony("docrun.skulinsight_qol")));
			DamageLog.Recorded += delegate(DamageRecord record)
			{
				SelfTest.Observe(in record);
			};
			LogFile.Attach();
			((Component)this).gameObject.AddComponent<CombatLogWindow>();
			((Component)this).gameObject.AddComponent<MiniLog>();
			((Component)this).gameObject.AddComponent<CodexWindow>();
			((Component)this).gameObject.AddComponent<FightRecorder>();
			Application.quitting += delegate
			{
				CodexTracker.SaveIfNeeded(force: true);
			};
			Log.LogInfo((object)"SkulInsight QoL 0.10.2 loaded");
		}

		private void Update()
		{
			LanguageWatcher.Tick();
			Service instance = Singleton<Service>.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				LevelManager levelManager = instance.levelManager;
				obj = ((levelManager != null) ? levelManager.player : null);
			}
			bool flag = (Object)obj != (Object)null;
			CodexTracker.Tick((Character)obj);
			if (flag)
			{
				SelfTest.CheckRun();
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "docrun.skulinsight_qol";

		public const string PLUGIN_NAME = "SkulInsight QoL";

		public const string PLUGIN_VERSION = "0.10.2";
	}
}
namespace DamageInsight.UI
{
	public sealed class CombatLogWindow : MonoBehaviour
	{
		private enum ChartMode
		{
			Source,
			Type
		}

		private sealed class ChipGroup
		{
			public TextMeshProUGUI Label;

			public readonly List<(UiKit.Chip chip, float width)> Chips = new List<(UiKit.Chip, float)>();
		}

		public static readonly LogFilter Filter = new LogFilter();

		public static readonly LogFeed Feed = new LogFeed(Filter);

		private static int _feedFrame = -1;

		private ChartMode _chartMode;

		private int _minDamageIndex;

		private const int MaxLines = 250;

		private const float TextInterval = 0.1f;

		private const float ChartInterval = 0.3f;

		private const float DefaultWidth = 920f;

		private const float DefaultHeight = 720f;

		private Canvas _canvas;

		private WindowFrame _frame;

		private RectTransform _panel;

		private ScrollRect _scroll;

		private TextMeshProUGUI _logText;

		private TextMeshProUGUI _legendText;

		private TextMeshProUGUI _pieCenterText;

		private RectTransform _logFrame;

		private RectTransform _chartFrame;

		private RectTransform _pieRect;

		private RectTransform _legendRect;

		private PieChart _pie;

		private readonly List<Action> _chipRefreshers = new List<Action>();

		private readonly List<ChipGroup> _groups = new List<ChipGroup>();

		private int _textVersion = -1;

		private int _chartVersion = -1;

		private ChartMode _chartModeShown;

		private float _nextText;

		private float _nextChart;

		private TraceTooltip _tooltip;

		private readonly List<int> _lineMap = new List<int>();

		private int _hoverLine = -1;

		private DamageRecord? _pinned;

		private Image _panelImage;

		private TextMeshProUGUI _hint;

		private bool _rebuild;

		private static readonly Color PlainBackground = Color32.op_Implicit(new Color32((byte)27, (byte)18, (byte)36, (byte)235));

		private int _pinnedLine = -1;

		public static bool IsOpen { get; private set; }

		public static void UpdateFeed()
		{
			if (_feedFrame != Time.frameCount)
			{
				_feedFrame = Time.frameCount;
				Feed.Update(DamageLog.Records, DamageLog.TotalAdded, DamageLog.ClearCount, DamageLog.CurrentRoom);
			}
		}

		private void Awake()
		{
			Plugin.CombatLogUseDialogueBackground.SettingChanged += delegate
			{
				Guard.Run("Combat log background", Restyle);
			};
			Plugin.CombatLogOpacity.SettingChanged += delegate
			{
				Guard.Run("Combat log background", Restyle);
			};
			Plugin.CombatLogWindowRect.SettingChanged += delegate
			{
				Guard.Run("Combat log position", delegate
				{
					_frame?.MoveTo(SavedEdges());
				});
			};
			Plugin.CombatLogKey.SettingChanged += delegate
			{
				Guard.Run("Combat log hint", delegate
				{
					if ((Object)(object)_hint != (Object)null)
					{
						((TMP_Text)_hint).text = HintText();
					}
				});
			};
			Loc.Changed += delegate
			{
				_rebuild = true;
			};
		}

		private void Rebuild()
		{
			_rebuild = false;
			if (!((Object)(object)_canvas == (Object)null))
			{
				bool isOpen = IsOpen;
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
				_canvas = null;
				_frame = null;
				_tooltip = null;
				_pinned = null;
				_hoverLine = (_pinnedLine = -1);
				_chipRefreshers.Clear();
				_groups.Clear();
				_lineMap.Clear();
				IsOpen = false;
				if (isOpen)
				{
					SetOpen(open: true);
				}
			}
		}

		private void Update()
		{
			//IL_0031: 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)
			if (_rebuild)
			{
				Guard.Run("Combat log (language)", Rebuild);
			}
			if (!CodexWindow.IsTyping && !SettingsPage.IsOpen)
			{
				KeyboardShortcut value = Plugin.CombatLogKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() || (IsOpen && Input.GetKeyDown((KeyCode)27)))
				{
					SetOpen(!IsOpen);
				}
			}
			if (IsOpen)
			{
				UpdateFeed();
				UpdateTooltip();
				float unscaledTime = Time.unscaledTime;
				if (Feed.Version != _textVersion && unscaledTime >= _nextText)
				{
					_nextText = unscaledTime + 0.1f;
					_textVersion = Feed.Version;
					DrawLog();
				}
				if ((Feed.Version != _chartVersion || _chartMode != _chartModeShown) && unscaledTime >= _nextChart)
				{
					_nextChart = unscaledTime + 0.3f;
					_chartVersion = Feed.Version;
					_chartModeShown = _chartMode;
					DrawChart();
				}
			}
		}

		private void SetOpen(bool open)
		{
			if (open && (Object)(object)_canvas == (Object)null)
			{
				try
				{
					Build();
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"Could not build the combat log window: {arg}");
					return;
				}
			}
			IsOpen = open;
			((Component)_canvas).gameObject.SetActive(open);
			if (open)
			{
				EnsureEventSystem();
				RefreshChips();
				_textVersion = (_chartVersion = -1);
				_nextText = (_nextChart = 0f);
			}
		}

		private void Build()
		{
			//IL_0043: 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_05bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0600: Unknown result type (might be due to invalid IL or missing references)
			//IL_0605: Unknown result type (might be due to invalid IL or missing references)
			//IL_0713: Unknown result type (might be due to invalid IL or missing references)
			_canvas = UiKit.OverlayCanvas("DamageInsight_CombatLog", 5000);
			((Component)_canvas).gameObject.AddComponent<GraphicRaycaster>();
			Image val = UiKit.Image("Panel", ((Component)_canvas).transform, PlainBackground);
			_panel = ((Graphic)val).rectTransform;
			_panelImage = val;
			ApplyBackground(val);
			_frame = WindowFrame.Attach(_panel, SavedEdges(), 560f, 440f);
			Transform panel = (Transform)(object)_panel;
			((TMP_Text)UiKit.Text("Title", panel, Loc.T("Combat Log"), 30f, (TextAlignmentOptions)257)).rectTransform.Place(28f, 12f, 360f, 40f);
			_hint = UiKit.Text("Hint", panel, HintText(), 13f, (TextAlignmentOptions)257, UiKit.DimTextColor);
			((TMP_Text)_hint).rectTransform.Place(28f, 48f, 520f, 20f);
			string label = Loc.T("Clear");
			string label2 = Loc.T("Mini log");
			float num = Mathf.Max(80f, UiKit.ChipWidth(label));
			float width = Mathf.Max(100f, UiKit.ChipWidth(label2));
			((Graphic)new UiKit.Chip(panel, label, 0f, 0f, num, delegate
			{
				DamageLog.Clear();
				Filter.Changed();
			}).Background).rectTransform.PlaceTopRight(28f, 16f, num, 28f);
			UiKit.Chip mini = new UiKit.Chip(panel, label2, 0f, 0f, width, delegate
			{
				Plugin.MiniLogEnabled.Value = !Plugin.MiniLogEnabled.Value;
				RefreshChips();
			});
			((Graphic)mini.Background).rectTransform.PlaceTopRight(28f + num + 8f, 16f, width, 28f);
			_chipRefreshers.Add(delegate
			{
				mini.SetOn(Plugin.MiniLogEnabled.Value);
			});
			ChipGroup chipGroup = Group(panel, Loc.T("Show"));
			Radio(chipGroup, panel, new(string, LogDirection)[3]
			{
				(Loc.T("Dealt"), LogDirection.Dealt),
				(Loc.T("Taken"), LogDirection.Taken),
				(Loc.T("All"), LogDirection.All)
			}, () => Filter.Direction, delegate(LogDirection v)
			{
				Filter.Direction = v;
			});
			ChipGroup chipGroup2 = Group(panel, Loc.T("Scope"));
			Radio(chipGroup2, panel, new(string, LogScope)[2]
			{
				(Loc.T("This room"), LogScope.Room),
				(Loc.T("All rooms"), LogScope.All)
			}, () => Filter.Scope, delegate(LogScope v)
			{
				Filter.Scope = v;
			});
			ChipGroup chipGroup3 = Group(panel, Loc.T("Filter"));
			Toggle(chipGroup3, panel, Loc.T("Crits only"), () => Filter.CritsOnly, delegate(bool v)
			{
				Filter.CritsOnly = v;
			});
			UiKit.Chip minChip = AddChip(chipGroup3, panel, Loc.T("Min: any"), Mathf.Max(100f, UiKit.ChipWidth(Loc.T("Min: any"))), delegate
			{
				_minDamageIndex = (_minDamageIndex + 1) % LogFilter.MinDamageSteps.Length;
				Filter.MinDamage = LogFilter.MinDamageSteps[_minDamageIndex];
				Filter.Changed();
				RefreshChips();
			});
			_chipRefreshers.Add(delegate
			{
				int num3 = LogFilter.MinDamageSteps[_minDamageIndex];
				((TMP_Text)minChip.Label).text = ((num3 == 0) ? Loc.T("Min: any") : Loc.F("Min: {0}", num3));
				minChip.SetOn(num3 > 0);
			});
			ChipGroup chipGroup4 = Group(panel, Loc.T("Enemy"));
			(string, EntityKind[])[] array = new(string, EntityKind[])[6]
			{
				(Loc.T("Regular"), new EntityKind[1] { EntityKind.TrashMob }),
				(Loc.T("Elites"), new EntityKind[1] { EntityKind.Elite }),
				(Loc.T("Adventurers"), new EntityKind[1] { EntityKind.Adventurer }),
				(Loc.T("Bosses"), new EntityKind[1] { EntityKind.Boss }),
				(Loc.T("Summons"), new EntityKind[1] { EntityKind.Summoned }),
				(Loc.T("Other"), new EntityKind[3]
				{
					EntityKind.Trap,
					EntityKind.Other,
					EntityKind.PlayerMinion
				})
			};
			for (int num2 = 0; num2 < array.Length; num2++)
			{
				var (label3, kinds) = array[num2];
				Toggle(chipGroup4, panel, label3, () => kinds.All(Filter.EnemyKinds.Contains), delegate(bool on)
				{
					EntityKind[] array2 = kinds;
					foreach (EntityKind value in array2)
					{
						Set(Filter.EnemyKinds, value, on);
					}
				});
			}
			ChipGroup chipGroup5 = Group(panel, Loc.T("Type"));
			foreach (Attribute attribute in Enum.GetValues(typeof(Attribute)))
			{
				Toggle(chipGroup5, panel, DescriptionFormatter.AttributeName(((object)attribute/*cast due to .constrained prefix*/).ToString()), () => Filter.Attributes.Contains(attribute), delegate(bool on)
				{
					//IL_000b: Unknown result type (might be due to invalid IL or missing references)
					Set(Filter.Attributes, attribute, on);
				}, DamageSources.AttributeColor(attribute));
			}
			ChipGroup chipGroup6 = Group(panel, Loc.T("Chart"));
			Radio(chipGroup6, panel, new(string, ChartMode)[2]
			{
				(Loc.T("By source"), ChartMode.Source),
				(Loc.T("By type"), ChartMode.Type)
			}, () => _chartMode, delegate(ChartMode v)
			{
				_chartMode = v;
			}, changesFilter: false);
			ChipGroup chipGroup7 = Group(panel, Loc.T("Source"));
			foreach (DamageSource s in Enum.GetValues(typeof(DamageSource)))
			{
				Toggle(chipGroup7, panel, DamageSources.Title(s), () => Filter.Sources.Contains(s), delegate(bool on)
				{
					Set(Filter.Sources, s, on);
				}, DamageSources.Color(s));
			}
			BuildLog(panel);
			_tooltip = new TraceTooltip(_canvas);
			BuildChart(panel);
			_frame.AddCornerGrips();
			_frame.Resized += delegate
			{
				Relayout();
			};
			_frame.DragEnded += delegate(Edges e)
			{
				Plugin.CombatLogWindowRect.Value = WindowFrame.Serialize(e);
			};
			Relayout();
			RefreshChips();
			((Component)_canvas).gameObject.SetActive(false);
		}

		private void Relayout()
		{
			//IL_0214: 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_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			float width = _frame.Current.Width;
			float num = Mathf.Max(70f, (_groups.Count == 0) ? 0f : (_groups.Max((ChipGroup g) => ((TMP_Text)g.Label).preferredWidth) + 10f));
			float num2 = width - 28f;
			float num3 = 28f;
			float num4 = 80f;
			bool flag = true;
			foreach (ChipGroup group in _groups)
			{
				float num5 = num + group.Chips.Sum(((UiKit.Chip chip, float width) c) => c.width + 6f);
				if (!flag && num3 + 22f + num5 > num2)
				{
					num3 = 28f;
					num4 += 34f;
					flag = true;
				}
				if (!flag)
				{
					num3 += 22f;
				}
				((TMP_Text)group.Label).rectTransform.Place(num3, num4, num, 28f);
				num3 += num;
				float num6 = num3;
				foreach (var (chip, num7) in group.Chips)
				{
					if (num3 + num7 > num2 && num3 > num6)
					{
						num3 = num6;
						num4 += 34f;
					}
					((Graphic)chip.Background).rectTransform.Place(num3, num4, num7, 28f);
					num3 += num7 + 6f;
				}
				flag = false;
			}
			float num8 = num4 + 34f + 10f;
			float num9 = Mathf.Clamp(width * 0.3f, 180f, 260f);
			_logFrame.Stretch(28f, num8, 28f + num9 + 16f, 24f);
			_chartFrame.anchorMin = new Vector2(1f, 0f);
			_chartFrame.anchorMax = new Vector2(1f, 1f);
			_chartFrame.pivot = new Vector2(1f, 0.5f);
			_chartFrame.offsetMin = new Vector2(0f - (28f + num9), 24f);
			_chartFrame.offsetMax = new Vector2(-28f, 0f - num8);
			float num10 = Mathf.Min(num9 - 32f, 220f);
			_pieRect.Place((num9 - num10) / 2f, 14f, num10, num10);
			_legendRect.Stretch(14f, num10 + 26f, 14f, 10f);
		}

		private void BuildLog(Transform parent)
		{
			//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_0074: 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_00d3: 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_00f3: 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)
			Image val = UiKit.Image("LogFrame", parent, Color32.op_Implicit(new Color32((byte)14, (byte)9, (byte)20, (byte)153)));
			_logFrame = ((Graphic)val).rectTransform;
			RectTransform val2 = UiKit.Rect("Viewport", ((Component)val).transform).Fill(8f);
			((Component)val2).gameObject.AddComponent<RectMask2D>();
			((Graphic)((Component)val2).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0f);
			_logText = UiKit.Text("Lines", (Transform)(object)val2, "", 16f, (TextAlignmentOptions)257);
			RectTransform rectTransform = ((TMP_Text)_logText).rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 1f);
			rectTransform.anchorMax = new Vector2(1f, 1f);
			rectTransform.pivot = new Vector2(0.5f, 1f);
			rectTransform.anchoredPosition = Vector2.zero;
			rectTransform.sizeDelta = new Vector2(-8f, 0f);
			((Component)rectTransform).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			_scroll = ((Component)val).gameObject.AddComponent<ScrollRect>();
			_scroll.viewport = val2;
			_scroll.content = rectTransform;
			_scroll.horizontal = false;
			_scroll.movementType = (MovementType)2;
			_scroll.scrollSensitivity = 40f;
		}

		private void BuildChart(Transform parent)
		{
			//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)
			Image val = UiKit.Image("ChartFrame", parent, Color32.op_Implicit(new Color32((byte)14, (byte)9, (byte)20, (byte)153)));
			_chartFrame = ((Graphic)val).rectTransform;
			_pie = new PieChart();
			_pieRect = UiKit.Rect("Pie", ((Component)val).transform);
			RawImage obj = ((Component)_pieRect).gameObject.AddComponent<RawImage>();
			obj.texture = (Texture)(object)_pie.Texture;
			((Graphic)obj).raycastTarget = false;
			_pieCenterText = UiKit.Text("Total", (Transform)(object)_pieRect, "", 18f, (TextAlignmentOptions)514);
			((TMP_Text)_pieCenterText).rectTransform.Fill();
			_legendText = UiKit.Text("Legend", ((Component)val).transform, "", 15f, (TextAlignmentOptions)257);
			_legendRect = ((TMP_Text)_legendText).rectTransform;
		}

		public static Image FindDialogueBackground()
		{
			//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_005d: 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_006d: 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_0082: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			Image val = null;
			NpcConversation[] array = Resources.FindObjectsOfTypeAll<NpcConversation>();
			foreach (NpcConversation val2 in array)
			{
				if ((Object)(object)val2._container == (Object)null)
				{
					continue;
				}
				Image[] componentsInChildren = val2._container.GetComponentsInChildren<Image>(true);
				foreach (Image val3 in componentsInChildren)
				{
					if ((Object)(object)val3.sprite == (Object)null)
					{
						continue;
					}
					Rect rect = ((Graphic)val3).rectTransform.rect;
					Vector2 size = ((Rect)(ref rect)).size;
					if (!((Object)(object)val == (Object)null))
					{
						float num = size.x * size.y;
						rect = ((Graphic)val).rectTransform.rect;
						float width = ((Rect)(ref rect)).width;
						rect = ((Graphic)val).rectTransform.rect;
						if (!(num > width * ((Rect)(ref rect)).height))
						{
							continue;
						}
					}
					val = val3;
				}
			}
			return val;
		}

		private static string HintText()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return Loc.F("Drag here to move · corners to resize · {0}/Esc to close", Plugin.CombatLogKey.Value);
		}

		private static Edges SavedEdges()
		{
			//IL_0015: 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_001b: 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)
			if (WindowFrame.TryParse(Plugin.CombatLogWindowRect.Value, out var edges))
			{
				return edges;
			}
			Vector2 canvasSize = UiKit.CanvasSize;
			return new Edges(canvasSize.x - 40f - 920f, (canvasSize.y - 720f) / 2f, 920f, 720f);
		}

		private void Restyle()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Image panelImage = _panelImage;
			if (!((Object)(object)panelImage == (Object)null))
			{
				panelImage.sprite = null;
				panelImage.type = (Type)0;
				((Graphic)panelImage).color = PlainBackground;
				ApplyBackground(panelImage);
			}
		}

		private static void ApplyBackground(Image panel)
		{
			//IL_0044: 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_005f: 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_0080: 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)
			if (!Plugin.CombatLogUseDialogueBackground.Value)
			{
				return;
			}
			try
			{
				Image val = FindDialogueBackground();
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogInfo((object)"Combat log: dialogue background not found, using a plain panel.");
					return;
				}
				panel.sprite = val.sprite;
				panel.type = (Type)((val.sprite.border != Vector4.zero) ? 1 : 0);
				Color color = ((Graphic)val).color;
				color.a *= Mathf.Clamp01(Plugin.CombatLogOpacity.Value);
				((Graphic)panel).color = color;
				Plugin.Log.LogInfo((object)$"Combat log: using dialogue background '{((Object)val.sprite).name}' (border {val.sprite.border})");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Combat log: could not use dialogue background: " + ex.Message));
			}
		}

		private static void EnsureEventSystem()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)EventSystem.current != (Object)null))
			{
				GameObject val = new GameObject("DamageInsight_EventSystem");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<EventSystem>();
				val.AddComponent<StandaloneInputModule>();
				Plugin.Log.LogInfo((object)"Combat log: created an EventSystem for mouse input.");
			}
		}

		private ChipGroup Group(Transform parent, string label)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			ChipGroup chipGroup = new ChipGroup
			{
				Label = UiKit.Text("Label " + label, parent, label, 16f, (TextAlignmentOptions)4097, UiKit.DimTextColor)
			};
			_groups.Add(chipGroup);
			return chipGroup;
		}

		private static UiKit.Chip AddChip(ChipGroup group, Transform parent, string label, float width, Action onClick, Color? onColor = null)
		{
			UiKit.Chip chip = new UiKit.Chip(parent, label, 0f, 0f, width, onClick, onColor);
			group.Chips.Add((chip, width));
			return chip;
		}

		private void Toggle(ChipGroup group, Transform parent, string label, Func<bool> get, Action<bool> set, Color? onColor = null)
		{
			UiKit.Chip chip = AddChip(group, parent, label, UiKit.ChipWidth(label), delegate
			{
				set(!get());
				Filter.Changed();
				RefreshChips();
			}, onColor);
			_chipRefreshers.Add(delegate
			{
				chip.SetOn(get());
			});
		}

		private void Radio<T>(ChipGroup group, Transform parent, (string label, T value)[] options, Func<T> get, Action<T> set, bool changesFilter = true)
		{
			for (int i = 0; i < options.Length; i++)
			{
				(string, T) tuple = options[i];
				string item = tuple.Item1;
				T value = tuple.Item2;
				UiKit.Chip chip = AddChip(group, parent, item, UiKit.ChipWidth(item), delegate
				{
					set(value);
					if (changesFilter)
					{
						Filter.Changed();
					}
					RefreshChips();
				});
				_chipRefreshers.Add(delegate
				{
					chip.SetOn(EqualityComparer<T>.Default.Equals(get(), value));
				});
			}
		}

		private void RefreshChips()
		{
			foreach (Action chipRefresher in _chipRefreshers)
			{
				chipRefresher();
			}
		}

		private static void Set<T>(HashSet<T> set, T value, bool on)
		{
			if (on)
			{
				set.Add(value);
			}
			else
			{
				set.Remove(value);
			}
		}

		private void DrawLog()
		{
			bool num = _scroll.verticalNormalizedPosition <= 0.01f || ((TMP_Text)_logText).text.Length == 0;
			((TMP_Text)_logText).text = LogText.Build(Feed.Shown, DamageLog.Rooms, 250, _lineMap);
			_hoverLine = -1;
			if (num)
			{
				Canvas.ForceUpdateCanvases();
				_scroll.verticalNormalizedPosition = 0f;
			}
		}

		private void UpdateTooltip()
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (_tooltip == null)
			{
				return;
			}
			int num = RecordUnderMouse();
			if (Input.GetMouseButtonDown(0))
			{
				_pinned = ((num >= 0 && (!_pinned.HasValue || _hoverLine != _pinnedLine)) ? new DamageRecord?(Feed.Shown[num]) : ((DamageRecord?)null));
				_pinnedLine = (_pinned.HasValue ? _hoverLine : (-1));
				if (_pinned.HasValue)
				{
					_tooltip.Show(_pinned.Value, Vector2.op_Implicit(Input.mousePosition));
				}
			}
			if (!_pinned.HasValue)
			{
				if (num >= 0)
				{
					_tooltip.Show(Feed.Shown[num], Vector2.op_Implicit(Input.mousePosition));
				}
				else if (_tooltip.Visible)
				{
					_tooltip.Hide();
				}
			}
		}

		private int RecordUnderMouse()
		{
			//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_003a: Unknown result type (might be due to invalid IL or missing references)
			_hoverLine = -1;
			if ((Object)(object)_logText == (Object)null || !RectTransformUtility.RectangleContainsScreenPoint(_scroll.viewport, Vector2.op_Implicit(Input.mousePosition), (Camera)null))
			{
				return -1;
			}
			int num = TMP_TextUtilities.FindIntersectingLine((TMP_Text)(object)_logText, Input.mousePosition, (Camera)null);
			TMP_TextInfo textInfo = ((TMP_Text)_logText).textInfo;
			if (num < 0 || num >= textInfo.lineCount)
			{
				return -1;
			}
			int firstCharacterIndex = textInfo.lineInfo[num].firstCharacterIndex;
			int num2 = 0;
			for (int i = 0; i < firstCharacterIndex && i < textInfo.characterCount; i++)
			{
				if (textInfo.characterInfo[i].character == '\n')
				{
					num2++;
				}
			}
			_hoverLine = num2;
			int num3 = ((num2 < _lineMap.Count) ? _lineMap[num2] : (-1));
			if (num3 < 0 || num3 >= Feed.Shown.Count)
			{
				return -1;
			}
			return num3;
		}

		private void DrawChart()
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			List<(string, double, double, Color)> list = ((_chartMode == ChartMode.Source) ? (from s in DamageStats.FromTotals(Feed.TotalBySource)
				select (label: DamageSources.Title(s.Key), Value: s.Value, Percent: s.Percent, color: DamageSources.Color(s.Key))).ToList() : (from s in DamageStats.FromTotals(Feed.TotalByAttribute)
				select (label: DescriptionFormatter.AttributeName(((object)s.Key/*cast due to .constrained prefix*/).ToString()), Value: s.Value, Percent: s.Percent, color: DamageSources.AttributeColor(s.Key))).ToList());
			_pie.Draw(list.Select<(string, double, double, Color), (double, Color)>(((string label, double Value, double Percent, Color color) s) => (Value: s.Value, color: s.color)).ToList());
			double num = list.Sum<(string, double, double, Color)>(((string label, double Value, double Percent, Color color) s) => s.Value);
			((TMP_Text)_pieCenterText).text = ((num > 0.0) ? string.Format("<size=70%><color=#A89F94>{0}</color></size>\n{1:N0}", Loc.T("Total"), num) : "");
			StringBuilder stringBuilder = new StringBuilder();
			foreach (var item in list)
			{
				string text = ColorUtility.ToHtmlStringRGB(item.Item4);
				stringBuilder.Append($"<color=#{text}>{item.Item1}</color><pos=48%>{item.Item3:0.0}%<pos=72%><color=#A89F94>{item.Item2:N0}</color>\n");
			}
			((TMP_Text)_legendText).text = stringBuilder.ToString();
		}
	}
	public static class CooldownFormat
	{
		public static double RealSeconds(double remain, double speed)
		{
			if (!(remain > 0.0) || !(speed > 0.01))
			{
				return 0.0;
			}
			return remain / speed;
		}

		public static string Format(double seconds)
		{
			if (double.IsNaN(seconds) || double.IsInfinity(seconds) || seconds <= 0.0)
			{
				return "";
			}
			long num = (long)Math.Ceiling(seconds - 0.0001);
			if (num < 100)
			{
				return Loc.F("{0}s", num);
			}
			long num2 = num / 60;
			if (num % 60 != 0L)
			{
				return Loc.F("{0}m+", num2);
			}
			return Loc.F("{0}m", num2);
		}
	}
	public static class CooldownLabel
	{
		private const string Name = "DamageInsight Cooldown";

		public static void Set(Transform icon, string text, TMP_FontAsset font)
		{
			//IL_005f: 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)
			Transform val = icon.Find("DamageInsight Cooldown");
			TextMeshProUGUI val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TextMeshProUGUI>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				if (text.Length == 0)
				{
					return;
				}
				val2 = Create(icon, font);
			}
			if (((TMP_Text)val2).text != text)
			{
				((TMP_Text)val2).text = text;
			}
			float num = Mathf.Clamp01(Plugin.CooldownTickerOpacity.Value);
			if (!Mathf.Approximately(((Graphic)val2).color.a, num))
			{
				((Graphic)val2).color = new Color(1f, 1f, 1f, num);
			}
		}

		private static TextMeshProUGUI Create(Transform icon, TMP_FontAsset font)
		{
			//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_002a: 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_0036: 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_0041: 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_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_0052: 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_00bf: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DamageInsight Cooldown", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(icon, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
			val2.offsetMin = offsetMin;
			TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val3).font = font;
			}
			((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val3).enableWordWrapping = false;
			((Graphic)val3).raycastTarget = false;
			((TMP_Text)val3).enableAutoSizing = true;
			((TMP_Text)val3).fontSizeMin = 4f;
			((TMP_Text)val3).fontSizeMax = 40f;
			((TMP_Text)val3).margin = new Vector4(1f, 1f, 1f, 1f);
			((Graphic)val3).color = new Color(1f, 1f, 1f, Mathf.Clamp01(Plugin.CooldownTickerOpacity.Value));
			((TMP_Text)val3).outlineWidth = 0.25f;
			((TMP_Text)val3).outlineColor = new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue);
			return val3;
		}
	}
	public static class CooldownReader
	{
		private static readonly Dictionary<Type, FieldInfo> Fields = new Dictionary<Type, FieldInfo>();

		public static double Remaining(IAbilityInstance instance)
		{
			if (instance == null)
			{
				return 0.0;
			}
			float iconFillAmount = instance.iconFillAmount;
			if (!(iconFillAmount > 0.001f) || !(iconFillAmount < 0.999f))
			{
				return 0.0;
			}
			FieldInfo fieldInfo = FieldFor(((object)instance).GetType());
			double num = ((fieldInfo != null) ? Convert.ToDouble(fieldInfo.GetValue(instance)) : ((double)instance.remainTime));
			if (!(num > 0.0) || !(num < 100000.0))
			{
				return 0.0;
			}
			return num;
		}

		private static FieldInfo FieldFor(Type type)
		{
			if (Fields.TryGetValue(type, out var value))
			{
				return value;
			}
			List<FieldInfo> list = new List<FieldInfo>();
			Type type2 = type;
			while (type2 != null && type2 != typeof(object))
			{
				list.AddRange(from f in type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
					where (f.FieldType == typeof(float) || f.FieldType == typeof(double)) && f.Name.IndexOf("remain", StringComparison.OrdinalIgnoreCase) >= 0
					select f);
				type2 = type2.BaseType;
			}
			FieldInfo fieldInfo = list.FirstOrDefault((FieldInfo f) => f.Name.IndexOf("cooldown", StringComparison.OrdinalIgnoreCase) >= 0) ?? list.FirstOrDefault();
			Fields[type] = fieldInfo;
			return fieldInfo;
		}
	}
	public class HealthNumberLabel : MonoBehaviour
	{
		private const float FallbackBarHeight = 24f;

		private const float MinFontSize = 14f;

		private const float MaxFontSize = 34f;

		private CharacterHealthBar _bar;

		private RectTransform _rect;

		private TextMeshProUGUI _text;

		private TextMeshProUGUI _shadow;

		private double _lastCurrent = -1.0;

		private double _lastMax = -1.0;

		private double _lastShield = -1.0;

		private bool _loggedGeometry;

		public static HealthNumberLabel Attach(CharacterHealthBar bar, TMP_FontAsset font)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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_014f: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: 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)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: 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_01c2: Expected O, but got Unknown
			if ((Object)(object)bar == (Object)null || (Object)(object)bar._container == (Object)null || (Object)(object)bar._healthBar == (Object)null || (Object)(object)((Component)bar).GetComponentInChildren<HealthNumberLabel>(true) != (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("DamageInsight_HealthNumbers", new Type[1] { typeof(RectTransform) });
			val.layer = ((Component)bar._container).gameObject.layer;
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)bar._container, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.pivot = val3;
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			((Transform)val2).SetAsLastSibling();
			GameObject val5 = new GameObject("Shadow", new Type[1] { typeof(RectTransform) })
			{
				layer = val.layer
			};
			RectTransform val6 = (RectTransform)val5.transform;
			((Transform)val6).SetParent((Transform)(object)val2, false);
			val6.anchorMin = Vector2.zero;
			val6.anchorMax = Vector2.one;
			val6.offsetMin = new Vector2(2f, -2f);
			val6.offsetMax = new Vector2(2f, -2f);
			TextMeshProUGUI shadow = MakeText(val5, font, new Color(0f, 0f, 0f, 0.85f));
			GameObject val7 = new GameObject("Text", new Type[1] { typeof(RectTransform) })
			{
				layer = val.layer
			};
			RectTransform val8 = (RectTransform)val7.transform;
			((Transform)val8).SetParent((Transform)(object)val2, false);
			val8.anchorMin = Vector2.zero;
			val8.anchorMax = Vector2.one;
			anchorMin = (val8.offsetMax = Vector2.zero);
			val8.offsetMin = anchorMin;
			TextMeshProUGUI text = MakeText(val7, font, Color.white);
			HealthNumberLabel healthNumberLabel = val.AddComponent<HealthNumberLabel>();
			healthNumberLabel._bar = bar;
			healthNumberLabel._rect = val2;
			healthNumberLabel._text = text;
			healthNumberLabel._shadow = shadow;
			return healthNumberLabel;
		}

		private static TextMeshProUGUI MakeText(GameObject go, TMP_FontAsset font, Color color)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = go.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val).font = font;
			}
			((TMP_Text)val).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val).enableAutoSizing = false;
			((TMP_Text)val).enableWordWrapping = false;
			((TMP_Text)val).overflowMode = (TextOverflowModes)0;
			((Graphic)val).raycastTarget = false;
			((Graphic)val).color = color;
			return val;
		}

		private void LateUpdate()
		{
			bool value = Plugin.BossHealthNumbers.Value;
			if (((Behaviour)_text).enabled != value)
			{
				((Behaviour)_text).enabled = value;
				((Behaviour)_shadow).enabled = value;
			}
			if (value)
			{
				PlaceOverBar();
				UpdateText();
			}
		}

		private void PlaceOverBar()
		{
			//IL_0012: 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_0018: 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_0034: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_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_0085: 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)
			//IL_009a: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: 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)
			RectTransform healthBar = _bar._healthBar;
			Vector3 defaultHealthScale = _bar._defaultHealthScale;
			if (defaultHealthScale.x != 0f)
			{
				Vector3 val = (((Object)(object)((Transform)healthBar).parent != (Object)null) ? ((Transform)healthBar).parent.lossyScale : Vector3.one);
				Rect rect = healthBar.rect;
				float num = ((Rect)(ref rect)).width * Mathf.Abs(defaultHealthScale.x) * val.x;
				rect = healthBar.rect;
				float num2 = ((Rect)(ref rect)).height * Mathf.Abs(defaultHealthScale.y) * val.y;
				Vector3 val2 = ((Transform)healthBar).position + new Vector3((0.5f - healthBar.pivot.x) * num, (0.5f - healthBar.pivot.y) * num2, 0f);
				((Transform)_rect).position = val2;
				Vector3 lossyScale = ((Transform)_rect).lossyScale;
				float num3 = ((num2 > 1f) ? (num2 / lossyScale.y) : 24f);
				_rect.sizeDelta = new Vector2(Mathf.Max(num / lossyScale.x, 200f), num3);
				((TMP_Text)_text).fontSize = Mathf.Clamp(num3 * 0.85f, 14f, 34f);
				((TMP_Text)_shadow).fontSize = ((TMP_Text)_text).fontSize;
				if (!_loggedGeometry)
				{
					_loggedGeometry = true;
					ManualLogSource log = Plugin.Log;
					object[] obj = new object[4]
					{
						((Object)_bar).name,
						null,
						null,
						null
					};
					rect = healthBar.rect;
					obj[1] = ((Rect)(ref rect)).size;
					obj[2] = healthBar.pivot;
					obj[3] = defaultHealthScale;
					log.LogInfo((object)(string.Format("HP label on '{0}': fill rect={1} pivot={2} fullScale={3} ", obj) + $"-> bar {num:0}x{num2:0} at {val2}, font {((TMP_Text)_text).fontSize:0}"));
				}
			}
		}

		private void UpdateText()
		{
			CharacterHealth health = _bar._health;
			if ((Object)(object)health == (Object)null)
			{
				TextMeshProUGUI text = _text;
				string text2 = (((TMP_Text)_shadow).text = "");
				((TMP_Text)text).text = text2;
				return;
			}
			double num = (((Health)health).dead ? 0.0 : ((Health)health).currentHealth);
			double maximumHealth = ((Health)health).maximumHealth;
			Shield shield = ((Health)health).shield;
			double num2 = ((shield != null) ? shield.amount : 0.0);
			if (num != _lastCurrent || maximumHealth != _lastMax || num2 != _lastShield)
			{
				_lastCurrent = num;
				_lastMax = maximumHealth;
				_lastShield = num2;
				string text4 = $"{Math.Ceiling(num):N0} / {Math.Ceiling(maximumHealth):N0}";
				if (num2 >= 1.0)
				{
					text4 += $"  <color=#BFE9FF>(+{Math.Ceiling(num2):N0})</color>";
				}
				((TMP_Text)_text).text = text4;
				((TMP_Text)_shadow).text = Regex.Replace(text4, "</?color[^>]*>", "");
			}
		}
	}
	public static class IconLibrary
	{
		private static readonly Dictionary<DamageSource, string> Defaults = new Dictionary<DamageSource, string>
		{
			[DamageSource.Basic] = "inscription:Arms",
			[DamageSource.Skill] = "inscription:Wisdom",
			[DamageSource.Item] = "inscription:Artifact",
			[DamageSource.Quintessence] = "inscription:Mystery",
			[DamageSource.Poison] = "inscription:Poisoning",
			[DamageSource.Burn] = "inscription:Arson",
			[DamageSource.Bleed] = "inscription:ExcessiveBleeding",
			[DamageSource.Shock] = "inscription:Manatech",
			[DamageSource.Ember] = "inscription:Arson",
			[DamageSource.Status] = "none",
			[DamageSource.Dash] = "inscription:Rapidity",
			[DamageSource.Swap] = "inscription:Mutation",
			[DamageSource.DarkAbility] = "inscription:Omen",
			[DamageSource.Other] = "none"
		};

		private static readonly Dictionary<DamageSource, ConfigEntry<string>> Entries = new Dictionary<DamageSource, ConfigEntry<string>>();

		private static readonly Dictionary<DamageSource, Sprite> Cache = new Dictionary<DamageSource, Sprite>();

		private static readonly HashSet<string> WarnedMissing = new HashSet<string>();

		public static void Bind(ConfigFile config)
		{
			foreach (DamageSource source in Enum.GetValues(typeof(DamageSource)))
			{
				ConfigEntry<string> val = config.Bind<string>("Damage Icons", source.ToString(), Defaults[source], "Icon shown next to this damage type. Examples: inscription:Mutation, skill:<name>, item:<name>, none");
				val.SettingChanged += delegate
				{
					Cache.Remove(source);
				};
				Entries[source] = val;
			}
		}

		public static string Spec(DamageSource source)
		{
			if (!Entries.TryGetValue(source, out var value))
			{
				return "none";
			}
			return value.Value;
		}

		public static Sprite Get(DamageSource source)
		{
			if (Cache.TryGetValue(source, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			string text = Spec(source);
			Sprite val = Resolve(text);
			if ((Object)(object)val != (Object)null)
			{
				Cache[source] = val;
			}
			else if (text != "none" && WarnedMissing.Add(text))
			{
				Plugin.Log.LogWarning((object)$"Icon '{text}' for {source} not found (yet); using the text tag.");
			}
			return val;
		}

		internal static Sprite Resolve(string spec)
		{
			if (string.IsNullOrWhiteSpace(spec) || spec.Trim().Equals("none", StringComparison.OrdinalIgnoreCase))
			{
				return null;
			}
			int num = spec.IndexOf(':');
			string text = ((num >= 0) ? spec.Substring(0, num).Trim().ToLowerInvariant() : "inscription");
			string name = ((num >= 0) ? spec.Substring(num + 1) : spec).Trim();
			if (text == null)
			{
				goto IL_01f5;
			}
			int length = text.Length;
			Sprite[] array;
			if (length <= 5)
			{
				if (length != 4)
				{
					if (length != 5)
					{
						goto IL_01f5;
					}
					char c = text[2];
					if (c != 'i')
					{
						if (c != 'u' || !(text == "skull"))
						{
							goto IL_01f5;
						}
						array = GearResource.instance?._weaponHudMainIcons;
					}
					else
					{
						if (!(text == "skill"))
						{
							goto IL_01f5;
						}
						array = GearResource.instance?._skillIcons;
					}
				}
				else
				{
					char c = text[0];
					if (c != 'g')
					{
						if (c != 'i' || !(text == "item"))
						{
							goto IL_01f5;
						}
						array = GearResource.instance?._itemBuffIcons;
					}
					else
					{
						if (!(text == "gear"))
						{
							goto IL_01f5;
						}
						array = GearResource.instance?._gearThumbnails;
					}
				}
			}
			else if (length != 11)
			{
				if (length != 12)
				{
					if (length != 16 || !(text == "inscription_full"))
					{
						goto IL_01f5;
					}
					array = CommonResource.instance?._keywordFullactiveIcons;
				}
				else
				{
					if (!(text == "quintessence"))
					{
						goto IL_01f5;
					}
					array = GearResource.instance?._quintessenceHudIcons;
				}
			}
			else
			{
				if (!(text == "inscription"))
				{
					goto IL_01f5;
				}
				array = CommonResource.instance?._keywordIcons;
			}
			goto IL_01f8;
			IL_01f8:
			IEnumerable<Sprite> enumerable = array;
			if (enumerable == null)
			{
				return null;
			}
			List<Sprite> source = enumerable.Where((Sprite s) => (Object)(object)s != (Object)null).ToList();
			return ((IEnumerable<Sprite>)source).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => ((Object)s).name.Equals(name, StringComparison.OrdinalIgnoreCase))) ?? ((IEnumerable<Sprite>)source).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => ((Object)s).name.IndexOf(name, StringComparison.OrdinalIgnoreCase) >= 0));
			IL_01f5:
			array = null;
			goto IL_01f8;
		}
	}
	public sealed class MiniLog : MonoBehaviour
	{
		private const float LineHeight = 19f;

		private const float PieSize = 40f;

		private const float FadeInSeconds = 0.2f;

		private const float FadeOutSeconds = 0.6f;

		private const float FallbackWidth = 314f;

		private Canvas _canvas;

		private RectTransform _root;

		private CanvasGroup _group;

		private TextMeshProUGUI _text;

		private RawImage _pieImage;

		private PieChart _pie;

		private readonly List<(DamageRecord record, float arrived)> _lines = new List<(DamageRecord, float)>();

		private int _cursor;

		private int _rebuildsSeen = -1;

		private float _lastNew = -999f;

		private bool _dirty;

		private float _nextPlacement;

		private float _nextPie;

		private int _pieVersion = -1;

		private bool _loggedPlacement;

		private void Update()
		{
			if (!ShouldShow())
			{
				if ((Object)(object)_canvas != (Object)null && ((Behaviour)_canvas).enabled)
				{
					((Behaviour)_canvas).enabled = false;
				}
				return;
			}
			if ((Object)(object)_canvas == (Object)null)
			{
				Build();
			}
			((Behaviour)_canvas).enabled = true;
			float now = Time.unscaledTime;
			CollectNewLines(now);
			float num = now - _lastNew;
			float num2 = Mathf.Max(0.5f, Plugin.MiniLogIdleSeconds.Value);
			_group.alpha = ((num < num2) ? 1f : Mathf.Clamp01(1f - (num - num2) / 0.6f));
			if (!(_group.alpha <= 0f))
			{
				if (now >= _nextPlacement)
				{
					_nextPlacement = now + 0.5f;
					Place();
				}
				if (_dirty || _lines.Any(((DamageRecord record, float arrived) l) => now - l.arrived < 0.2f))
				{
					_dirty = false;
					DrawLines(now);
				}
				if (Plugin.MiniLogPie.Value && CombatLogWindow.Feed.Version != _pieVersion && now >= _nextPie)
				{
					_nextPie = now + 0.5f;
					_pieVersion = CombatLogWindow.Feed.Version;
					DrawPie();
				}
			}
		}

		private static bool ShouldShow()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Invalid comparison between Unknown and I4
			if (!Plugin.MiniLogEnabled.Value || CombatLogWindow.IsOpen)
			{
				return false;
			}
			Service instance = Singleton<Service>.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				LevelManager levelManager = instance.levelManager;
				obj = ((levelManager != null) ? levelManager.player : null);
			}
			if ((Object)obj == (Object)null)
			{
				return false;
			}
			GameBase instance2 = Scene<GameBase>.instance;
			UIManager val = ((instance2 != null) ? instance2.uiManager : null);
			if ((Object)(object)val != (Object)null)
			{
				return (int)val.hideOption != 2;
			}
			return false;
		}

		private void CollectNewLines(float now)
		{
			CombatLogWindow.UpdateFeed();
			LogFeed feed = CombatLogWindow.Feed;
			if (feed.Rebuilds != _rebuildsSeen)
			{
				_rebuildsSeen = feed.Rebuilds;
				_cursor = feed.Shown.Count;
				_lines.Clear();
				_dirty = true;
			}
			int num = Mathf.Clamp(Plugin.MiniLogLines.Value, 1, 8);
			while (_cursor < feed.Shown.Count)
			{
				_lines.Add((feed.Shown[_cursor], now));
				_lastNew = now;
				_dirty = true;
				_cursor++;
			}
			if (_lines.Count > num)
			{
				_lines.RemoveRange(0, _lines.Count - num);
			}
		}

		private void DrawLines(float now)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < _lines.Count; i++)
			{
				int num = _lines.Count - 1 - i;
				float num2 = Mathf.Max(0.3f, 1f - (float)num * 0.2f);
				num2 *= Mathf.Clamp01((now - _lines[i].arrived) / 0.2f);
				if (i > 0)
				{
					stringBuilder.Append('\n');
				}
				(DamageRecord, float) tuple = _lines[i];
				stringBuilder.Append(LogText.CompactLine(in tuple.Item1, num2));
			}
			((TMP_Text)_text).text = stringBuilder.ToString();
		}

		private void DrawPie()
		{
			List<(double, Color)> list = (from s in DamageStats.FromTotals(CombatLogWindow.Feed.TotalBySource)
				select (Value: s.Value, DamageSources.Color(s.Key))).ToList();
			((Behaviour)_pieImage).enabled = list.Count > 0;
			_pie.Draw(list);
		}

		private void Build()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_004e: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			_canvas = UiKit.OverlayCanvas("DamageInsight_MiniLog", 4000);
			_root = UiKit.Rect("MiniLog", ((Component)_canvas).transform);
			RectTransform root = _root;
			RectTransform root2 = _root;
			Vector2 val = (_root.pivot = Vector2.zero);
			Vector2 anchorMin = (root2.anchorMax = val);
			root.anchorMin = anchorMin;
			_group = ((Component)_root).gameObject.AddComponent<CanvasGroup>();
			_group.blocksRaycasts = false;
			_group.interactable = false;
			_text = UiKit.Text("Lines", (Transform)(object)_root, "", 14f, (TextAlignmentOptions)1025);
			((TMP_Text)_text).enableWordWrapping = false;
			((TMP_Text)_text).overflowMode = (TextOverflowModes)1;
			((TMP_Text)_text).outlineWidth = 0.22f;
			((TMP_Text)_text).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)220);
			_pie = new PieChart(64);
			RectTransform val3 = UiKit.Rect("Pie", (Transform)(object)_root);
			((Vector2)(ref val))..ctor(1f, 0f);
			val3.pivot = val;
			anchorMin = (val3.anchorMax = val);
			val3.anchorMin = anchorMin;
			val3.anchoredPosition = Vector2.zero;
			val3.sizeDelta = new Vector2(40f, 40f);
			_pieImage = ((Component)val3).gameObject.AddComponent<RawImage>();
			_pieImage.texture = (Texture)(object)_pie.Texture;
			((Graphic)_pieImage).raycastTarget = false;
			((Behaviour)_pieImage).enabled = false;
			Place();
		}

		private void Place()
		{
			//IL_001f: 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)
			//IL_005b: 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_0097: 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_0143: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)Mathf.Clamp(Plugin.MiniLogLines.Value, 1, 8) * 19f + 4f;
			Vector2 canvasSize = UiKit.CanvasSize;
			float num2;
			float num3;
			float num4;
			if (TryGetMinimapRect(out var rect))
			{
				num2 = ((Rect)(ref rect)).xMin;
				num3 = ((Rect)(ref rect)).width;
				num4 = ((Rect)(ref rect)).yMax + Plugin.MiniLogOffsetY.Value;
			}
			else
			{
				num3 = 314f;
				num2 = canvasSize.x - num3 - 18f;
				num4 = 190f + Plugin.MiniLogOffsetY.Value;
			}
			_root.anchoredPosition = new Vector2(num2, num4);
			_root.sizeDelta = new Vector2(num3, num);
			bool value = Plugin.MiniLogPie.Value;
			((Component)_pieImage).gameObject.SetActive(value);
			((TMP_Text)_text).rectTransform.Stretch(0f, 0f, value ? 48f : 0f, 0f);
			if (!_loggedPlacement)
			{
				_loggedPlacement = true;
				Plugin.Log.LogInfo((object)$"Mini log placed at ({num2:0},{num4:0}) size {num3:0}x{num:0} (canvas {canvasSize.x:0}x{canvasSize.y:0})");
			}
		}

		private static bool TryGetMinimapRect(out Rect rect)
		{
			//IL_0001: 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_00f9: 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_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_0111: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_0149: Unknown result type (might be due to invalid IL or missing references)
			rect = default(Rect);
			try
			{
				GameBase instance = Scene<GameBase>.instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					UIManager uiManager = instance.uiManager;
					obj = ((uiManager != null) ? uiManager.headupDisplay : null);
				}
				HeadupDisplay val = (HeadupDisplay)obj;
				GameObject val2 = (((Object)(object)val != (Object)null) ? val._rightBottomWithMinimap : null);
				if ((Object)(object)val2 == (Object)null || !val2.activeInHierarchy)
				{
					return false;
				}
				RectTransform val3 = (from r in val2.GetComponentsInChildren<RawImage>(false)
					select ((Graphic)r).rectTransform into r
					orderby Area(r) descending
					select r).FirstOrDefault();
				if ((Object)(object)val3 == (Object)null)
				{
					return false;
				}
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				val3.GetWorldCorners(array);
				Canvas componentInParent = ((Component)val3).GetComponentInParent<Canvas>();
				Canvas val4 = ((componentInParent != null) ? componentInParent.rootCanvas : null);
				Camera obj2 = (((Object)(object)val4 != (Object)null && (int)val4.renderMode != 0) ? val4.worldCamera : null);
				Vector2 val5 = RectTransformUtility.WorldToScreenPoint(obj2, array[0]) / UiKit.CanvasScale;
				Vector2 val6 = RectTransformUtility.WorldToScreenPoint(obj2, array[2]) / UiKit.CanvasScale;
				rect = Rect.MinMaxRect(val5.x, val5.y, val6.x, val6.y);
				return ((Rect)(ref rect)).width > 20f && ((Rect)(ref rect)).height > 20f;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Mini log: could not find the minimap: " + ex.Message));
				return false;
			}
		}

		private static float Area(RectTransform r)
		{
			//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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = r.rect;
			float width = ((Rect)(ref rect)).width;
			rect = r.rect;
			return width * ((Rect)(ref rect)).height * ((Transform)r).lossyScale.x * ((Transform)r).lossyScale.y;
		}
	}
	public class MoveCounterLabel : MonoBehaviour
	{
		private CharacterHealthBar _bar;

		private RectTransform _rect;

		private TextMeshProUGUI _text;

		private TextMeshProUGUI _shadow;

		private float _nextUpdate;

		private string _last = "";

		public static void Attach(CharacterHealthBar bar, TMP_FontAsset font)
		{
			//IL_004d: 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_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)
			//IL_0074: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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)
			if (!((Object)(object)bar == (Object)null) && !((Object)(object)bar._container == (Object)null) && !((Object)(object)bar._healthBar == (Object)null) && !((Object)(object)((Component)bar).GetComponentInChildren<MoveCounterLabel>(true) != (Object)null))
			{
				GameObject val = new GameObject("DamageInsight_MoveCounter", new Type[1] { typeof(RectTransform) })
				{
					layer = ((Component)bar._container).gameObject.layer
				};
				RectTransform val2 = (RectTransform)val.transform;
				((Transform)val2).SetParent((Transform)(object)bar._container, false);
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(0.5f, 1f);
				val2.pivot = val3;
				Vector2 anchorMin = (val2.anchorMax = val3);
				val2.anchorMin = anchorMin;
				((Transform)val2).SetAsLastSibling();
				MoveCounterLabel moveCounterLabel = val.AddComponent<MoveCounterLabel>();
				moveCounterLabel._bar = bar;
				moveCounterLabel._rect = val2;
				moveCounterLabel._shadow = Text(val2, font, new Color(0f, 0f, 0f, 0.85f), new Vector2(2f, -2f));
				moveCounterLabel._text = Text(val2, font, Color.white, Vector2.zero);
			}
		}

		private static TextMeshProUGUI Text(RectTransform parent, TMP_FontAsset font, Color color, Vector2 offset)
		{
			//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_002e: 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_0039: 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_0042: 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_004d: 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_0058: 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_005a: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Text", new Type[1] { typeof(RectTransform) })
			{
				layer = ((Component)parent).gameObject.layer
			};
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			Vector2 offsetMin = (val2.offsetMax = offset);
			val2.offsetMin = offsetMin;
			TextMeshProUGUI val4 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val4).font = font;
			}
			((TMP_Text)val4).alignment = (TextAlignmentOptions)258;
			((TMP_Text)val4).enableWordWrapping = true;
			((TMP_Text)val4).overflowMode = (TextOverflowModes)0;
			((Graphic)val4).raycastTarget = false;
			((Graphic)val4).color = color;
			((TMP_Text)val4).richText = true;
			return val4;
		}

		private void LateUpdate()
		{
			bool flag = Plugin.CodexMoveCounter != null && Plugin.CodexMoveCounter.Value;
			Place();
			if (!(Time.unscaledTime < _nextUpdate))
			{
				_nextUpdate = Time.unscaledTime + 0.25f;
				string text = (flag ? TextFor(_bar._character) : "");
				if (!(text == _last))
				{
					_last = text;
					((TMP_Text)_text).text = text;
					((TMP_Text)_shadow).text = Regex.Replace(text, "</?color[^>]*>", "");
				}
			}
		}

		private void Place()
		{
			//IL_0012: 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_0018: 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_0034: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_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_0085: 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)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00fc: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			RectTransform healthBar = _bar._healthBar;
			Vector3 defaultHealthScale = _bar._defaultHealthScale;
			if (defaultHealthScale.x != 0f)
			{
				Vector3 val = (((Object)(object)((Transform)healthBar).parent != (Object)null) ? ((Transform)healthBar).parent.lossyScale : Vector3.one);
				Rect rect = healthBar.rect;
				float num = ((Rect)(ref rect)).width * Mathf.Abs(defaultHealthScale.x) * val.x;
				rect = healthBar.rect;
				float num2 = ((Rect)(ref rect)).height * Mathf.Abs(defaultHealthScale.y) * val.y;
				Vector3 position = ((Transform)healthBar).position + new Vector3((0.5f - healthBar.pivot.x) * num, (0f - healthBar.pivot.y) * num2 - num2 * 0.35f, 0f);
				((Transform)_rect).position = position;
				Vector3 lossyScale = ((Transform)_rect).lossyScale;
				float num3 = Mathf.Clamp(((num2 > 1f) ? (num2 / lossyScale.y) : 24f) * 0.62f, 13f, 22f);
				_rect.sizeDelta = new Vector2(Mathf.Max(num / lossyScale.x, 360f), num3 * 3.2f);
				TextMeshProUGUI text = _text;
				float fontSize = (((TMP_Text)_shadow).fontSize = num3);
				((TMP_Text)text).fontSize = fontSize;
			}
		}

		private static string TextFor(Character boss)
		{
			if ((Object)(object)boss == (Object)null)
			{
				return "";
			}
			string text = "";
			FightRecorder.MoveCount? moveCount = FightRecorder.CountFor(boss);
			if (!moveCount.HasValue && BossAttacks.Covers(boss) && !BossAttacks.HasAi(boss))
			{
				Character val = FightRecorder.MainBoss();
				if (val != null)
				{
					moveCount = FightRecorder.CountFor(val);
					(string, string, CodexCategory)? tuple = CodexTracker.EntryOf(val);
					if (tuple.HasValue)
					{
						(string id, string key, CodexCategory category) entry = tuple.GetValueOrDefault();
						text = (CodexCatalog.Entries.FirstOrDefault((CodexEntry e) => e.Id == entry.id)?.Name ?? entry.key) + ": ";
					}
				}
			}
			if (!moveCount.HasValue)
			{
				return "";
			}
			return text + TextOf(moveCount.Value);
		}

		private static string TextOf(FightRecorder.MoveCount count)
		{
			if (count.Pending)
			{
				return "<color=#B8B8B8>Moves: reading its behaviour tree...</color>";
			}
			string text = ((count.Inside > 0) ? $" <color=#B8B8B8>({count.Inside} inside other moves)</color>" : "") + (count.Dark ? " <color=#C58CFF>(Dark Mirror)</color>" : "");
			if (count.Total == 0)
			{
				return $"Moves seen {count.Seen} · filmed {count.Filmed}{text}";
			}
			if (count.Seen >= count.Total)
			{
				string text2 = $"<color=#7CFC7C>ALL {count.Total} MOVES SEEN</color> · filmed {count.Filmed}/{count.Total}{text}";
				if (count.NotFilmed.Count != 0)
				{
					return text2 + "\n<size=80%><color=#D8C8A8>Not on film yet: " + List(count.NotFilmed) + "</color></size>";
				}
				return text2;
			}
			return $"Moves seen <b>{count.Seen}/{count.Total}</b> · filmed {count.Filmed}{text}" + "\n<size=80%><color=#D8C8A8>Missing: " + List(count.Missing) + "</color></size>";
		}

		private static string List(List<string> names)
		{
			if (names.Count > 6)
			{
				return string.Join(", ", names.Take(6)) + $" (+{names.Count - 6})";
			}
			return string.Join(", ", names);
		}
	}
	public sealed class PieChart
	{
		private readonly int Size;

		private const float InnerRadius = 0.56f;

		private readonly Color32[] _pixels;

		public Texture2D Texture { get; }

		public PieChart(int size = 256)
		{
			//IL_002a: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Size = size;
			_pixels = (Color32[])(object)new Color32[size * size];
			Texture = new Texture2D(Size, Size, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Draw(new List<(double, Color)>());
		}

		public void Draw(IReadOnlyList<(double value, Color color)> slices)
		{
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			double num = 0.0;
			foreach (var slice in slices)
			{
				num += slice.value;
			}
			float[] array = new float[slices.Count];
			double num2 = 0.0;
			for (int i = 0; i < slices.Count; i++)
			{
				num2 += slices[i].value;
				array[i] = ((num > 0.0) ? ((float)(num2 / num)) : 0f);
			}
			Color32 val = default(Color32);
			((Color32)(ref val))..ctor((byte)58, (byte)48, (byte)68, byte.MaxValue);
			float num3 = (float)Size / 2f;
			for (int j = 0; j < Size; j++)
			{
				for (int k = 0; k < Size; k++)
				{
					float num4 = ((float)k + 0.5f - num3) / num3;
					float num5 = ((float)j + 0.5f - num3) / num3;
					float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5);
					float num7 = 1f / num3;
					float num8 = Mathf.Clamp01((1f - num6) / num7) * Mathf.Clamp01((num6 - 0.56f) / num7);
					if (num8 <= 0f)
					{
						_pixels[j * Size + k] = new Color32((byte)0, (byte)0, (byte)0, (byte)0);
						continue;
					}
					Color val2 = Color32.op_Implicit(val);
					if (num > 0.0)
					{
						float num9 = Mathf.Atan2(num4, num5) / ((float)Math.PI * 2f);
						if (num9 < 0f)
						{
							num9 += 1f;
						}
						for (int l = 0; l < array.Length; l++)
						{
							if (num9 <= array[l])
							{
								val2 = slices[l].color;
								break;
							}
						}
					}
					val2.a *= num8;
					_pixels[j * Size + k] = Color32.op_Implicit(val2);
				}
			}
			Texture.SetPixels32(_pixels);
			Texture.Apply();
		}
	}
	[HarmonyPatch(typeof(FloatingText))]
	public static class PopupIcon
	{
		private const string ChildName = "DamageInsight_Icon";

		private const float Gap = 0.08f;

		public static SpriteRenderer Show(FloatingText floatingText, Sprite sprite)
		{
			//IL_0028: 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_003e: 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_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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: 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_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			TextMeshPro text = floatingText._text;
			Transform transform = text.transform;
			Transform val = transform.Find("DamageInsight_Icon");
			SpriteRenderer val3;
			if ((Object)(object)val == (Object)null)
			{
				GameObject val2 = new GameObject("DamageInsight_Icon")
				{
					layer = ((Component)text).gameObject.layer
				};
				val2.transform.SetParent(transform, false);
				val3 = val2.AddComponent<SpriteRenderer>();
			}
			else
			{
				val3 = ((Component)val).GetComponent<SpriteRenderer>();
			}
			val3.sprite = sprite;
			val3.color = Color.white;
			((Renderer)val3).sortingLayerID = text.sortingLayerID;
			((Renderer)val3).sortingOrder = text.sortingOrder;
			((TMP_Text)text).ForceMeshUpdate(false, false);
			float num = float.MinValue;
			float num2 = float.MaxValue;
			float num3 = float.MaxValue;
			TMP_TextInfo textInfo = ((TMP_Text)text).textInfo;
			for (int i = 0; i < textInfo.characterCount; i++)
			{
				TMP_CharacterInfo val4 = textInfo.characterInfo[i];
				if (val4.isVisible)
				{
					num = Mathf.Max(num, val4.topLeft.y);
					num2 = Mathf.Min(num2, val4.bottomLeft.y);
					num3 = Mathf.Min(num3, val4.bottomLeft.x);
				}
			}
			if (num3 == float.MaxValue)
			{
				Bounds textBounds = ((TMP_Text)text).textBounds;
				num = ((Bounds)(ref textBounds)).max.y;
				num2 = ((Bounds)(ref textBounds)).min.y;
				num3 = ((Bounds)(ref textBounds)).min.x;
			}
			float num4 = Mathf.Max(num - num2, 0.05f);
			Bounds bounds = sprite.bounds;
			float num5 = num4 / Mathf.Max(((Bounds)(ref bounds)).size.y, 0.001f);
			((Component)val3).transform.localScale = new Vector3(num5, num5, 1f);
			bounds = sprite.bounds;
			float num6 = ((Bounds)(ref bounds)).size.x * num5;
			((Component)val3).transform.localPosition = new Vector3(num3 - 0.08f - num6 / 2f, (num + num2) / 2f, 0f);
			((Component)val3).gameObject.SetActive(true);
			return val3;
		}

		[HarmonyPostfix]
		[HarmonyPatch("Initialize", new Type[]
		{
			typeof(string),
			typeof(Vector3)
		})]
		private static void HideOnReuse(FloatingText __instance)
		{
			Transform val = (((Object)(object)__instance._text != (Object)null) ? __instance._text.transform.Find("DamageInsight_Icon") : null);
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
			}
		}
	}
	public enum SettingKind
	{
		Choice,
		Key,
		Action
	}
	public sealed class SettingItem
	{
		public string Section = "";

		public string Label = "";

		public string Help = "";

		public SettingKind Kind;

		public ConfigEntryBase Entry;

		public string Action;

		public bool Wraps = true;

		public bool ShowsIcon;

		internal readonly List<object> Steps = new List<object>();

		internal Func<object, string> Formatter = (object v) => Convert.ToString(v, CultureInfo.InvariantCulture);

		public string DefaultText
		{
			get
			{
				if (Entry != null)
				{
					return Format(Entry.DefaultValue);
				}
				return "";
			}
		}

		public string Format(object value)
		{
			if (value != null)
			{
				return Formatter(value);
			}
			return "";
		}

		public List<object> Values()
		{
			List<object> list = new List<object>(Steps);
			ConfigEntryBase entry = Entry;
			object current = ((entry != null) ? entry.BoxedValue : null);
			if (current == null || list.Any((object v) => Same(v, current)))
			{
				return list;
			}
			if (IsNumber(current))
			{
				double c = Convert.ToDouble(current, CultureInfo.InvariantCulture);
				int num = list.FindIndex((object v) => IsNumber(v) && Convert.ToDouble(v, CultureInfo.InvariantCulture) > c);
				list.Insert((num < 0) ? list.Count : num, current);
			}
			else
			{
				list.Insert(0, current);
			}
			return list;
		}

		public static int IndexOf(IList<object> values, object value)
		{
			for (int i = 0; i < values.Count; i++)
			{
				if (Same(values[i], value))
				{
					return i;
				}
			}
			return 0;
		}

		internal static bool Same(object a, object b)
		{
			if (IsNumber(a) && IsNumber(b))
			{
				return Math.Abs(Convert.ToDouble(a, CultureInfo.InvariantCulture) - Convert.ToDouble(b, CultureInfo.InvariantCulture)) < 0.0001;
			}
			return object.Equals(a, b);
		}

		private static bool IsNumber(object v)
		{
			if (v is float || v is double || v is int || v is long)
			{
				return true;
			}
			return false;
		}
	}
	public static class SettingsCatalog
	{
		private enum Unit
		{
			Plain,
			Seconds,
			Percent
		}

		private sealed class Spec
		{
			public string Label;

			public string Help;

			public double Min;

			public double Max;

			public double Step;

			public Unit Unit;

			public bool Hidden;
		}

		public const string ResetWindow = "ResetWindow";

		public const string ResetAll = "ResetAll";

		private static readonly (string section, string heading)[] Sections = new(string, string)[11]
		{
			("General", Loc.N("General")),
			("Damage Numbers", Loc.N("Damage numbers")),
			("Damage Icons", Loc.N("Damage icons")),
			("Boss Health Bar", Loc.N("Boss health bars")),
			("Descriptions", Loc.N("Descriptions")),
			("Combat Log", Loc.N("Combat log")),
			("Mini Log", Loc.N("Mini log")),
			("Cooldown Ticker", Loc.N("Cooldown seconds")),
			("Codex", Loc.N("Codex")),
			("Codex balance", Loc.N("Codex unlocks")),
			("Developer", Loc.N("Developer"))
		};

		private static readonly Dictionary<string, string> BalanceGroups = new Dictionary<string, string>
		{
			["Enemies"] = Loc.N("Codex unlocks: enemies"),
			["Bosses"] = Loc.N("Codex unlocks: bosses"),
			["Gear"] = Loc.N("Codex unlocks: gear")
		};

		private static readonly Dictionary<string, Spec> Specs = new Dictionary<string, Spec>
		{
			["General/Language"] = On(Loc.N("Language"), Loc.N("The language of the mod's texts. \"Game language\" follows the game's own setting.")),
			["Damage Numbers/ShowSourceTag"] = On(Loc.N("Show source"), Loc.N("Mark each damage number with where the damage came from: an icon or a short tag (ATK, SKILL, ITEM...).")),
			["Damage Numbers/UseIcons"] = On(Loc.N("Use icons"), Loc.N("Use icons instead of text tags where an icon is set (see Damage icons below).")),
			["Damage Numbers/HoldSeconds"] = Number(Loc.N("Stay visible"), 0.0, 5.0, 0.1, Unit.Seconds, Loc.N("How long a damage number stays fully visible after it pops up (the game's own: about 0.15 s).")),
			["Damage Numbers/FadeSeconds"] = Number(Loc.N("Fade out"), 0.1, 5.0, 0.1, Unit.Seconds, Loc.N("How long a damage number takes to fade out.")),
			["Boss Health Bar/ShowNumbers"] = On(Loc.N("HP numbers"), Loc.N("Show current / maximum HP as text on the health bars of bosses, adventurers and dark enemies.")),
			["Descriptions/ShowDamageNumbers"] = On(Loc.N("Damage numbers"), Loc.N("Add your real damage (with your current stats) to the descriptions of skulls, skills, swaps, items, essences and inscriptions.")),
			["Descriptions/PreviewPickup"] = On(Loc.N("Pickup preview"), Loc.N("Items on the ground, in shops and in the swap menu show their numbers as if you had picked them up (their stats and inscription steps included).")),
			["Combat Log/ToggleKey"] = On(Loc.N("Open / close key"), Loc.N("The key that opens and closes the combat log.")),
			["Combat Log/UseDialogueBackground"] = On(Loc.N("Dialogue frame"), Loc.N("Use the NPC dialogue box artwork as the window background (off: a plain dark panel).")),
			["Combat Log/BackgroundOpacity"] = Number(Loc.N("Background"), 0.0, 1.0, 0.05, Unit.Percent, Loc.N("How solid the dialogue background is (0% invisible, 100% solid).")),
			["Combat Log/WindowRect"] = new Spec
			{
				Hidden = true
			},
			["Combat Log/RecordCalculations"] = On(Loc.N("Calculations"), Loc.N("Record how every hit's number came about (stats, items, inscriptions, dark abilities, crits, debuffs); hover a log line to see it.")),
			["Combat Log/SaveToFile"] = On(Loc.N("Save to file"), Loc.N("Also write every hit (with its calculation) to BepInEx/DamageInsight/CombatLogs, one file per game session (the newest 30 are kept).")),
			["Mini Log/Enabled"] = On(Loc.N("Show mini log"), Loc.N("Show a few log lines above the minimap. Can also be switched in the combat log window.")),
			["Mini Log/Lines"] = Number(Loc.N("Lines"), 1.0, 8.0, 1.0, Unit.Plain, Loc.N("How many lines the mini log shows.")),
			["Mini Log/HideAfterSeconds"] = Number(Loc.N("Hide after"), 1.0, 30.0, 1.0, Unit.Seconds, Loc.N("Hide the mini log when no new damage came in for this long.")),
			["Mini Log/ShowPie"] = On(Loc.N("Pie chart"), Loc.N("Show a tiny pie chart