Decompiled source of BloodCraftHub v0.14.0

BloodCraftHub.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BloodCraftHub.Behaviors;
using BloodCraftHub.Config;
using BloodCraftHub.Resources;
using BloodCraftHub.Services;
using BloodCraftHub.UI;
using BloodCraftHub.UI.Forms;
using BloodCraftHub.UI.Framework.CustomLib;
using BloodCraftHub.UI.Framework.CustomLib.Controls;
using BloodCraftHub.UI.Framework.CustomLib.Panel;
using BloodCraftHub.UI.Framework.CustomLib.Util;
using BloodCraftHub.UI.Framework.ModernLib;
using BloodCraftHub.UI.Framework.UniverseLib.UI;
using BloodCraftHub.UI.Framework.UniverseLib.UI.Models;
using BloodCraftHub.UI.Framework.UniverseLib.UI.ObjectPool;
using BloodCraftHub.UI.Framework.UniverseLib.UI.Panels;
using BloodCraftHub.UI.Framework.UniverseLib.UI.Widgets;
using BloodCraftHub.UI.Framework.UniverseLib.UI.Widgets.ScrollView;
using BloodCraftHub.UI.ModContent;
using BloodCraftHub.UI.ModContent.Data;
using BloodCraftHub.Utils;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Network;
using ProjectM.Scripting;
using ProjectM.UI;
using Stunlock.Core;
using TMPro;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("kdpen")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Unified client UI for V Rising's Bloodcraft mod. Surfaces every Bloodcraft, KindredCommands, and KindredLogistics chat command as buttons + forms.")]
[assembly: AssemblyFileVersion("0.14.0.0")]
[assembly: AssemblyInformationalVersion("0.14.0+b0b839b6e4b535a43e18461164d7b185266c4a63")]
[assembly: AssemblyProduct("BloodCraftHub")]
[assembly: AssemblyTitle("BloodCraftHub")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.14.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BloodCraftHub
{
	internal static class Core
	{
		private static World _client;

		public static World ClientWorld => _client;

		public static EntityManager EntityManager => _client.EntityManager;

		public static ManualLogSource Log => Plugin.LogInstance;

		public static bool HasInitialized { get; private set; }

		public static Entity LocalCharacter { get; set; } = Entity.Null;


		public static Entity LocalUser { get; set; } = Entity.Null;


		public static byte[] SharedKey { get; set; }

		public static void Initialize(World clientWorld)
		{
			if (!HasInitialized)
			{
				_client = clientWorld;
				HasInitialized = true;
				Log.LogInfo((object)"Core initialized on client world.");
			}
		}

		public static void Reset()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			_client = null;
			LocalCharacter = Entity.Null;
			LocalUser = Entity.Null;
			SharedKey = null;
			HasInitialized = false;
		}
	}
	[BepInProcess("VRising.exe")]
	[BepInPlugin("BloodCraftHub", "BloodCraftHub", "0.14.0")]
	public class Plugin : BasePlugin
	{
		public const bool IS_TESTING = false;

		private static World _client;

		private Harmony _harmony;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource LogInstance => ((BasePlugin)Instance).Log;

		public static Settings Settings { get; private set; }

		public static BCHubUIManager UIManager { get; private set; }

		public static CoreUpdateBehavior CoreUpdateBehavior { get; private set; }

		public static bool IsClient { get; private set; }

		public static bool IsInitialized { get; private set; }

		public static bool IsGameDataInitialized { get; set; }

		public static EntityManager EntityManager => _client.EntityManager;

		public static Entity LocalCharacter { get; set; } = Entity.Null;


		public static bool IsClientNull()
		{
			return _client == null;
		}

		public override void Load()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			Instance = this;
			IsClient = Application.productName != "VRisingServer";
			LogUtils.Init(((BasePlugin)this).Log);
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val;
			if (!IsClient)
			{
				ManualLogSource log = ((BasePlugin)this).Log;
				val = new BepInExInfoLogInterpolatedStringHandler(45, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("BloodCraftHub");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("0.14.0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] is a client mod — not loading on server (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Application.productName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
				}
				log.LogInfo(val);
				return;
			}
			Settings = new Settings().InitConfig();
			Theme.UIFontMultiplier = Settings.UITextScale;
			Theme.OverlayFontMultiplier = Settings.OverlayTextScale;
			EclipseProtocolService.Initialize();
			UIManager = new BCHubUIManager();
			CoreUpdateBehavior = new CoreUpdateBehavior();
			CoreUpdateBehavior.Setup();
			CoreUpdateBehavior.Actions.Add(MessageService.ProcessAllMessages);
			CoreUpdateBehavior.Actions.Add(MessageService.TickInterceptTimeouts);
			CoreUpdateBehavior.Actions.Add(VBloodScannerService.Tick);
			CoreUpdateBehavior.Actions.Add(ShiftCooldownService.Tick);
			CoreUpdateBehavior.Actions.Add(TooltipHover.TickAll);
			CoreUpdateBehavior.Actions.Add(FormDropdownRegistry.TickCloseOnOutsideClick);
			CoreUpdateBehavior.Actions.Add(SliderClickRegistry.TickClickOnTrack);
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "BloodCraftHub");
			IsInitialized = true;
			ManualLogSource log2 = ((BasePlugin)this).Log;
			val = new BepInExInfoLogInterpolatedStringHandler(17, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("BloodCraftHub");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("0.14.0");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded.");
			}
			log2.LogInfo(val);
		}

		public override bool Unload()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			return true;
		}

		public static void UIOnInitialize()
		{
			if (!UIManager.IsInitialized)
			{
				UIManager.SetupAndShowUI();
				UIManager.RestoreOverlaysFromSettings();
				VBloodScannerService.Initialize();
				LogUtils.LogInfo("UI Manager initialized.");
			}
		}

		public static void GameDataOnInitialize(World world)
		{
			if (!IsGameDataInitialized && IsClient)
			{
				_client = world;
				IsGameDataInitialized = true;
				LogUtils.LogInfo("Client world bound; game data initialized.");
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "BloodCraftHub";

		public const string PLUGIN_NAME = "BloodCraftHub";

		public const string PLUGIN_VERSION = "0.14.0";
	}
}
namespace BloodCraftHub.Utils
{
	public static class Extensions
	{
		private static EntityManager EntityManager => Plugin.EntityManager;

		public static Color GetTransparent(this Color baseColor, float alpha = 0.7f)
		{
			//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)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			return new Color(baseColor.r, baseColor.g, baseColor.b, alpha);
		}

		public static bool Has<T>(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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)
			EntityManager entityManager = EntityManager;
			return ((EntityManager)(ref entityManager)).HasComponent(entity, new ComponentType(Il2CppType.Of<T>(), (AccessMode)0));
		}

		public unsafe static T Read<T>(this Entity entity) where T : struct
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0019: 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)
			TypeIndex typeIndex = new ComponentType(Il2CppType.Of<T>(), (AccessMode)0).TypeIndex;
			EntityManager entityManager = EntityManager;
			return Marshal.PtrToStructure<T>(new IntPtr(((EntityManager)(ref entityManager)).GetComponentDataRawRO(entity, typeIndex)));
		}

		public unsafe static void Write<T>(this Entity entity, T componentData) where T : struct
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003d: 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)
			TypeIndex typeIndex = new ComponentType(Il2CppType.Of<T>(), (AccessMode)0).TypeIndex;
			byte[] array = StructureToByteArray(componentData);
			int num = Marshal.SizeOf<T>();
			fixed (byte* ptr = array)
			{
				EntityManager entityManager = EntityManager;
				((EntityManager)(ref entityManager)).SetComponentDataRaw(entity, typeIndex, (void*)ptr, num);
			}
		}

		public static bool HasValue(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return entity != Entity.Null;
		}

		private static byte[] StructureToByteArray<T>(T structure) where T : struct
		{
			int num = Marshal.SizeOf(structure);
			byte[] array = new byte[num];
			IntPtr intPtr = Marshal.AllocHGlobal(num);
			try
			{
				Marshal.StructureToPtr(structure, intPtr, fDeleteOld: true);
				Marshal.Copy(intPtr, array, 0, num);
				return array;
			}
			finally
			{
				Marshal.FreeHGlobal(intPtr);
			}
		}
	}
	public static class LogUtils
	{
		private static ManualLogSource _log;

		public static void Init(ManualLogSource log)
		{
			_log = log;
		}

		public static void LogInfo(object msg)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo(msg);
			}
		}

		public static void LogWarning(object msg)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogWarning(msg);
			}
		}

		public static void LogError(object msg)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogError(msg);
			}
		}

		public static void LogDebug(object msg)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogDebug(msg);
			}
		}
	}
}
namespace BloodCraftHub.UI
{
	public class BCHubUIManager : UIManagerBase
	{
		private readonly List<IPanelBase> _panels = new List<IPanelBase>();

		private FloatingButtonPanel _floatingButton;

		private MainPanel _mainPanel;

		private ExperienceOverlayPanel _experienceOverlay;

		private FamiliarOverlayPanel _familiarOverlay;

		private FamiliarBrowserOverlayPanel _familiarBrowserOverlay;

		private DailyQuestOverlayPanel _dailyQuestOverlay;

		private ProfessionOverlayPanel _professionOverlay;

		private ShiftSpellOverlayPanel _shiftSpellOverlay;

		private CombinedOverlayPanel _combinedOverlay;

		private bool _overlaysSuppressed;

		private Action _deferredMainPanelRebuild;

		private Action _deferredOverlayRebuild;

		public bool IsMainPanelOpen
		{
			get
			{
				if (_mainPanel != null)
				{
					return _mainPanel.Enabled;
				}
				return false;
			}
		}

		public MainPanel MainPanel => _mainPanel;

		public ExperienceOverlayPanel ExperienceOverlay => _experienceOverlay;

		public FamiliarOverlayPanel FamiliarOverlay => _familiarOverlay;

		public FamiliarBrowserOverlayPanel FamiliarBrowserOverlay => _familiarBrowserOverlay;

		public DailyQuestOverlayPanel DailyQuestOverlay => _dailyQuestOverlay;

		public ProfessionOverlayPanel ProfessionOverlay => _professionOverlay;

		public ShiftSpellOverlayPanel ShiftSpellOverlay => _shiftSpellOverlay;

		public CombinedOverlayPanel CombinedOverlay => _combinedOverlay;

		public bool AreOverlaysSuppressed => _overlaysSuppressed;

		public void ApplyOverlayLockState()
		{
			bool lockOverlays = Settings.LockOverlays;
			ApplyPinnedTo(_experienceOverlay, lockOverlays);
			ApplyPinnedTo(_familiarOverlay, lockOverlays);
			ApplyPinnedTo(_familiarBrowserOverlay, lockOverlays);
			ApplyPinnedTo(_dailyQuestOverlay, lockOverlays);
			ApplyPinnedTo(_professionOverlay, lockOverlays);
			ApplyPinnedTo(_shiftSpellOverlay, lockOverlays);
			ApplyPinnedTo(_combinedOverlay, lockOverlays);
		}

		private static void ApplyPinnedTo(ResizeablePanelBase panel, bool pinned)
		{
			if (panel != null)
			{
				panel.IsPinned = pinned;
			}
		}

		public override void Reset()
		{
			base.Reset();
			foreach (IPanelBase panel in _panels)
			{
				if (panel is ResizeablePanelBase resizeablePanelBase)
				{
					resizeablePanelBase.Reset();
				}
				panel.Destroy();
			}
			_panels.Clear();
			_floatingButton = null;
			_mainPanel = null;
			_experienceOverlay = null;
			_familiarOverlay = null;
			_familiarBrowserOverlay = null;
			_dailyQuestOverlay = null;
			_professionOverlay = null;
			_combinedOverlay = null;
			_shiftSpellOverlay = null;
		}

		protected override void AddMainContentPanel()
		{
			_floatingButton = new FloatingButtonPanel(base.UiBase);
			_panels.Add(_floatingButton);
		}

		public override void SetActive(bool active)
		{
			_floatingButton?.SetActive(active);
			_mainPanel?.SetActive(active && IsMainPanelOpen);
			_experienceOverlay?.SetActive(active && (_experienceOverlay?.Enabled ?? false));
			_familiarOverlay?.SetActive(active && (_familiarOverlay?.Enabled ?? false));
			_familiarBrowserOverlay?.SetActive(active && (_familiarBrowserOverlay?.Enabled ?? false));
			_dailyQuestOverlay?.SetActive(active && (_dailyQuestOverlay?.Enabled ?? false));
			_professionOverlay?.SetActive(active && (_professionOverlay?.Enabled ?? false));
			_shiftSpellOverlay?.SetActive(active && (_shiftSpellOverlay?.Enabled ?? false));
		}

		public void ToggleMainPanel()
		{
			EnsureMainPanel();
			_mainPanel.SetActive(!_mainPanel.Enabled);
		}

		public void ShowTab(PanelType tab)
		{
			EnsureMainPanel();
			_mainPanel.SetActive(active: true);
			_mainPanel.ShowTab(tab);
		}

		public void ToggleOverlay(PanelType overlay)
		{
			switch (overlay)
			{
			case PanelType.ExperienceOverlay:
				EnsureExperienceOverlay();
				_experienceOverlay.SetActive(!_experienceOverlay.Enabled);
				Settings.SetShowExperienceOverlay(_experienceOverlay.Enabled);
				break;
			case PanelType.FamiliarOverlay:
				EnsureFamiliarOverlay();
				_familiarOverlay.SetActive(!_familiarOverlay.Enabled);
				Settings.SetShowFamiliarOverlay(_familiarOverlay.Enabled);
				break;
			case PanelType.FamiliarBrowserOverlay:
				EnsureFamiliarBrowserOverlay();
				_familiarBrowserOverlay.SetActive(!_familiarBrowserOverlay.Enabled);
				Settings.SetShowFamiliarBrowser(_familiarBrowserOverlay.Enabled);
				break;
			case PanelType.DailyQuestOverlay:
				EnsureDailyQuestOverlay();
				_dailyQuestOverlay.SetActive(!_dailyQuestOverlay.Enabled);
				Settings.SetShowDailyQuestOverlay(_dailyQuestOverlay.Enabled);
				break;
			case PanelType.ProfessionOverlay:
				EnsureProfessionOverlay();
				_professionOverlay.SetActive(!_professionOverlay.Enabled);
				Settings.SetShowProfessionOverlay(_professionOverlay.Enabled);
				break;
			case PanelType.ShiftSpellOverlay:
				EnsureShiftSpellOverlay();
				_shiftSpellOverlay.SetActive(!_shiftSpellOverlay.Enabled);
				Settings.SetShowShiftSpellOverlay(_shiftSpellOverlay.Enabled);
				break;
			case PanelType.CombinedOverlay:
				Settings.SetShowCombinedOverlay(!(_combinedOverlay?.Enabled ?? false));
				ApplyCombinedOverlayMutualExclusion();
				break;
			default:
				throw new ArgumentOutOfRangeException("overlay", overlay, "Not a secondary overlay.");
			}
		}

		public void ApplyCombinedOverlayMutualExclusion()
		{
			if (Settings.ShowCombinedOverlay)
			{
				EnsureCombinedOverlay();
				_combinedOverlay.SetActive(active: true);
				EnsureExperienceOverlay();
				_experienceOverlay.SetActive(active: false);
				_familiarOverlay?.SetActive(active: false);
				_dailyQuestOverlay?.SetActive(active: false);
				_professionOverlay?.SetActive(active: false);
				return;
			}
			_combinedOverlay?.SetActive(active: false);
			if (Settings.ShowExperienceOverlay)
			{
				EnsureExperienceOverlay();
				_experienceOverlay.SetActive(active: true);
			}
			if (Settings.ShowFamiliarOverlay)
			{
				EnsureFamiliarOverlay();
				_familiarOverlay.SetActive(active: true);
			}
			if (Settings.ShowDailyQuestOverlay)
			{
				EnsureDailyQuestOverlay();
				_dailyQuestOverlay.SetActive(active: true);
			}
			if (Settings.ShowProfessionOverlay)
			{
				EnsureProfessionOverlay();
				_professionOverlay.SetActive(active: true);
			}
		}

		public void RefreshCombinedOverlaySections()
		{
			_combinedOverlay?.RefreshSections();
		}

		public void ToggleAllOverlaysSuppressed()
		{
			_overlaysSuppressed = !_overlaysSuppressed;
			Settings.OverlaysSuppressedByUser = _overlaysSuppressed;
			ApplyOverlaySuppression();
		}

		private void ApplyOverlaySuppression()
		{
			if (_overlaysSuppressed)
			{
				_experienceOverlay?.SetActive(active: false);
				_familiarOverlay?.SetActive(active: false);
				_familiarBrowserOverlay?.SetActive(active: false);
				_dailyQuestOverlay?.SetActive(active: false);
				_professionOverlay?.SetActive(active: false);
				_shiftSpellOverlay?.SetActive(active: false);
				_combinedOverlay?.SetActive(active: false);
				return;
			}
			if (Settings.ShowExperienceOverlay)
			{
				EnsureExperienceOverlay();
				_experienceOverlay.SetActive(active: true);
			}
			if (Settings.ShowFamiliarOverlay)
			{
				EnsureFamiliarOverlay();
				_familiarOverlay.SetActive(active: true);
			}
			if (Settings.ShowFamiliarBrowser)
			{
				EnsureFamiliarBrowserOverlay();
				_familiarBrowserOverlay.SetActive(active: true);
			}
			if (Settings.ShowDailyQuestOverlay)
			{
				EnsureDailyQuestOverlay();
				_dailyQuestOverlay.SetActive(active: true);
			}
			if (Settings.ShowProfessionOverlay)
			{
				EnsureProfessionOverlay();
				_professionOverlay.SetActive(active: true);
			}
			if (Settings.ShowShiftSpellOverlay)
			{
				EnsureShiftSpellOverlay();
				_shiftSpellOverlay.SetActive(active: true);
			}
		}

		public void RestoreOverlaysFromSettings()
		{
			if (Settings.ShowCombinedOverlay)
			{
				ApplyCombinedOverlayMutualExclusion();
			}
			else
			{
				if (Settings.ShowExperienceOverlay)
				{
					EnsureExperienceOverlay();
					_experienceOverlay.SetActive(active: true);
				}
				if (Settings.ShowFamiliarOverlay)
				{
					EnsureFamiliarOverlay();
					_familiarOverlay.SetActive(active: true);
				}
				if (Settings.ShowDailyQuestOverlay)
				{
					EnsureDailyQuestOverlay();
					_dailyQuestOverlay.SetActive(active: true);
				}
				if (Settings.ShowProfessionOverlay)
				{
					EnsureProfessionOverlay();
					_professionOverlay.SetActive(active: true);
				}
			}
			if (Settings.ShowFamiliarBrowser)
			{
				EnsureFamiliarBrowserOverlay();
				_familiarBrowserOverlay.SetActive(active: true);
			}
			if (Settings.ShowShiftSpellOverlay)
			{
				EnsureShiftSpellOverlay();
				_shiftSpellOverlay.SetActive(active: true);
			}
			if (Settings.ShowCombinedOverlay)
			{
				ApplyCombinedOverlayMutualExclusion();
			}
		}

		public bool IsOverlayOpen(PanelType overlay)
		{
			return overlay switch
			{
				PanelType.ExperienceOverlay => _experienceOverlay?.Enabled ?? false, 
				PanelType.FamiliarOverlay => _familiarOverlay?.Enabled ?? false, 
				PanelType.FamiliarBrowserOverlay => _familiarBrowserOverlay?.Enabled ?? false, 
				PanelType.DailyQuestOverlay => _dailyQuestOverlay?.Enabled ?? false, 
				PanelType.ProfessionOverlay => _professionOverlay?.Enabled ?? false, 
				PanelType.ShiftSpellOverlay => _shiftSpellOverlay?.Enabled ?? false, 
				PanelType.CombinedOverlay => _combinedOverlay?.Enabled ?? false, 
				_ => false, 
			};
		}

		private void EnsureMainPanel()
		{
			if (_mainPanel == null)
			{
				_mainPanel = new MainPanel(base.UiBase);
				_panels.Add(_mainPanel);
				_mainPanel.SetActive(active: false);
			}
		}

		private void EnsureExperienceOverlay()
		{
			if (_experienceOverlay == null)
			{
				_experienceOverlay = new ExperienceOverlayPanel(base.UiBase);
				_panels.Add(_experienceOverlay);
				_experienceOverlay.SetActive(active: false);
			}
		}

		private void EnsureFamiliarBrowserOverlay()
		{
			if (_familiarBrowserOverlay == null)
			{
				_familiarBrowserOverlay = new FamiliarBrowserOverlayPanel(base.UiBase);
				_panels.Add(_familiarBrowserOverlay);
				_familiarBrowserOverlay.SetActive(active: false);
			}
		}

		private void EnsureDailyQuestOverlay()
		{
			if (_dailyQuestOverlay == null)
			{
				_dailyQuestOverlay = new DailyQuestOverlayPanel(base.UiBase);
				_panels.Add(_dailyQuestOverlay);
				_dailyQuestOverlay.SetActive(active: false);
			}
		}

		private void EnsureFamiliarOverlay()
		{
			if (_familiarOverlay == null)
			{
				_familiarOverlay = new FamiliarOverlayPanel(base.UiBase);
				_panels.Add(_familiarOverlay);
				_familiarOverlay.SetActive(active: false);
			}
		}

		private void EnsureProfessionOverlay()
		{
			if (_professionOverlay == null)
			{
				_professionOverlay = new ProfessionOverlayPanel(base.UiBase);
				_panels.Add(_professionOverlay);
				_professionOverlay.SetActive(active: false);
			}
		}

		private void EnsureShiftSpellOverlay()
		{
			if (_shiftSpellOverlay == null)
			{
				_shiftSpellOverlay = new ShiftSpellOverlayPanel(base.UiBase);
				_panels.Add(_shiftSpellOverlay);
				_shiftSpellOverlay.SetActive(active: false);
			}
		}

		private void EnsureCombinedOverlay()
		{
			if (_combinedOverlay == null)
			{
				_combinedOverlay = new CombinedOverlayPanel(base.UiBase);
				_panels.Add(_combinedOverlay);
				_combinedOverlay.SetActive(active: false);
			}
		}

		public void RefreshAllOpacities()
		{
			_experienceOverlay?.RefreshOpacity();
			_familiarOverlay?.RefreshOpacity();
			_familiarBrowserOverlay?.RefreshOpacity();
			_dailyQuestOverlay?.RefreshOpacity();
			_professionOverlay?.RefreshOpacity();
			_shiftSpellOverlay?.RefreshOpacity();
			_combinedOverlay?.RefreshOpacity();
			_mainPanel?.RefreshOpacity();
			_floatingButton?.RefreshOpacity();
		}

		public void RefreshAllPanelBackgrounds()
		{
			_mainPanel?.RefreshBackgroundColor();
			_experienceOverlay?.RefreshBackgroundColor();
			_familiarOverlay?.RefreshBackgroundColor();
			_familiarBrowserOverlay?.RefreshBackgroundColor();
			_dailyQuestOverlay?.RefreshBackgroundColor();
			_professionOverlay?.RefreshBackgroundColor();
			_shiftSpellOverlay?.RefreshBackgroundColor();
			_combinedOverlay?.RefreshBackgroundColor();
		}

		public void RefreshScopedInnerBackgrounds()
		{
			_mainPanel?.RefreshInnerBackgroundColor();
			_familiarBrowserOverlay?.RefreshInnerBackgroundColor();
		}

		public void RefreshProfessionOverlay()
		{
			_professionOverlay?.Refresh();
		}

		public void RequestRebuildMainPanel()
		{
			if (_mainPanel != null)
			{
				CoreUpdateBehavior.Actions.Add(delegate
				{
					CoreUpdateBehavior.Actions.Remove(_deferredMainPanelRebuild);
					_deferredMainPanelRebuild = null;
					RebuildMainPanelNow();
				});
			}
		}

		private void RebuildMainPanelNow()
		{
			if (_mainPanel != null)
			{
				bool enabled = _mainPanel.Enabled;
				PanelType activeTab = _mainPanel.ActiveTab;
				_mainPanel?.Reset();
				_mainPanel.Destroy();
				_panels.Remove(_mainPanel);
				_mainPanel = null;
				if (enabled)
				{
					EnsureMainPanel();
					_mainPanel.SetActive(active: true);
					_mainPanel.ShowTab(activeTab);
				}
			}
		}

		public void RequestRebuildAllOverlays()
		{
			CoreUpdateBehavior.Actions.Add(delegate
			{
				CoreUpdateBehavior.Actions.Remove(_deferredOverlayRebuild);
				_deferredOverlayRebuild = null;
				RebuildAllOverlaysNow();
			});
		}

		private void RebuildAllOverlaysNow()
		{
			bool showCombinedOverlay = Settings.ShowCombinedOverlay;
			RebuildOverlay(ref _experienceOverlay, !showCombinedOverlay && Settings.ShowExperienceOverlay, (UIBase b) => new ExperienceOverlayPanel(b));
			RebuildOverlay(ref _familiarOverlay, !showCombinedOverlay && Settings.ShowFamiliarOverlay, (UIBase b) => new FamiliarOverlayPanel(b));
			RebuildOverlay(ref _familiarBrowserOverlay, Settings.ShowFamiliarBrowser, (UIBase b) => new FamiliarBrowserOverlayPanel(b));
			RebuildOverlay(ref _dailyQuestOverlay, !showCombinedOverlay && Settings.ShowDailyQuestOverlay, (UIBase b) => new DailyQuestOverlayPanel(b));
			RebuildOverlay(ref _professionOverlay, !showCombinedOverlay && Settings.ShowProfessionOverlay, (UIBase b) => new ProfessionOverlayPanel(b));
			RebuildOverlay(ref _shiftSpellOverlay, Settings.ShowShiftSpellOverlay, (UIBase b) => new ShiftSpellOverlayPanel(b));
			RebuildOverlay(ref _combinedOverlay, showCombinedOverlay, (UIBase b) => new CombinedOverlayPanel(b));
			_mainPanel?.RefreshAllOverlayToggleStates();
		}

		private void RebuildOverlay<T>(ref T slot, bool wasVisibleByConfig, Func<UIBase, T> factory) where T : ResizeablePanelBase
		{
			if (slot != null)
			{
				slot.Reset();
				slot.Destroy();
				_panels.Remove(slot);
				slot = null;
				if (wasVisibleByConfig)
				{
					T val = factory(base.UiBase);
					_panels.Add(val);
					val.SetActive(active: true);
					slot = val;
				}
			}
		}
	}
	public static class TooltipHover
	{
		private struct Binding
		{
			public RectTransform Rt;

			public string Text;
		}

		private static readonly List<Binding> _bindings = new List<Binding>();

		public static TextMeshProUGUI Sink;

		public static string IdlePlaceholder = "Hint: hover any control for help.";

		private static bool _firstHitLogged;

		public static int BindingCount => _bindings.Count;

		public static void Attach(GameObject target, string text)
		{
			if (!((Object)(object)target == (Object)null) && !string.IsNullOrEmpty(text))
			{
				RectTransform component = target.GetComponent<RectTransform>();
				if (!((Object)(object)component == (Object)null))
				{
					_bindings.Add(new Binding
					{
						Rt = component,
						Text = text
					});
				}
			}
		}

		public static void TickAll()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//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_0098: 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)
			if ((Object)(object)Sink == (Object)null)
			{
				return;
			}
			Vector2 val = Vector2.op_Implicit(Input.mousePosition);
			string text = null;
			for (int num = _bindings.Count - 1; num >= 0; num--)
			{
				Binding binding = _bindings[num];
				if ((Object)(object)binding.Rt == (Object)null)
				{
					_bindings.RemoveAt(num);
				}
				else if (((Component)binding.Rt).gameObject.activeInHierarchy)
				{
					Canvas componentInParent = ((Component)binding.Rt).GetComponentInParent<Canvas>();
					Camera val2 = null;
					if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0)
					{
						val2 = componentInParent.worldCamera;
					}
					if (RectTransformUtility.RectangleContainsScreenPoint(binding.Rt, val, val2))
					{
						text = binding.Text;
					}
				}
			}
			((TMP_Text)Sink).text = text ?? IdlePlaceholder;
			if (text == null || _firstHitLogged)
			{
				return;
			}
			_firstHitLogged = true;
			try
			{
				LogUtils.LogInfo($"TooltipHover: first hover registered ({_bindings.Count} bindings tracked).");
			}
			catch
			{
			}
		}
	}
}
namespace BloodCraftHub.UI.ModContent
{
	public class CombinedOverlayPanel : ResizeablePanelBase
	{
		private static readonly Color COL_XP = new Color(0.55f, 0.95f, 0.55f, 1f);

		private static readonly Color COL_FAMILIAR = new Color(1f, 0.78f, 0.3f, 1f);

		private static readonly Color COL_EXPERTISE = new Color(0.85f, 0.85f, 0.85f, 1f);

		private static readonly Color COL_LEGACY = new Color(1f, 0.45f, 0.45f, 1f);

		private static readonly Color COL_PROFS = new Color(0.95f, 0.75f, 0.35f, 1f);

		private static readonly Color COL_QUEST_D = new Color(0f, 1f, 1f, 1f);

		private static readonly Color COL_QUEST_W = new Color(1f, 0.85f, 0.3f, 1f);

		private GameObject _xpSection;

		private GameObject _familiarSection;

		private GameObject _expertiseSection;

		private GameObject _legacySection;

		private GameObject _profSection;

		private GameObject _questSection;

		private TextMeshProUGUI _xpLine;

		private TextMeshProUGUI _famNameLine;

		private TextMeshProUGUI _famStatsLine;

		private TextMeshProUGUI _wepLine;

		private TextMeshProUGUI _wepStatsLine;

		private TextMeshProUGUI _wepBonusValuesLine;

		private TextMeshProUGUI _wepCounterLine;

		private TextMeshProUGUI _blLine;

		private TextMeshProUGUI _blStatsLine;

		private TextMeshProUGUI _blBonusValuesLine;

		private TextMeshProUGUI _blCounterLine;

		private TextMeshProUGUI _profLine;

		private GameObject _profWrapMode;

		private GameObject _profRowMode;

		private TextMeshProUGUI _profRowEnchanting;

		private TextMeshProUGUI _profRowAlchemy;

		private TextMeshProUGUI _profRowHarvesting;

		private TextMeshProUGUI _profRowBlacksmithing;

		private TextMeshProUGUI _profRowTailoring;

		private TextMeshProUGUI _profRowWoodcutting;

		private TextMeshProUGUI _profRowMining;

		private TextMeshProUGUI _profRowFishing;

		private GameObject _profBarEnchanting;

		private GameObject _profBarAlchemy;

		private GameObject _profBarHarvesting;

		private GameObject _profBarBlacksmithing;

		private GameObject _profBarTailoring;

		private GameObject _profBarWoodcutting;

		private GameObject _profBarMining;

		private GameObject _profBarFishing;

		private RectTransform _profBarFillEnchanting;

		private RectTransform _profBarFillAlchemy;

		private RectTransform _profBarFillHarvesting;

		private RectTransform _profBarFillBlacksmithing;

		private RectTransform _profBarFillTailoring;

		private RectTransform _profBarFillWoodcutting;

		private RectTransform _profBarFillMining;

		private RectTransform _profBarFillFishing;

		private TextMeshProUGUI _dailyLine;

		private TextMeshProUGUI _weeklyLine;

		private GameObject _xpBar;

		private RectTransform _xpBarFill;

		private GameObject _famBar;

		private RectTransform _famBarFill;

		private GameObject _wepBar;

		private RectTransform _wepBarFill;

		private GameObject _blBar;

		private RectTransform _blBarFill;

		private bool _subscribed;

		public override string PanelId => "CombinedOverlay";

		public override PanelType PanelType => PanelType.CombinedOverlay;

		public override int MinWidth => 360;

		public override int MinHeight
		{
			get
			{
				int num = ResolveRowHeight(Theme.ScaledOverlay(11));
				if (Settings.ShowExperienceOverlay)
				{
					num += sectionHeight(1, Settings.ShowProgressBarXP);
				}
				if (Settings.ShowFamiliarOverlay)
				{
					num += sectionHeight(3, Settings.ShowProgressBarFamiliar);
				}
				int num2 = 3;
				if (Settings.ShowOverlayBonusStats)
				{
					num2 += 2;
				}
				if (Settings.ShowOverlayXpCounter)
				{
					num2++;
				}
				int num3 = 3;
				if (Settings.ShowOverlayBonusStats)
				{
					num3 += 2;
				}
				if (Settings.ShowOverlayXpCounter)
				{
					num3++;
				}
				if (Settings.CombinedOverlayShowExpertise)
				{
					num += sectionHeight(num2, Settings.ShowProgressBarExpertise);
				}
				if (Settings.CombinedOverlayShowLegacy)
				{
					num += sectionHeight(num3, Settings.ShowProgressBarLegacy);
				}
				if (Settings.ShowProfessionOverlay)
				{
					if (Settings.ShowProgressBarProfessions)
					{
						int num4 = 0;
						if (Settings.ShowProfessionEnchanting)
						{
							num4++;
						}
						if (Settings.ShowProfessionAlchemy)
						{
							num4++;
						}
						if (Settings.ShowProfessionHarvesting)
						{
							num4++;
						}
						if (Settings.ShowProfessionBlacksmithing)
						{
							num4++;
						}
						if (Settings.ShowProfessionTailoring)
						{
							num4++;
						}
						if (Settings.ShowProfessionWoodcutting)
						{
							num4++;
						}
						if (Settings.ShowProfessionMining)
						{
							num4++;
						}
						if (Settings.ShowProfessionFishing)
						{
							num4++;
						}
						num += ResolveRowHeight(Theme.ScaledOverlay(12)) + num4 * (ResolveRowHeight(Theme.ScaledOverlay(12)) + Settings.ProgressBarHeight + 2);
					}
					else
					{
						num += sectionHeight(3, barVisible: false);
					}
				}
				if (Settings.ShowDailyQuestOverlay)
				{
					num += sectionHeight(2, barVisible: false);
				}
				return num;
				static int sectionHeight(int bodyLines, bool barVisible)
				{
					return ResolveRowHeight(Theme.ScaledOverlay(12)) + bodyLines * ResolveRowHeight(Theme.ScaledOverlay(13)) + (barVisible ? (Settings.ProgressBarHeight + 2) : 0);
				}
			}
		}

		public override Vector2 DefaultAnchorMin => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultAnchorMax => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultPivot => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultPosition => new Vector2((0f - base.Owner.Scaler.m_ReferenceResolution.x) * 0.5f, base.Owner.Scaler.m_ReferenceResolution.y * 0.5f - 30f);

		public override bool CanDrag => true;

		public override PanelDragger.ResizeTypes CanResize => PanelDragger.ResizeTypes.All;

		public override float Opacity => Settings.TransparencyToAlpha(Settings.CombinedOverlayTransparency);

		public override bool UsesCustomBackgroundColor => true;

		public CombinedOverlayPanel(UIBase owner)
			: base(owner)
		{
		}

		protected override void LateConstructUI()
		{
			base.LateConstructUI();
			if ((Object)(object)base.Rect != (Object)null)
			{
				base.Rect.SetSizeWithCurrentAnchors((Axis)1, (float)MinHeight);
			}
		}

		protected override void ConstructPanelContent()
		{
			base.ConstructPanelContent();
			BuildXPSection();
			BuildFamiliarSection();
			BuildExpertiseSection();
			BuildLegacySection();
			BuildProfessionSection();
			BuildQuestSection();
			ApplySectionVisibility();
			RenderAll();
			if (!_subscribed)
			{
				PlayerStateService.ExperienceChanged += OnAnyChanged;
				PlayerStateService.FamiliarChanged += OnAnyChanged;
				PlayerStateService.ExpertiseChanged += OnAnyChanged;
				PlayerStateService.LegacyChanged += OnAnyChanged;
				PlayerStateService.ProfessionChanged += OnAnyChanged;
				PlayerStateService.QuestChanged += OnAnyChanged;
				PlayerStateService.LastResponseChanged += OnAnyChanged;
				PlayerStateService.BloodInfoChanged += OnAnyChanged;
				_subscribed = true;
			}
		}

		public void RefreshSections()
		{
			ApplySectionVisibility();
			RenderAll();
			if ((Object)(object)base.Rect != (Object)null)
			{
				base.Rect.SetSizeWithCurrentAnchors((Axis)1, (float)MinHeight);
				EnsureValidSize();
				EnsureValidPosition();
				if (base.Dragger != null)
				{
					base.Dragger.OnEndResize();
				}
			}
		}

		private static int ResolveRowHeight(int fontSize)
		{
			return Mathf.Max(20, Mathf.RoundToInt((float)fontSize * 1.45f));
		}

		private void ApplySectionVisibility()
		{
			if ((Object)(object)_xpSection != (Object)null)
			{
				_xpSection.SetActive(Settings.ShowExperienceOverlay);
			}
			if ((Object)(object)_familiarSection != (Object)null)
			{
				_familiarSection.SetActive(Settings.ShowFamiliarOverlay);
			}
			if ((Object)(object)_expertiseSection != (Object)null)
			{
				_expertiseSection.SetActive(Settings.CombinedOverlayShowExpertise);
			}
			if ((Object)(object)_legacySection != (Object)null)
			{
				_legacySection.SetActive(Settings.CombinedOverlayShowLegacy);
			}
			if ((Object)(object)_profSection != (Object)null)
			{
				_profSection.SetActive(Settings.ShowProfessionOverlay);
			}
			if ((Object)(object)_questSection != (Object)null)
			{
				_questSection.SetActive(Settings.ShowDailyQuestOverlay);
			}
		}

		private void OnAnyChanged()
		{
			RenderAll();
		}

		private void RenderAll()
		{
			RenderXP();
			RenderFamiliar();
			RenderExpertise();
			RenderLegacy();
			RenderProfessions();
			RenderQuests();
		}

		private GameObject BuildSectionRoot(string name)
		{
			//IL_0020: 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)
			GameObject obj = UIFactory.CreateVerticalGroup(base.ContentRoot, name, forceWidth: true, forceHeight: false, childControlWidth: true, childControlHeight: true, 1, new Vector4(2f, 2f, 2f, 2f), (Color?)new Color(0f, 0f, 0f, 0f), (TextAnchor?)null, 1f);
			UIFactory.SetLayoutElement(obj, 260, preferredWidth: 280, flexibleWidth: 1, minHeight: Theme.ScaledOverlayHeight(24), flexibleHeight: 0);
			return obj;
		}

		private TextMeshProUGUI AddSectionHeader(GameObject section, string title, Color color)
		{
			//IL_0012: 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)
			LabelRef labelRef = UIFactory.CreateLabel(section, ((Object)section).name + "_Hdr", title, Theme.OverlayMidlineAlignment(), null, Theme.ScaledOverlay(12));
			GameObject gameObject = labelRef.GameObject;
			int? minWidth = 240;
			int? preferredWidth = 260;
			int? num = 1;
			UIFactory.SetLayoutElement(minHeight: Theme.ScaledOverlayHeight(18), flexibleWidth: num, preferredHeight: Theme.ScaledOverlayHeight(20), gameObject: gameObject, minWidth: minWidth, flexibleHeight: 0, preferredWidth: preferredWidth);
			((TMP_Text)labelRef.TextMesh).fontStyle = (FontStyles)1;
			((Graphic)labelRef.TextMesh).color = color;
			((TMP_Text)labelRef.TextMesh).enableWordWrapping = false;
			((TMP_Text)labelRef.TextMesh).overflowMode = (TextOverflowModes)0;
			return labelRef.TextMesh;
		}

		private TextMeshProUGUI AddSectionBody(GameObject section, string name, string initialText, int fontSize = 13, bool wrap = false)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			LabelRef labelRef = UIFactory.CreateLabel(section, name, initialText, Theme.OverlayMidlineAlignment(), null, Theme.ScaledOverlay(fontSize));
			GameObject gameObject = labelRef.GameObject;
			int? minWidth = 240;
			int? preferredWidth = 260;
			int? num = 1;
			UIFactory.SetLayoutElement(minHeight: Theme.ScaledOverlayHeight(18), flexibleWidth: num, preferredHeight: Theme.ScaledOverlayHeight(20), gameObject: gameObject, minWidth: minWidth, flexibleHeight: 0, preferredWidth: preferredWidth);
			((TMP_Text)labelRef.TextMesh).enableWordWrapping = wrap;
			((TMP_Text)labelRef.TextMesh).overflowMode = (TextOverflowModes)0;
			if (wrap)
			{
				ContentSizeFitter obj = labelRef.GameObject.AddComponent<ContentSizeFitter>();
				obj.horizontalFit = (FitMode)0;
				obj.verticalFit = (FitMode)2;
			}
			return labelRef.TextMesh;
		}

		private GameObject AddMiniBar(GameObject section, string name, Color fillColor, out RectTransform fill)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = MiniBar.Create(section, name, out fill, fillColor, Settings.ProgressBarHeight);
			obj.SetActive(false);
			return obj;
		}

		private void BuildXPSection()
		{
			//IL_001d: 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)
			_xpSection = BuildSectionRoot("XPSection");
			AddSectionHeader(_xpSection, "EXPERIENCE", COL_XP);
			_xpLine = AddSectionBody(_xpSection, "XPLine", "Lv —");
			_xpBar = AddMiniBar(_xpSection, "XPBar", new Color(0.55f, 0.95f, 0.55f, 0.95f), out _xpBarFill);
		}

		private void BuildFamiliarSection()
		{
			//IL_001d: 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)
			_familiarSection = BuildSectionRoot("FamiliarSection");
			AddSectionHeader(_familiarSection, "FAMILIAR", COL_FAMILIAR);
			_famNameLine = AddSectionBody(_familiarSection, "FamName", "(no familiar bound)");
			_famBar = AddMiniBar(_familiarSection, "FamBar", new Color(1f, 0.6f, 0.2f, 0.95f), out _famBarFill);
			_famStatsLine = AddSectionBody(_familiarSection, "FamStats", "—", 12, wrap: true);
		}

		private void BuildExpertiseSection()
		{
			//IL_001d: 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)
			_expertiseSection = BuildSectionRoot("ExpertiseSection");
			AddSectionHeader(_expertiseSection, "WEAPON EXPERTISE", COL_EXPERTISE);
			_wepLine = AddSectionBody(_expertiseSection, "WepLine", "—");
			_wepBar = AddMiniBar(_expertiseSection, "WepBar", new Color(0.75f, 0.75f, 0.85f, 0.95f), out _wepBarFill);
			_wepStatsLine = AddSectionBody(_expertiseSection, "WepStats", "—", 12, wrap: true);
			_wepBonusValuesLine = AddSectionBody(_expertiseSection, "WepBonusValues", "", 11, wrap: true);
			((TMP_Text)_wepBonusValuesLine).fontStyle = (FontStyles)2;
			((Component)_wepBonusValuesLine).gameObject.SetActive(false);
			_wepCounterLine = AddSectionBody(_expertiseSection, "WepCounter", "", 11);
			((TMP_Text)_wepCounterLine).fontStyle = (FontStyles)2;
			((Component)_wepCounterLine).gameObject.SetActive(false);
		}

		private void BuildLegacySection()
		{
			//IL_001d: 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)
			_legacySection = BuildSectionRoot("LegacySection");
			AddSectionHeader(_legacySection, "BLOOD LEGACY", COL_LEGACY);
			_blLine = AddSectionBody(_legacySection, "BlLine", "—");
			_blBar = AddMiniBar(_legacySection, "BlBar", new Color(0.85f, 0.3f, 0.3f, 0.95f), out _blBarFill);
			_blStatsLine = AddSectionBody(_legacySection, "BlStats", "—", 12, wrap: true);
			_blBonusValuesLine = AddSectionBody(_legacySection, "BlBonusValues", "", 11, wrap: true);
			((TMP_Text)_blBonusValuesLine).fontStyle = (FontStyles)2;
			((Component)_blBonusValuesLine).gameObject.SetActive(false);
			_blCounterLine = AddSectionBody(_legacySection, "BlCounter", "", 11);
			((TMP_Text)_blCounterLine).fontStyle = (FontStyles)2;
			((Component)_blCounterLine).gameObject.SetActive(false);
		}

		private void BuildProfessionSection()
		{
			//IL_001d: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: 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_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			_profSection = BuildSectionRoot("ProfSection");
			AddSectionHeader(_profSection, "PROFESSIONS", COL_PROFS);
			_profWrapMode = UIFactory.CreateVerticalGroup(_profSection, "ProfWrapMode", forceWidth: true, forceHeight: false, childControlWidth: true, childControlHeight: true, 0, new Vector4(0f, 0f, 0f, 0f), (Color?)new Color(0f, 0f, 0f, 0f), (TextAnchor?)null, 1f);
			UIFactory.SetLayoutElement(_profWrapMode, 240, preferredWidth: 320, flexibleWidth: 1, minHeight: Theme.ScaledOverlayHeight(18), flexibleHeight: 0);
			LabelRef labelRef = UIFactory.CreateLabel(_profWrapMode, "ProfLine", "—", Theme.OverlayMidlineAlignment(), null, Theme.ScaledOverlay(12));
			UIFactory.SetLayoutElement(labelRef.GameObject, 240, preferredWidth: 320, flexibleWidth: 1, minHeight: Theme.ScaledOverlayHeight(18), flexibleHeight: 0);
			((TMP_Text)labelRef.TextMesh).enableWordWrapping = true;
			((TMP_Text)labelRef.TextMesh).overflowMode = (TextOverflowModes)0;
			ContentSizeFitter obj = labelRef.GameObject.AddComponent<ContentSizeFitter>();
			obj.horizontalFit = (FitMode)0;
			obj.verticalFit = (FitMode)2;
			_profLine = labelRef.TextMesh;
			_profRowMode = UIFactory.CreateVerticalGroup(_profSection, "ProfRowMode", forceWidth: true, forceHeight: false, childControlWidth: true, childControlHeight: true, 1, new Vector4(0f, 0f, 0f, 0f), (Color?)new Color(0f, 0f, 0f, 0f), (TextAnchor?)null, 1f);
			UIFactory.SetLayoutElement(_profRowMode, 240, preferredWidth: 320, flexibleWidth: 1, minHeight: Theme.ScaledOverlayHeight(18), flexibleHeight: 0);
			Color fillColor = default(Color);
			((Color)(ref fillColor))..ctor(0.95f, 0.75f, 0.35f, 0.95f);
			_profRowEnchanting = AddProfRow(_profRowMode, "ProfRow_Enchanting", "Enchanting —");
			_profBarEnchanting = AddMiniBar(_profRowMode, "ProfBar_Enchanting", fillColor, out _profBarFillEnchanting);
			_profRowAlchemy = AddProfRow(_profRowMode, "ProfRow_Alchemy", "Alchemy —");
			_profBarAlchemy = AddMiniBar(_profRowMode, "ProfBar_Alchemy", fillColor, out _profBarFillAlchemy);
			_profRowHarvesting = AddProfRow(_profRowMode, "ProfRow_Harvesting", "Harvesting —");
			_profBarHarvesting = AddMiniBar(_profRowMode, "ProfBar_Harvesting", fillColor, out _profBarFillHarvesting);
			_profRowBlacksmithing = AddProfRow(_profRowMode, "ProfRow_Blacksmithing", "Blacksmithing —");
			_profBarBlacksmithing = AddMiniBar(_profRowMode, "ProfBar_Blacksmithing", fillColor, out _profBarFillBlacksmithing);
			_profRowTailoring = AddProfRow(_profRowMode, "ProfRow_Tailoring", "Tailoring —");
			_profBarTailoring = AddMiniBar(_profRowMode, "ProfBar_Tailoring", fillColor, out _profBarFillTailoring);
			_profRowWoodcutting = AddProfRow(_profRowMode, "ProfRow_Woodcutting", "Woodcutting —");
			_profBarWoodcutting = AddMiniBar(_profRowMode, "ProfBar_Woodcutting", fillColor, out _profBarFillWoodcutting);
			_profRowMining = AddProfRow(_profRowMode, "ProfRow_Mining", "Mining —");
			_profBarMining = AddMiniBar(_profRowMode, "ProfBar_Mining", fillColor, out _profBarFillMining);
			_profRowFishing = AddProfRow(_profRowMode, "ProfRow_Fishing", "Fishing —");
			_profBarFishing = AddMiniBar(_profRowMode, "ProfBar_Fishing", fillColor, out _profBarFillFishing);
		}

		private TextMeshProUGUI AddProfRow(GameObject parent, string name, string initial)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			LabelRef labelRef = UIFactory.CreateLabel(parent, name, initial, Theme.OverlayMidlineAlignment(), null, Theme.ScaledOverlay(12));
			GameObject gameObject = labelRef.GameObject;
			int? minWidth = 240;
			int? preferredWidth = 260;
			int? num = 1;
			UIFactory.SetLayoutElement(minHeight: Theme.ScaledOverlayHeight(18), flexibleWidth: num, preferredHeight: Theme.ScaledOverlayHeight(20), gameObject: gameObject, minWidth: minWidth, flexibleHeight: 0, preferredWidth: preferredWidth);
			((TMP_Text)labelRef.TextMesh).enableWordWrapping = false;
			((TMP_Text)labelRef.TextMesh).overflowMode = (TextOverflowModes)0;
			return labelRef.TextMesh;
		}

		private void BuildQuestSection()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			_questSection = BuildSectionRoot("QuestSection");
			AddSectionHeader(_questSection, "DAILY / WEEKLY QUEST", COL_QUEST_D);
			_dailyLine = AddSectionBody(_questSection, "DailyLine", "Daily: —");
			_weeklyLine = AddSectionBody(_questSection, "WeeklyLine", "Weekly: —");
			((Graphic)_weeklyLine).color = COL_QUEST_W;
		}

		private static void SyncBar(GameObject bar, RectTransform fill, float progress, bool show)
		{
			if (!((Object)(object)bar == (Object)null))
			{
				if (bar.activeSelf != show)
				{
					bar.SetActive(show);
				}
				if (show && (Object)(object)fill != (Object)null)
				{
					MiniBar.SetProgress(fill, progress);
				}
			}
		}

		private void RenderXP()
		{
			if (!((Object)(object)_xpLine == (Object)null))
			{
				PlayerStateService.ExperienceState experience = PlayerStateService.Experience;
				string value = ((experience.Class == PlayerStateService.PlayerClass.None) ? "(no class)" : experience.Class.ToString());
				string value2 = ((experience.Prestige > 0) ? $"  P{experience.Prestige}" : "");
				((TMP_Text)_xpLine).text = $"Lv {experience.Level} ({experience.Progress * 100f:0.#}%){value2}   {value}";
				SyncBar(_xpBar, _xpBarFill, experience.Progress, Settings.ShowProgressBarXP);
			}
		}

		private void RenderFamiliar()
		{
			if (!((Object)(object)_famNameLine == (Object)null))
			{
				PlayerStateService.FamiliarState familiar = PlayerStateService.Familiar;
				if (!familiar.HasActive)
				{
					((TMP_Text)_famNameLine).text = "(no familiar bound)";
					((TMP_Text)_famStatsLine).text = "—";
					SyncBar(_famBar, _famBarFill, 0f, show: false);
					return;
				}
				string value = ((familiar.Prestige > 0) ? $"  P{familiar.Prestige}" : "");
				((TMP_Text)_famNameLine).text = $"{familiar.Name}  Lv {familiar.Level} ({familiar.Progress * 100f:0.#}%){value}";
				((TMP_Text)_famStatsLine).text = $"HP {familiar.MaxHealth}   PP {familiar.PhysicalPower}   SP {familiar.SpellPower}";
				SyncBar(_famBar, _famBarFill, familiar.Progress, Settings.ShowProgressBarFamiliar);
			}
		}

		private void RenderExpertise()
		{
			if (!((Object)(object)_wepLine == (Object)null))
			{
				PlayerStateService.ExpertiseState expertise = PlayerStateService.Expertise;
				string value = ((expertise.Prestige > 0) ? $"  P{expertise.Prestige}" : "");
				((TMP_Text)_wepLine).text = $"{expertise.Type}   Lv {expertise.Level} ({expertise.Progress * 100f:0.#}%){value}";
				List<PlayerStateService.WeaponStatType> list = PlayerStateService.DecodeWeaponBonusStats(expertise.BonusStatsRaw);
				((TMP_Text)_wepStatsLine).text = ((list == null || list.Count == 0) ? "Stats: (none chosen)" : ("Stats: " + string.Join(", ", list)));
				SyncBar(_wepBar, _wepBarFill, expertise.Progress, Settings.ShowProgressBarExpertise);
				RenderWepBonusValuesSubRow();
				RenderWepCounterSubRow();
			}
		}

		private void RenderLegacy()
		{
			if (!((Object)(object)_blLine == (Object)null))
			{
				PlayerStateService.LegacyState legacy = PlayerStateService.Legacy;
				string value = ((legacy.Prestige > 0) ? $"  P{legacy.Prestige}" : "");
				((TMP_Text)_blLine).text = $"{legacy.Type}   Lv {legacy.Level} ({legacy.Progress * 100f:0.#}%){value}";
				List<PlayerStateService.BloodStatType> list = PlayerStateService.DecodeBloodBonusStats(legacy.BonusStatsRaw);
				((TMP_Text)_blStatsLine).text = ((list == null || list.Count == 0) ? "Stats: (none chosen)" : ("Stats: " + string.Join(", ", list)));
				SyncBar(_blBar, _blBarFill, legacy.Progress, Settings.ShowProgressBarLegacy);
				RenderBlBonusValuesSubRow();
				RenderBlCounterSubRow();
			}
		}

		private void RenderWepBonusValuesSubRow()
		{
			if (!((Object)(object)_wepBonusValuesLine == (Object)null))
			{
				bool showOverlayBonusStats = Settings.ShowOverlayBonusStats;
				ExperienceOverlayPanel experienceOverlayPanel = Plugin.UIManager?.ExperienceOverlay;
				List<string> list = ((!showOverlayBonusStats) ? null : experienceOverlayPanel?.BuildCleanedWepGetStatsLines());
				bool flag = list != null && list.Count > 0;
				if (((Component)_wepBonusValuesLine).gameObject.activeSelf != (showOverlayBonusStats && flag))
				{
					((Component)_wepBonusValuesLine).gameObject.SetActive(showOverlayBonusStats && flag);
				}
				if (showOverlayBonusStats && flag)
				{
					((TMP_Text)_wepBonusValuesLine).text = string.Join("\n", list);
				}
			}
		}

		private void RenderWepCounterSubRow()
		{
			if (!((Object)(object)_wepCounterLine == (Object)null))
			{
				bool showOverlayXpCounter = Settings.ShowOverlayXpCounter;
				ExperienceOverlayPanel experienceOverlayPanel = Plugin.UIManager?.ExperienceOverlay;
				bool flag = showOverlayXpCounter && (experienceOverlayPanel?.WepGetHasData ?? false);
				if (((Component)_wepCounterLine).gameObject.activeSelf != flag)
				{
					((Component)_wepCounterLine).gameObject.SetActive(flag);
				}
				if (flag)
				{
					int wepGetRawExpertise = experienceOverlayPanel.WepGetRawExpertise;
					float wepGetProgressPct = experienceOverlayPanel.WepGetProgressPct;
					int num = ((wepGetProgressPct > 0.01f) ? Mathf.RoundToInt((float)wepGetRawExpertise * 100f / wepGetProgressPct) : 0);
					((TMP_Text)_wepCounterLine).text = ((num > 0) ? $"Exp: {wepGetRawExpertise} / {num} ({wepGetProgressPct:0.0}%)" : $"Exp: {wepGetRawExpertise} ({wepGetProgressPct:0.0}%)");
				}
			}
		}

		private void RenderBlBonusValuesSubRow()
		{
			if (!((Object)(object)_blBonusValuesLine == (Object)null))
			{
				bool showOverlayBonusStats = Settings.ShowOverlayBonusStats;
				PlayerStateService.BloodInfo bloodInfoLatest = PlayerStateService.BloodInfoLatest;
				bool flag = bloodInfoLatest.StatLines != null && bloodInfoLatest.StatLines.Count > 0;
				if (((Component)_blBonusValuesLine).gameObject.activeSelf != (showOverlayBonusStats && flag))
				{
					((Component)_blBonusValuesLine).gameObject.SetActive(showOverlayBonusStats && flag);
				}
				if (showOverlayBonusStats && flag)
				{
					((TMP_Text)_blBonusValuesLine).text = string.Join("\n", bloodInfoLatest.StatLines);
				}
			}
		}

		private void RenderBlCounterSubRow()
		{
			if ((Object)(object)_blCounterLine == (Object)null)
			{
				return;
			}
			bool showOverlayXpCounter = Settings.ShowOverlayXpCounter;
			PlayerStateService.BloodInfo bloodInfoLatest = PlayerStateService.BloodInfoLatest;
			bool flag = showOverlayXpCounter && !string.IsNullOrEmpty(bloodInfoLatest.Essence) && !string.IsNullOrEmpty(bloodInfoLatest.ProgressPct);
			if (((Component)_blCounterLine).gameObject.activeSelf != flag)
			{
				((Component)_blCounterLine).gameObject.SetActive(flag);
			}
			if (flag)
			{
				if (float.TryParse(bloodInfoLatest.ProgressPct, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && int.TryParse(bloodInfoLatest.Essence, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
				{
					int num = ((result > 0.01f) ? Mathf.RoundToInt((float)result2 * 100f / result) : 0);
					((TMP_Text)_blCounterLine).text = ((num > 0) ? $"Ess: {result2} / {num} ({result:0.0}%)" : $"Ess: {result2} ({result:0.0}%)");
				}
				else
				{
					((TMP_Text)_blCounterLine).text = $"Ess: {bloodInfoLatest.Essence} ({bloodInfoLatest.ProgressPct}%)";
				}
			}
		}

		private void RenderProfessions()
		{
			if ((Object)(object)_profLine == (Object)null)
			{
				return;
			}
			PlayerStateService.ProfessionState profession = PlayerStateService.Profession;
			bool showProgressBarProfessions = Settings.ShowProgressBarProfessions;
			if ((Object)(object)_profWrapMode != (Object)null && _profWrapMode.activeSelf != !showProgressBarProfessions)
			{
				_profWrapMode.SetActive(!showProgressBarProfessions);
			}
			if ((Object)(object)_profRowMode != (Object)null && _profRowMode.activeSelf != showProgressBarProfessions)
			{
				_profRowMode.SetActive(showProgressBarProfessions);
			}
			if (!showProgressBarProfessions)
			{
				List<string> list = new List<string>(8);
				if (Settings.ShowProfessionEnchanting)
				{
					list.Add($"Enchanting {profession.EnchantingLevel}");
				}
				if (Settings.ShowProfessionAlchemy)
				{
					list.Add($"Alchemy {profession.AlchemyLevel}");
				}
				if (Settings.ShowProfessionHarvesting)
				{
					list.Add($"Harvesting {profession.HarvestingLevel}");
				}
				if (Settings.ShowProfessionBlacksmithing)
				{
					list.Add($"Blacksmithing {profession.BlacksmithingLevel}");
				}
				if (Settings.ShowProfessionTailoring)
				{
					list.Add($"Tailoring {profession.TailoringLevel}");
				}
				if (Settings.ShowProfessionWoodcutting)
				{
					list.Add($"Woodcutting {profession.WoodcuttingLevel}");
				}
				if (Settings.ShowProfessionMining)
				{
					list.Add($"Mining {profession.MiningLevel}");
				}
				if (Settings.ShowProfessionFishing)
				{
					list.Add($"Fishing {profession.FishingLevel}");
				}
				((TMP_Text)_profLine).text = ((list.Count == 0) ? "(all professions hidden in Settings)" : string.Join("    ", list));
			}
			else
			{
				RenderProfRow(_profRowEnchanting, _profBarEnchanting, _profBarFillEnchanting, Settings.ShowProfessionEnchanting, "Enchanting", profession.EnchantingLevel, profession.EnchantingProgress);
				RenderProfRow(_profRowAlchemy, _profBarAlchemy, _profBarFillAlchemy, Settings.ShowProfessionAlchemy, "Alchemy", profession.AlchemyLevel, profession.AlchemyProgress);
				RenderProfRow(_profRowHarvesting, _profBarHarvesting, _profBarFillHarvesting, Settings.ShowProfessionHarvesting, "Harvesting", profession.HarvestingLevel, profession.HarvestingProgress);
				RenderProfRow(_profRowBlacksmithing, _profBarBlacksmithing, _profBarFillBlacksmithing, Settings.ShowProfessionBlacksmithing, "Blacksmithing", profession.BlacksmithingLevel, profession.BlacksmithingProgress);
				RenderProfRow(_profRowTailoring, _profBarTailoring, _profBarFillTailoring, Settings.ShowProfessionTailoring, "Tailoring", profession.TailoringLevel, profession.TailoringProgress);
				RenderProfRow(_profRowWoodcutting, _profBarWoodcutting, _profBarFillWoodcutting, Settings.ShowProfessionWoodcutting, "Woodcutting", profession.WoodcuttingLevel, profession.WoodcuttingProgress);
				RenderProfRow(_profRowMining, _profBarMining, _profBarFillMining, Settings.ShowProfessionMining, "Mining", profession.MiningLevel, profession.MiningProgress);
				RenderProfRow(_profRowFishing, _profBarFishing, _profBarFillFishing, Settings.ShowProfessionFishing, "Fishing", profession.FishingLevel, profession.FishingProgress);
			}
		}

		private static void RenderProfRow(TextMeshProUGUI label, GameObject bar, RectTransform fill, bool show, string name, int level, float progress)
		{
			if ((Object)(object)label != (Object)null)
			{
				if (((Component)label).gameObject.activeSelf != show)
				{
					((Component)label).gameObject.SetActive(show);
				}
				if (show)
				{
					((TMP_Text)label).text = $"{name}: Lv {level} ({progress * 100f:0.#}%)";
				}
			}
			SyncBar(bar, fill, progress, show);
		}

		private void RenderQuests()
		{
			if (!((Object)(object)_dailyLine == (Object)null))
			{
				PlayerStateService.QuestState dailyQuest = PlayerStateService.DailyQuest;
				PlayerStateService.QuestState weeklyQuest = PlayerStateService.WeeklyQuest;
				((TMP_Text)_dailyLine).text = FormatQuest("Daily", dailyQuest);
				((TMP_Text)_weeklyLine).text = FormatQuest("Weekly", weeklyQuest);
			}
		}

		private static string FormatQuest(string label, PlayerStateService.QuestState q)
		{
			if (string.IsNullOrEmpty(q.TargetName))
			{
				return label + ": —";
			}
			if (q.Goal <= 0 || q.Progress < q.Goal)
			{
				return $"{label}: {q.TargetName} ({q.Progress}/{q.Goal})";
			}
			return label + ": " + q.TargetName + " — Complete!";
		}

		internal override void Reset()
		{
			if (_subscribed)
			{
				PlayerStateService.ExperienceChanged -= OnAnyChanged;
				PlayerStateService.FamiliarChanged -= OnAnyChanged;
				PlayerStateService.ExpertiseChanged -= OnAnyChanged;
				PlayerStateService.LegacyChanged -= OnAnyChanged;
				PlayerStateService.ProfessionChanged -= OnAnyChanged;
				PlayerStateService.QuestChanged -= OnAnyChanged;
				PlayerStateService.LastResponseChanged -= OnAnyChanged;
				PlayerStateService.BloodInfoChanged -= OnAnyChanged;
				_subscribed = false;
			}
		}
	}
	public class DailyQuestOverlayPanel : ResizeablePanelBase
	{
		private LabelRef _dailyTitleLabel;

		private LabelRef _dailyTargetLabel;

		private LabelRef _dailyProgressLabel;

		private LabelRef _weeklyTitleLabel;

		private LabelRef _weeklyTargetLabel;

		private LabelRef _weeklyProgressLabel;

		private bool _subscribed;

		public override string PanelId => "DailyQuestOverlay";

		public override PanelType PanelType => PanelType.DailyQuestOverlay;

		public override int MinWidth => 260;

		public override int MinHeight => 130;

		public override Vector2 DefaultAnchorMin => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultAnchorMax => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultPivot => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultPosition => new Vector2((0f - base.Owner.Scaler.m_ReferenceResolution.x) * 0.5f + 280f, base.Owner.Scaler.m_ReferenceResolution.y * 0.5f - 40f);

		public override bool CanDrag => true;

		public override PanelDragger.ResizeTypes CanResize => PanelDragger.ResizeTypes.All;

		public override float Opacity => Settings.TransparencyToAlpha(Settings.DailyQuestTransparency);

		public override bool UsesCustomBackgroundColor => true;

		public DailyQuestOverlayPanel(UIBase owner)
			: base(owner)
		{
		}

		protected override void ConstructPanelContent()
		{
			//IL_003e: 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)
			base.ConstructPanelContent();
			_dailyTitleLabel = AddRow("DailyTitle", "Daily Quest", (FontStyles)1, Theme.ScaledOverlay(14));
			((Graphic)_dailyTitleLabel.TextMesh).color = new Color(0f, 1f, 1f);
			ApplyStrongOutline(_dailyTitleLabel.TextMesh);
			_dailyTargetLabel = AddRow("DailyTarget", "—", (FontStyles)0, Theme.ScaledOverlay(13));
			_dailyProgressLabel = AddRow("DailyProgress", "—", (FontStyles)2, Theme.ScaledOverlay(13));
			AddSpacer(6);
			_weeklyTitleLabel = AddRow("WeeklyTitle", "Weekly Quest", (FontStyles)1, Theme.ScaledOverlay(14));
			((Graphic)_weeklyTitleLabel.TextMesh).color = new Color(1f, 0.85f, 0.3f);
			ApplyStrongOutline(_weeklyTitleLabel.TextMesh);
			_weeklyTargetLabel = AddRow("WeeklyTarget", "—", (FontStyles)0, Theme.ScaledOverlay(13));
			_weeklyProgressLabel = AddRow("WeeklyProgress", "—", (FontStyles)2, Theme.ScaledOverlay(13));
			Render();
			if (!_subscribed)
			{
				PlayerStateService.QuestChanged += OnQuestChanged;
				_subscribed = true;
			}
		}

		private LabelRef AddRow(string name, string text, FontStyles style, int fontSize)
		{
			//IL_0008: 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)
			LabelRef labelRef = UIFactory.CreateLabel(base.ContentRoot, name, text, Theme.OverlayMidlineAlignment(), null, fontSize);
			GameObject gameObject = labelRef.GameObject;
			int? minWidth = 240;
			int? preferredWidth = 260;
			int? num = 1;
			UIFactory.SetLayoutElement(minHeight: 20, flexibleWidth: num, preferredHeight: 22, gameObject: gameObject, minWidth: minWidth, flexibleHeight: 0, preferredWidth: preferredWidth);
			((TMP_Text)labelRef.TextMesh).enableWordWrapping = false;
			((TMP_Text)labelRef.TextMesh).overflowMode = (TextOverflowModes)0;
			((TMP_Text)labelRef.TextMesh).fontStyle = style;
			return labelRef;
		}

		private void AddSpacer(int height)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = UIFactory.CreateUIObject("Spacer", base.ContentRoot);
			int? minHeight = height;
			int? preferredHeight = height;
			int? flexibleHeight = 0;
			int? flexibleWidth = 1;
			UIFactory.SetLayoutElement(gameObject, null, minHeight, flexibleWidth, flexibleHeight, null, preferredHeight);
		}

		private void OnQuestChanged()
		{
			Render();
		}

		private void Render()
		{
			if (_dailyTitleLabel != null)
			{
				FillRow(_dailyTargetLabel, _dailyProgressLabel, PlayerStateService.DailyQuest, ".quest r d");
				FillRow(_weeklyTargetLabel, _weeklyProgressLabel, PlayerStateService.WeeklyQuest, ".quest r w");
			}
		}

		private static void FillRow(LabelRef target, LabelRef progress, PlayerStateService.QuestState s, string rerollHint)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: 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)
			if (string.IsNullOrEmpty(s.TargetName) && s.Goal <= 0)
			{
				((TMP_Text)target.TextMesh).text = "(none yet)";
				((TMP_Text)progress.TextMesh).text = "Check back after refresh.";
				((Graphic)progress.TextMesh).color = Color.white;
				return;
			}
			((TMP_Text)target.TextMesh).text = (s.IsVBlood ? ("⚔  " + s.TargetName + "  (V Blood)") : ("⚔  " + s.TargetName));
			if (s.Goal > 0 && s.Progress >= s.Goal)
			{
				((TMP_Text)progress.TextMesh).text = "Complete!  (" + rerollHint + " to reroll)";
				((Graphic)progress.TextMesh).color = new Color(0.6f, 1f, 0.6f);
				return;
			}
			((TMP_Text)progress.TextMesh).text = $"Progress: {s.Progress} / {s.Goal}";
			((Graphic)progress.TextMesh).color = Color.white;
		}

		private static void ApplyStrongOutline(TextMeshProUGUI t)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)t == (Object)null)
			{
				return;
			}
			try
			{
				((TMP_Text)t).outlineColor = Color32.op_Implicit(Color.black);
				((TMP_Text)t).outlineWidth = 0.25f;
			}
			catch
			{
			}
		}

		internal override void Reset()
		{
			if (_subscribed)
			{
				PlayerStateService.QuestChanged -= OnQuestChanged;
				_subscribed = false;
			}
		}
	}
	public class ExperienceOverlayPanel : ResizeablePanelBase
	{
		private LabelRef _levelLabel;

		private LabelRef _progressLabel;

		private GameObject _xpBar;

		private RectTransform _xpBarFill;

		private RectTransform _xpBarSubFill;

		private LabelRef _classLabel;

		private LabelRef _weaponLabel;

		private LabelRef _weaponCounterLabel;

		private GameObject _weaponBar;

		private RectTransform _weaponBarFill;

		private RectTransform _weaponBarSubFill;

		private LabelRef _weaponStatsLabel;

		private LabelRef _legacyLabel;

		private LabelRef _legacyCounterLabel;

		private GameObject _legacyBar;

		private RectTransform _legacyBarFill;

		private RectTransform _legacyBarSubFill;

		private LabelRef _legacyStatsLabel;

		private LabelRef _exoLabel;

		private int _wepGetRawExpertise;

		private float _wepGetProgressPct;

		private bool _wepGetHasData;

		private bool _subscribed;

		private bool _expertiseSubscribed;

		private bool _legacySubscribed;

		private bool _prestigeSubscribed;

		private bool _lastResponseSubscribed;

		private bool _bloodInfoSubscribed;

		private bool _exoFetchScheduled;

		private int _exoLevel;

		private int _exoMaxLevel;

		private List<string> _cachedWepGetLines;

		private Action _bonusStatsTicker;

		private double _lastBonusStatsFetchAt;

		private const double OVERLAY_BONUS_REFRESH_SECONDS = 10.0;

		private bool _bonusStatsFetchToggle;

		private PlayerStateService.WeaponType _lastSeenWeaponType;

		private PlayerStateService.BloodType _lastSeenBloodType;

		private bool _seenWeaponTypeBaseline;

		private bool _seenBloodTypeBaseline;

		private static readonly Regex _wepGetPreambleRegex = new Regex("Your weapon expertise is \\[<color=white>\\d+</color>\\]\\[<color=#90EE90>\\d+</color>\\] and you have <color=yellow>(?<xp>[^<]+)</color> <color=#FFC0CB>expertise</color> \\(<color=white>(?<pct>[^<%]+)%?</color>\\) with", RegexOptions.Compiled);

		private static readonly Regex _tmpTagStripRegex = new Regex("</?color(=[^>]*)?>", RegexOptions.Compiled);

		public override string PanelId => "ExperienceOverlay";

		public override PanelType PanelType => PanelType.ExperienceOverlay;

		public override int MinWidth => 240;

		public override int MinHeight
		{
			get
			{
				int num = ResolveRowHeight(Theme.ScaledOverlay(16));
				int num2 = ResolveRowHeight(Theme.ScaledOverlay(13));
				int num3 = ResolveRowHeight(Theme.ScaledOverlay(11));
				int num4 = ResolveRowHeight(Theme.ScaledOverlay(11)) * 2;
				int num5 = num + 5 * num2 + 12;
				int num6 = 0;
				if (Settings.ShowProgressBarXP)
				{
					num6++;
				}
				if (Settings.ShowProgressBarExpertise)
				{
					num6++;
				}
				if (Settings.ShowProgressBarLegacy)
				{
					num6++;
				}
				if (num6 > 0)
				{
					num5 += num6 * (Settings.ProgressBarHeight + 2);
				}
				if (Settings.ShowOverlayBonusStats)
				{
					num5 += 2 * num4;
				}
				if (Settings.ShowOverlayXpCounter)
				{
					num5 += 2 * num3;
				}
				return num5;
			}
		}

		public override Vector2 DefaultAnchorMin => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultAnchorMax => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultPivot => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultPosition => new Vector2((0f - base.Owner.Scaler.m_ReferenceResolution.x) * 0.5f, base.Owner.Scaler.m_ReferenceResolution.y * 0.5f);

		public override bool CanDrag => true;

		public override PanelDragger.ResizeTypes CanResize => PanelDragger.ResizeTypes.All;

		public override float Opacity => Settings.TransparencyToAlpha(Settings.XPOverlayTransparency);

		public override bool UsesCustomBackgroundColor => true;

		public bool WepGetHasData => _wepGetHasData;

		public int WepGetRawExpertise => _wepGetRawExpertise;

		public float WepGetProgressPct => _wepGetProgressPct;

		public IReadOnlyList<string> CachedWepGetLines => _cachedWepGetLines;

		public List<string> BuildCleanedWepGetStatsLines()
		{
			if (_cachedWepGetLines == null || _cachedWepGetLines.Count == 0)
			{
				return null;
			}
			List<string> list = new List<string>(_cachedWepGetLines.Count);
			foreach (string cachedWepGetLine in _cachedWepGetLines)
			{
				string text = _tmpTagStripRegex.Replace(cachedWepGetLine, string.Empty).Trim();
				if (!string.IsNullOrEmpty(text) && !IsWepGetPreambleOrPlaceholder(text))
				{
					list.Add(text);
				}
			}
			if (list.Count <= 0)
			{
				return null;
			}
			return list;
		}

		public ExperienceOverlayPanel(UIBase owner)
			: base(owner)
		{
		}

		protected override void ConstructPanelContent()
		{
			//IL_006e: 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_01f9: Unknown result type (might be due to invalid IL or missing references)
			base.ConstructPanelContent();
			_levelLabel = AddRow("LevelLabel", "Level —", (FontStyles)1, Theme.ScaledOverlay(16));
			_progressLabel = AddRow("ProgressLabel", "XP — %", (FontStyles)0, Theme.ScaledOverlay(14));
			_xpBar = MiniBar.CreateWithSubLine(base.ContentRoot, "XpBar", out _xpBarFill, out _xpBarSubFill, new Color(0.4f, 0.85f, 1f, 0.95f), ResolveBarHeight());
			_xpBar.SetActive(false);
			_classLabel = AddRow("ClassLabel", "Class —", (FontStyles)2, Theme.ScaledOverlay(13));
			_weaponLabel = AddRow("WeaponLabel", "Weapon —", (FontStyles)0, Theme.ScaledOverlay(13));
			_weaponCounterLabel = AddRow("WeaponCounterLabel", "", (FontStyles)2, Theme.ScaledOverlay(11));
			_weaponCounterLabel.GameObject.SetActive(false);
			_weaponBar = MiniBar.CreateWithSubLine(base.ContentRoot, "WeaponXpBar", out _weaponBarFill, out _weaponBarSubFill, new Color(1f, 0.45f, 0.3f, 0.95f), ResolveBarHeight());
			_weaponBar.SetActive(false);
			_weaponStatsLabel = AddRow("WeaponStatsLabel", "", (FontStyles)2, Theme.ScaledOverlay(11));
			ConfigureBonusStatsLabel(_weaponStatsLabel);
			_weaponStatsLabel.GameObject.SetActive(false);
			_legacyLabel = AddRow("LegacyLabel", "Legacy —", (FontStyles)0, Theme.ScaledOverlay(13));
			_legacyCounterLabel = AddRow("LegacyCounterLabel", "", (FontStyles)2, Theme.ScaledOverlay(11));
			_legacyCounterLabel.GameObject.SetActive(false);
			_legacyBar = MiniBar.CreateWithSubLine(base.ContentRoot, "LegacyXpBar", out _legacyBarFill, out _legacyBarSubFill, new Color(0.75f, 0.25f, 0.45f, 0.95f), ResolveBarHeight());
			_legacyBar.SetActive(false);
			_legacyStatsLabel = AddRow("LegacyStatsLabel", "", (FontStyles)2, Theme.ScaledOverlay(11));
			ConfigureBonusStatsLabel(_legacyStatsLabel);
			_legacyStatsLabel.GameObject.SetActive(false);
			_exoLabel = AddRow("ExoLabel", "EXO Prestige —", (FontStyles)2, Theme.ScaledOverlay(13));
			Render(PlayerStateService.Experience);
			TryRenderExoFromState();
			if (!_subscribed)
			{
				PlayerStateService.ExperienceChanged += OnExperienceChanged;
				_subscribed = true;
			}
			if (!_expertiseSubscribed)
			{
				PlayerStateService.ExpertiseChanged += OnExpertiseChanged;
				_expertiseSubscribed = true;
			}
			if (!_legacySubscribed)
			{
				PlayerStateService.LegacyChanged += OnLegacyChanged;
				_legacySubscribed = true;
			}
			if (!_prestigeSubscribed)
			{
				PlayerStateService.PrestigeInfoChanged += OnPrestigeInfoChanged;
				_prestigeSubscribed = true;
			}
			if (!_lastResponseSubscribed)
			{
				PlayerStateService.LastResponseChanged += OnLastResponseChanged;
				_lastResponseSubscribed = true;
			}
			if (!_bloodInfoSubscribed)
			{
				PlayerStateService.BloodInfoChanged += OnBloodInfoChanged;
				_bloodInfoSubscribed = true;
			}
			RenderWeapon(PlayerStateService.Expertise);
			RenderLegacy(PlayerStateService.Legacy);
			PlayerStateService.LastServerResponse lastResponse = PlayerStateService.LastResponse;
			if (lastResponse.Command == ".wep get" && lastResponse.Lines != null && lastResponse.Lines.Count > 0)
			{
				_cachedWepGetLines = new List<string>(lastResponse.Lines);
			}
			ScheduleExoFetch();
			if (_bonusStatsTicker == null)
			{
				_bonusStatsTicker = BonusStatsTick;
				CoreUpdateBehavior.Actions.Add(_bonusStatsTicker);
			}
		}

		private void ScheduleExoFetch()
		{
			if (_exoFetchScheduled)
			{
				return;
			}
			_exoFetchScheduled = true;
			Action ticker = null;
			ticker = delegate
			{
				if (!MessageService.IsInitialized)
				{
					return;
				}
				CoreUpdateBehavior.Actions.Remove(ticker);
				try
				{
					MessageService.EnqueueMessage(".prestige get Exo");
				}
				catch (Exception ex)
				{
					LogUtils.LogWarning("ExperienceOverlay: auto .prestige get Exo failed — " + ex.Message);
				}
			};
			CoreUpdateBehavior.Actions.Add(ticker);
		}

		private void ConfigureBonusStatsLabel(LabelRef lbl)
		{
			if (lbl != null)
			{
				((TMP_Text)lbl.TextMesh).enableWordWrapping = true;
				((TMP_Text)lbl.TextMesh).overflowMode = (TextOverflowModes)0;
				GameObject gameObject = lbl.GameObject;
				int? minWidth = 220;
				int? preferredWidth = 240;
				int? num = 1;
				UIFactory.SetLayoutElement(minHeight: 16, flexibleWidth: num, preferredHeight: -1, gameObject: gameObject, minWidth: minWidth, flexibleHeight: 0, preferredWidth: preferredWidth);
				ContentSizeFitter obj = lbl.GameObject.AddComponent<ContentSizeFitter>();
				obj.horizontalFit = (FitMode)0;
				obj.verticalFit = (FitMode)2;
			}
		}

		private LabelRef AddRow(string name, string text, FontStyles style, int fontSize)
		{
			//IL_0010: 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)
			int value = ResolveRowHeight(fontSize);
			LabelRef labelRef = UIFactory.CreateLabel(base.ContentRoot, name, text, Theme.OverlayMidlineAlignment(), null, fontSize);
			GameObject gameObject = labelRef.GameObject;
			int? minWidth = 220;
			int? preferredWidth = 240;
			int? num = 1;
			UIFactory.SetLayoutElement(minHeight: value, flexibleWidth: num, preferredHeight: value, gameObject: gameObject, minWidth: minWidth, flexibleHeight: 0, preferredWidth: preferredWidth);
			((TMP_Text)labelRef.TextMesh).enableWordWrapping = false;
			((TMP_Text)labelRef.TextMesh).overflowMode = (TextOverflowModes)0;
			((TMP_Text)labelRef.TextMesh).fontStyle = style;
			return labelRef;
		}

		private static int ResolveRowHeight(int fontSize)
		{
			return Mathf.Max(20, Mathf.RoundToInt((float)fontSize * 1.45f));
		}

		private void OnExperienceChanged()
		{
			Render(PlayerStateService.Experience);
		}

		private void OnExpertiseChanged()
		{
			PlayerStateService.ExpertiseState expertise = PlayerStateService.Expertise;
			if (_seenWeaponTypeBaseline && expertise.Type != _lastSeenWeaponType)
			{
				_lastBonusStatsFetchAt = 0.0;
				_bonusStatsFetchToggle = true;
				_cachedWepGetLines = null;
			}
			_lastSeenWeaponType = expertise.Type;
			_seenWeaponTypeBaseline = true;
			RenderWeapon(expertise);
			RenderWeaponStats();
		}

		private void OnLegacyChanged()
		{
			PlayerStateService.LegacyState legacy = PlayerStateService.Legacy;
			if (_seenBloodTypeBaseline && legacy.Type != _lastSeenBloodType)
			{
				_lastBonusStatsFetchAt = 0.0;
				_bonusStatsFetchToggle = false;
			}
			_lastSeenBloodType = legacy.Type;
			_seenBloodTypeBaseline = true;
			RenderLegacy(legacy);
			RenderLegacyStats();
		}

		private void OnLastResponseChanged()
		{
			PlayerStateService.LastServerResponse lastResponse = PlayerStateService.LastResponse;
			if (!(lastResponse.Command != ".wep get") && lastResponse.Lines != null)
			{
				_cachedWepGetLines = new List<string>(lastResponse.Lines);
				ParseWepGetPreamble(_cachedWepGetLines);
				RenderWeaponStats();
				RenderWeaponCounter();
			}
		}

		private void ParseWepGetPreamble(List<string> lines)
		{
			if (lines == null || lines.Count == 0)
			{
				_wepGetHasData = false;
				return;
			}
			foreach (string line in lines)
			{
				Match match = _wepGetPreambleRegex.Match(line);
				if (match.Success && int.TryParse(match.Groups["xp"].Value.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && float.TryParse(match.Groups["pct"].Value.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
				{
					_wepGetRawExpertise = result;
					_wepGetProgressPct = result2;
					_wepGetHasData = true;
					break;
				}
			}
		}

		private void OnBloodInfoChanged()
		{
			RenderLegacyStats();
			RenderLegacyCounter();
		}

		private void RenderWeapon(PlayerStateService.ExpertiseState e)
		{
			if (_weaponLabel == null)
			{
				return;
			}
			ApplyBarChrome();
			if (e.Level <= 0 && e.Type == PlayerStateService.WeaponType.Sword)
			{
				((TMP_Text)_weaponLabel.TextMesh).text = "Weapon —";
				if ((Object)(object)_weaponBar != (Object)null && _weaponBar.activeSelf)
				{
					_weaponBar.SetActive(false);
				}
				RenderWeaponCounter();
				return;
			}
			string text = ((e.Prestige > 0) ? $"Weapon: {e.Type}  Lv {e.Level} ({e.Progress * 100f:0.#}%)   Pr {e.Prestige}" : $"Weapon: {e.Type}  Lv {e.Level} ({e.Progress * 100f:0.#}%)");
			((TMP_Text)_weaponLabel.TextMesh).text = text;
			bool showProgressBarExpertise = Settings.ShowProgressBarExpertise;
			if ((Object)(object)_weaponBar != (Object)null && _weaponBar.activeSelf != showProgressBarExpertise)
			{
				_weaponBar.SetActive(showProgressBarExpertise);
			}
			if (showProgressBarExpertise)
			{
				MiniBar.SetProgress(_weaponBarFill, e.Progress);
				int maxExpertiseLevel = PlayerStateService.Config.MaxExpertiseLevel;
				float progress = ((maxExpertiseLevel > 0) ? Mathf.Clamp01((float)e.Level / (float)maxExpertiseLevel) : 0f);
				ApplySubLine(_weaponBar, _weaponBarSubFill, Settings.ShowPrestigeSubLine && maxExpertiseLevel > 0, progress);
			}
			RenderWeaponCounter();
		}

		private void RenderLegacy(PlayerStateService.LegacyState l)
		{
			if (_legacyLabel == null)
			{
				return;
			}
			ApplyBarChrome();
			if (l.Level <= 0 && l.Type == PlayerStateService.BloodType.Worker)
			{
				((TMP_Text)_legacyLabel.TextMesh).text = "Legacy —";
				if ((Object)(object)_legacyBar != (Object)null && _legacyBar.activeSelf)
				{
					_legacyBar.SetActive(false);
				}
				RenderLegacyCounter();
				return;
			}
			string text = ((l.Prestige > 0) ? $"Legacy: {l.Type}  Lv {l.Level} ({l.Progress * 100f:0.#}%)   Pr {l.Prestige}" : $"Legacy: {l.Type}  Lv {l.Level} ({l.Progress * 100f:0.#}%)");
			((TMP_Text)_legacyLabel.TextMesh).text = text;
			bool showProgressBarLegacy = Settings.ShowProgressBarLegacy;
			if ((Object)(object)_legacyBar != (Object)null && _legacyBar.activeSelf != showProgressBarLegacy)
			{
				_legacyBar.SetActive(showProgressBarLegacy);
			}
			if (showProgressBarLegacy)
			{
				MiniBar.SetProgress(_legacyBarFill, l.Progress);
				int maxLegacyLevel = PlayerStateService.Config.MaxLegacyLevel;
				float progress = ((maxLegacyLevel > 0) ? Mathf.Clamp01((float)l.Level / (float)maxLegacyLevel) : 0f);
				ApplySubLine(_legacyBar, _legacyBarSubFill, Settings.ShowPrestigeSubLine && maxLegacyLevel > 0, progress);
			}
			RenderLegacyCounter();
		}

		private void RenderWeaponStats()
		{
			if (_weaponStatsLabel == null)
			{
				return;
			}
			if (!Settings.ShowOverlayBonusStats || _cachedWepGetLines == null || _cachedWepGetLines.Count == 0)
			{
				if (_weaponStatsLabel.GameObject.activeSelf)
				{
					_weaponStatsLabel.GameObject.SetActive(false);
				}
				return;
			}
			List<string> list = new List<string>(_cachedWepGetLines.Count);
			foreach (string cachedWepGetLine in _cachedWepGetLines)
			{
				string text = _tmpTagStripRegex.Replace(cachedWepGetLine, string.Empty).Trim();
				if (!string.IsNullOrEmpty(text) && !IsWepGetPreambleOrPlaceholder(text))
				{
					list.Add(text);
				}
			}
			if (list.Count == 0)
			{
				if (_weaponStatsLabel.GameObject.activeSelf)
				{
					_weaponStatsLabel.GameObject.SetActive(false);
				}
				return;
			}
			((TMP_Text)_weaponStatsLabel.TextMesh).text = string.Join("\n", list);
			if (!_weaponStatsLabel.GameObject.activeSelf)
			{
				_weaponStatsLabel.GameObject.SetActive(true);
			}
		}

		private static bool IsWepGetPreambleOrPlaceholder(string strippedLine)
		{
			if (!strippedLine.StartsWith("Your weapon expertise is", StringComparison.Ordinal) && !strippedLine.StartsWith("No bonuses from currently equipped", StringComparison.Ordinal))
			{
				return strippedLine.StartsWith("You haven't gained any expertise for", StringComparison.Ordinal);
			}
			return true;
		}

		private void RenderWeaponCounter()
		{
			if (_weaponCounterLabel == null)
			{
				return;
			}
			if (!Settings.ShowOverlayXpCounter || !_wepGetHasData)
			{
				if (_weaponCounterLabel.GameObject.activeSelf)
				{
					_weaponCounterLabel.GameObject.SetActive(false);
				}
				return;
			}
			int num = ((_wepGetProgressPct > 0.01f) ? Mathf.RoundToInt((float)_wepGetRawExpertise * 100f / _wepGetProgressPct) : 0);
			string text = ((num > 0) ? $"Exp: {_wepGetRawExpertise} / {num} ({_wepGetProgressPct:0.0}%)" : $"Exp: {_wepGetRawExpertise} ({_wepGetProgressPct:0.0}%)");
			((TMP_Text)_weaponCounterLabel.TextMesh).text = text;
			if (!_weaponCounterLabel.GameObject.activeSelf)
			{
				_weaponCounterLabel.GameObject.SetActive(true);
			}
		}

		private void RenderLegacyCounter()
		{
			if (_legacyCounterLabel == null)
			{
				return;
			}
			bool showOverlayXpCounter = Settings.ShowOverlayXpCounter;
			PlayerStateService.BloodInfo bloodInfoLatest = PlayerStateService.BloodInfoLatest;
			if (!showOverlayXpCounter || string.IsNullOrEmpty(bloodInfoLatest.BloodType))
			{
				if (_legacyCounterLabel.GameObject.activeSelf)
				{
					_legacyCounterLabel.GameObject.SetActive(false);
				}
				return;
			}
			if (!int.TryParse(bloodInfoLatest.Essence ?? "", NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
			{
				if (!float.TryParse(bloodInfoLatest.Essence ?? "", NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
				{
					if (_legacyCounterLabel.GameObject.activeSelf)
					{
						_legacyCounterLabel.GameObject.SetActive(false);
					}
					return;
				}
				result = Mathf.RoundToInt(result2);
			}
			if (!float.TryParse(bloodInfoLatest.ProgressPct ?? "", NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
			{
				result3 = 0f;
			}
			int num = ((result3 > 0.01f) ? Mathf.RoundToInt((float)result * 100f / result3) : 0);
			string text = ((num > 0) ? $"Ess: {result} / {num} ({result3:0.0}%)" : $"Ess: {result} ({result3:0.0}%)");
			((TMP_Text)_legacyCounterLabel.TextMesh).text = text;
			if (!_legacyCounterLabel.GameObject.activeSelf)
			{
				_legacyCounterLabel.GameObject.SetActive(true);
			}
		}

		private static int ResolveBarHeight()
		{
			return Settings.ProgressBarHeight;
		}

		private void ApplyBarChrome()
		{
			int height = ResolveBarHeight();
			MiniBar.SetHeight(_xpBar, height);
			MiniBar.SetHeight(_weaponBar, height);
			MiniBar.SetHeight(_legacyBar, height);
		}

		private static void ApplySubLine(GameObject bar, RectTransform subFill, bool wantVisible, float progress01)
		{
			if ((Object)(object)bar == (Object)null || (Object)(object)subFill == (Object)null)
			{
				return;
			}
			GameObject gameObject = ((Component)subFill).gameObject;
			if (!wantVisible)
			{
				if (gameObject.activeSelf)
				{
					gameObject.SetActive(false);
				}
				return;
			}
			if (!gameObject.activeSelf)
			{
				gameObject.SetActive(true);
			}
			MiniBar.SetProgress(subFill, progress01);
		}

		private void RenderLegacyStats()
		{
			if (_legacyStatsLabel == null)
			{
				return;
			}
			bool showOverlayBonusStats = Settings.ShowOverlayBonusStats;
			PlayerStateService.BloodInfo bloodInfoLatest = PlayerStateService.BloodInfoLatest;
			bool flag = !string.IsNullOrEmpty(bloodInfoLatest.BloodType) && bloodInfoLatest.StatLines != null && bloodInfoLatest.StatLines.Count > 0;
			if (!showOverlayBonusStats || !flag)
			{
				if (_legacyStatsLabel.GameObject.activeSelf)
				{
					_legacyStatsLabel.GameObject.SetActive(false);
				}
				return;
			}
			((TMP_Text)_legacyStatsLabel.TextMesh).text = string.Join("\n", bloodInfoLatest.StatLines);
			if (!_legacyStatsLabel.GameObject.activeSelf)
			{
				_legacyStatsLabel.GameObject.SetActive(true);
			}
		}

		private void BonusStatsTick()
		{
			RenderWeaponStats();
			RenderLegacyStats();
			if (!Settings.ShowOverlayBonusStats || !MessageService.IsInitialized)
			{
				return;
			}
			bool valueOrDefault = (Plugin.UIManager?.CombinedOverlay?.Enabled).GetValueOrDefault();
			if (!base.Enabled && !valueOrDefault)
			{
				return;
			}
			double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
			if (_lastBonusStatsFetchAt > 0.0 && realtimeSinceStartupAsDouble - _lastBonusStatsFetchAt < 10.0)
			{
				return;
			}
			_lastBonusStatsFetchAt = realtimeSinceStartupAsDouble;
			try
			{
				if (_bonusStatsFetchToggle)
				{
					MessageService.EnqueueMessageSilent(".wep get");
				}
				else
				{
					PlayerStateService.LegacyState legacy = PlayerStateService.Legacy;
					if (PlayerStateService.IsBondableBloodType(legacy.Type))
					{
						MessageService.EnqueueMessageSilent($".bl get {legacy.Type}");
					}
				}
				_bonusStatsFetchToggle = !_bonusStatsFetchToggle;
			}
			catch (Exception ex)
			{
				LogUtils.LogWarning("ExperienceOverlay: bonus-stats refresh failed — " + ex.Message);
			}
		}

		private void OnPrestigeInfoChanged()
		{
			TryRenderExoFromState();
		}

		private void TryRenderExoFromState()
		{
			PlayerStateService.PrestigeInfo prestigeInfoLatest = PlayerStateService.PrestigeInfoLatest;
			if (prestigeInfoLatest.TypeName != null && string.Equals(prestigeInfoLatest.TypeName, "Exo", StringComparison.OrdinalIgnoreCase))
			{
				_exoLevel = prestigeInfoLatest.Level;
				_exoMaxLevel = prestigeInfoLatest.MaxLevel;
				if (_exoLabel != null)
				{
					((TMP_Text)_exoLabel.TextMesh).text = $"EXO Prestige: {_exoLevel}" + ((_exoMaxLevel > 0) ? $" / {_exoMaxLevel}" : "");
				}
			}
		}

		private void Render(PlayerStateService.ExperienceState s)
		{
			if (_levelLabel != null)
			{
				ApplyBarChrome();
				string text = ((s.Prestige > 0) ? $"Level {s.Level}   Prestige {s.Prestige}" : $"Level {s.Level}");
				((TMP_Text)_levelLabel.TextMesh).text = text;
				((TMP_Text)_progressLabel.TextMesh).text = $"XP {s.Progress * 100f:0.#}%";
				((TMP_Text)_classLabel.TextMesh).text = $"Class: {s.Class}";
				bool showProgressBarXP = Settings.ShowProgressBarXP;
				if ((Object)(object)_xpBar != (Object)null && _xpBar.activeSelf != showProgressBarXP)
				{
					_xpBar.SetActive(showProgressBarXP);
				}
				if (showProgressBarXP)
				{
					MiniBar.SetProgress(_xpBarFill, s.Progress);
					int maxPlayerLevel = PlayerStateService.Config.MaxPlayerLevel;
					float progress = ((maxPlayerLevel > 0) ? Mathf.Clamp01((float)s.Level / (float)maxPlayerLevel) : 0f);
					ApplySubLine(_xpBar, _xpBarSubFill, Settings.ShowPrestigeSubLine && maxPlayerLevel > 0, progress);
				}
			}
		}

		internal override void Reset()
		{
			if (_subscribed)
			{
				PlayerStateService.ExperienceChanged -= OnExperienceChanged;
				_subscribed = false;
			}
			if (_expertiseSubscribed)
			{
				PlayerStateService.ExpertiseChanged -= OnExpertiseChanged;
				_expertiseSubscribed = false;
			}
			if (_legacySubscribed)
			{
				PlayerStateService.LegacyChanged -= OnLegacyChanged;
				_legacySubscribed = false;
			}
			if (_prestigeSubscribed)
			{
				PlayerStateService.PrestigeInfoChanged -= OnPrestigeInfoChanged;
				_prestigeSubscribed = false;
			}
			if (_lastResponseSubscribed)
			{
				PlayerStateService.LastResponseChanged -= OnLastResponseChanged;
				_lastResponseSubscribed = false;
			}
			if (_bloodInfoSubscribed)
			{
				PlayerStateService.BloodInfoChanged -= OnBloodInfoChanged;
				_bloodInfoSubscribed = false;
			}
			if (_bonusStatsTicker != null)
			{
				CoreUpdateBehavior.Actions.Remove(_bonusStatsTicker);
				_bonusStatsTicker = null;
			}
		}
	}
	public class FamiliarBrowserOverlayPanel : ResizeablePanelBase
	{
		private enum ViewMode
		{
			BoxView,
			VBloodView
		}

		private struct VBloodOverlayRow
		{
			public string BaseName;

			public string DisplayName;

			public string Box;

			public int Index;

			public int Level;

			public int Prestige;

			public bool IsShiny;

			public bool IsPrimal;

			public string ShinySchool;
		}

		private TextMeshProUGUI _boxNameLabel;

		private TextMeshProUGUI _activeFamLabel;

		private TextMeshProUGUI _swapWarningLabel;

		private GameObject _famListContainer;

		private ButtonRef _toggleBtn;

		private ButtonRef _unbindBtn;

		private ButtonRef _sortBtn;

		private ButtonRef _scanBtn;

		private ViewMode _viewMode;

		private ButtonRef _viewBtn;

		private GameObject _boxNavRow;

		private TextMeshProUGUI _vbStatusLabel;

		private bool _vbSummonStatusSubscribed;

		private bool _vbCollectionSubscribed;

		private int _pendingSwapIndex = -1;

		private float _pendingSwapDeadline = -1f;

		private const float SWAP_CONFIRM_WINDOW_SECONDS = 5f;

		private bool _subscribed;

		private bool _autoPullDone;

		public override string PanelId => "FamiliarBrowserOverlay";

		public override PanelType PanelType => PanelType.FamiliarBrowserOverlay;

		public override int MinWidth => 280;

		public override int MinHeight => 440;

		public override Vector2 DefaultAnchorMin => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultAnchorMax => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultPivot => new Vector2(0.5f, 0.5f);

		public override Vector2 DefaultPosition => new Vector2(base.Owner.Scaler.m_ReferenceResolution.x * 0.5f - 320f, -40f);

		public override bool CanDrag => true;

		public override PanelDragger.ResizeTypes CanResize => PanelDragger.ResizeTypes.All;

		public override float Opacity => Settings.TransparencyToAlpha(Settings.FamiliarBrowserTransparency);

		public override bool UsesCustomBackgroundColor => true;

		public override bool UsesCustomInnerBackgroundColor => true;

		public FamiliarBrowserOverlayPanel(UIBase owner)
			: base(owner)
		{
		}

		protected override void ConstructPanelContent()
		{
			base.ConstructPanelContent();
			VerticalLayoutGroup component = base.ContentRoot.GetComponent<VerticalLayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
			}
			BuildHeader();
			BuildFamiliarList();
			BuildFooter();
			if (!_subscribed)
			{
				PlayerStateService.BoxListChanged += OnAnyBoxStateChanged;
				PlayerStateService.BoxContentsChanged += OnAnyBoxStateChanged;
				PlayerStateService.ActiveBoxChanged += OnAnyBoxStateChanged;
				PlayerStateService.FamiliarChanged += OnAnyBoxStateChanged;
				_subscribed = true;
			}
			if (!_vbCollectionSubscribed)
			{
				PlayerStateService.VBloodCollectionChanged += OnAnyBoxStateChanged;
				VBloodScannerService.ScanStateChanged += OnScanStateChanged;
				_vbCollectionSubscribed = true;
			}
			ApplyViewModeVisibility();
			CoreUpdateBehavior.Actions.Add(TickDeferredAutoPull);
			Render();
		}

		private void TickDeferredAutoPull()
		{
			if (!_autoPullDone && MessageService.IsInitialized)
			{
				_autoPullDone = true;
				if (PlayerStateService.BoxList == null || PlayerStateService.BoxList.Count <= 0)
				{
					EnqueueOrWarn(".fam boxes");
				}
			}
		}

		private void BuildHeader()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_066b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = UIFactory.CreateHorizontalGroup(base.ContentRoot, "OverlayToolbar", forceExpandWidth: true, forceExpandHeight: false, childControlWidth: true, childControlHeight: true, 4, new Vector4(0f, 0f, 0f, 0f));
			int? minWidth = 260;
			int? preferredWidth = 280;
			int? num = 1;
			UIFactory.SetLayoutElement(minHeight: 28, flexibleWidth: num, preferredHeight: 30, gameObject: val, minWidth: minWidth, flexibleHeight: 0, preferredWidth: preferredWidth);
			ButtonRef buttonRef = UIFactory.CreateButton(val, "BoxPrev", "←");
			GameObject gameObject = buttonRef.GameObject;
			int? minWidth2 = 28;
			int? preferredWidth2 = 30;
			num = 0;
			UIFactory.SetLayoutElement(minHeight: 26, flexibleWidth: num, preferredHeight: 28, gameObject: gameObject, minWidth: minWidth2, flexibleHeight: 0, preferredWidth: preferredWidth2);
			TextMeshProUGUI componentInChildren = ((Component)buttonRef.Component).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).fontSize = Theme.ScaledOverlay(16);
				((TMP_Text)componentInChildren).fontStyle = (FontStyles)1;
			}
			buttonRef.OnClick = delegate
			{
				CycleBox(-1);
			};
			TooltipHover.Attach(buttonRef.GameObject, "Previous box (cycles left through your familiar boxes).");
			ButtonRef buttonRef2 = UIFactory.CreateButton(val, "BoxNext", "→");
			GameObject gameObject2 = buttonRef2.GameObject;
			int? minWidth3 = 28;
			preferredWidth = 30;
			num = 0;
			UIFactory.SetLayoutElement(minHeight: 26, flexibleWidth: num, preferredHeight: 28, gameObject: gameObject2, minWidth: minWidth3, flexibleHeight: 0, preferredWidth: preferredWidth);
			TextMeshProUGUI componentInChildren2 = ((Component)buttonRef2.Component).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				((TMP_Text)componentInChildren2).fontSize = Theme.ScaledOverlay(16);
				((TMP_Text)componentInChildren2).fontStyle = (FontStyles)1;
			}
			buttonRef2.OnClick = delegate
			{
				CycleBox(1);
			};
			TooltipHover.Attach(buttonRef2.GameObject, "Next box (cycles right through your familiar boxes).");
			ButtonRef buttonRef3 = UIFactory.CreateButton(val, "BoxRefresh", "Reload");
			GameObject gameObject3 = buttonRef3.GameObject;
			int? minWidth4 = 54;
			preferredWidth2 = 60;
			num = 0;
			UIFactory.SetLayoutElement(minHeight: 26, flexibleWidth: num, preferredHeight: 28, gameObject: gameObject3, minWidth: minWidth4, flexibleHeight: 0, preferredWidth: preferredWidth2);
			TextMeshProUGUI componentInChildren3 = ((Component)buttonRef3.Component).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren3 != (Object)null)
			{
				((TMP_Text)componentInChildren3).fontSize = Theme.ScaledOverlay(11);
			}
			buttonRef3.OnClick = delegate
			{
				EnqueueOrWarn(".fam boxes");
				EnqueueOrWarn(".fam l");
			};
			TooltipHover.Attach(buttonRef3.GameObject, "Re-pull the box list AND the current box's familiar list from the server.");
			_scanBtn = UIFactory.CreateButton(val, "OverlayScanBtn", FormatScanBtnText());
			GameObject gameObject4 = _scanBtn.GameObject;
			int? minWidth5 = 54;
			preferredWidth = 60;
			num = 0;
			UIFactory.SetLayoutElement(minHeight: 26, flexibleWidth: num, preferredHeight: 28, gameObject: gameObject4, minWidth: minWidth5, flexibleHeight: 0, preferredWidth: preferredWidth);
			TextMeshProUGUI componentInChildren4 = ((Component)_scanBtn.Component).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren4 != (Object)null)
			{
				((TMP_Text)componentInChildren4).fontSize = Theme.ScaledOverlay(11);
			}
			_scanBtn.OnClick = delegate
			{
				if (VBloodScannerService.Scanning)
				{
					VBloodScannerService.CancelScan();
				}
				else
				{
					VBloodScannerService.StartScan();
				}
				RefreshScanBtnText();
			};
			TooltipHover.Attach(_scanBtn.GameObject, "Run the V-Blood box-sweep scan from the overlay — same as the V-Bloods tab's Scan all button. Walks every box; ~30-60s; restores your active box at the end. Click again while running to cancel.");
			_viewBtn = UIFactory.CreateButton(val, "ViewModeBtn", FormatViewBtnText());
			GameObject gameObject5 = _viewBtn.GameObject;
			int? minWidth6 = 60;
			preferredWidth2 = 70;
			num = 0;
			UIFactory.SetLayoutElement(minHeight: 26, flexibleWidth: num, preferredHeight: 28, gameObject: gameObject5, minWidth: minWidth6, flexibleHeight: 0, preferredWidth: preferredWidth2);
			TextMeshProUGUI componentInChildren5 = ((Component)_viewBtn.Component).