Decompiled source of Silken Impact v1.6.0

plugins/com.kokomi.silkenimpact.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using SilkenImpact;
using SilkenImpact.Patch;
using TMPro;
using TeamCherry.Localization;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.kokomi.silkenimpact")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.6.0.0")]
[assembly: AssemblyInformationalVersion("1.6.0+051e21b7d3445bf53176ca55e1c2c4b1bc111a0e")]
[assembly: AssemblyProduct("Silken Impact")]
[assembly: AssemblyTitle("com.kokomi.silkenimpact")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.6.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;
		}
	}
}
public class BossHealthBarContainer : MonoBehaviour
{
	[SerializeField]
	private List<HealthBar> bars = new List<HealthBar>();

	[SerializeField]
	private RectTransform rect;

	public float interval = 0.3f;

	public void SetWidth(float width)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		RectTransform component = ((Component)this).GetComponent<RectTransform>();
		component.sizeDelta = new Vector2(width, component.sizeDelta.y);
		OnUpdate();
	}

	public void AddBar(HealthBar bar)
	{
		if (!Object.op_Implicit((Object)(object)bars.Find((HealthBar b) => (Object)(object)b == (Object)(object)bar)))
		{
			bars.Add(bar);
			((Component)bar).transform.SetParent(((Component)this).transform, false);
			OnUpdate();
		}
	}

	public void RemoveBar(HealthBar bar)
	{
		bars.Remove(bar);
		OnUpdate();
	}

	private float barWidth()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		int count = bars.Count;
		if (count <= 0)
		{
			return 0f;
		}
		Rect val = rect.rect;
		return (((Rect)(ref val)).width - interval * (float)(count - 1)) / (float)count;
	}

	private float barCenterX(int index, float barWidth)
	{
		return (float)index * (barWidth + interval) + barWidth / 2f;
	}

	private void OnUpdate()
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		int count = bars.Count;
		float width = barWidth();
		for (int i = 0; i < count; i++)
		{
			bars[i].SetWidth(width);
			((Component)bars[i]).GetComponent<RectTransform>().anchoredPosition = new Vector2(barCenterX(i, width), 0f);
		}
	}

	internal void TakeDamage(int index, float amount)
	{
		int count = bars.Count;
		if (index < count && index >= 0)
		{
			bars[index].TakeDamage(amount);
		}
	}

	internal void Heal(int index, float amount)
	{
		int count = bars.Count;
		if (index < count && index >= 0)
		{
			bars[index].Heal(amount);
		}
	}
}
public class ContainerTest : MonoBehaviour
{
	public BossHealthBarContainer container;
}
namespace System.Runtime.CompilerServices
{
	internal static class IsExternalInit
	{
	}
}
namespace SilkenImpact
{
	internal static class AssetPaths
	{
		internal static class Prefabs
		{
			internal const string DamageText = "Assets/Addressables/Prefabs/DamageOldText.prefab";

			internal const string HealText = "Assets/Addressables/Prefabs/HealOldText.prefab";

			internal const string BossContainer = "Assets/Addressables/Prefabs/Container.prefab";
		}

		internal static class HealthBars
		{
			internal const string RoundedMob = "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab";

			internal const string DiamondMob = "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Diamond.prefab";

			internal const string RoundedBoss = "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab";

			internal const string DiamondBoss = "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/DiamondBoss.prefab";

			internal static string ForMobShape(HealthBarShape shape)
			{
				if (shape == HealthBarShape.Diamond)
				{
					return "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Diamond.prefab";
				}
				return "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab";
			}

			internal static string ForBossShape(HealthBarShape shape)
			{
				if (shape == HealthBarShape.Diamond)
				{
					return "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/DiamondBoss.prefab";
				}
				return "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab";
			}
		}
	}
	public enum HealthBarShape
	{
		Rounded,
		Diamond
	}
	public class Configs : MonoBehaviour
	{
		private static Configs __instance;

		public ConfigEntry<float> shortBarWidth;

		public ConfigEntry<float> mediumBarWidth;

		public ConfigEntry<float> longBarWidth;

		public ConfigEntry<float> bossBarWidth;

		public ConfigEntry<HealthBarShape> healthBarShape;

		public ConfigEntry<float> minMobHp;

		public ConfigEntry<float> minMediumBarHp;

		public ConfigEntry<float> minLongBarHp;

		public ConfigEntry<float> minBossBarHp;

		public ConfigEntry<float> infHp;

		public ConfigEntry<bool> displayMobHpBar;

		public ConfigEntry<bool> displayBossHpBar;

		public ConfigEntry<float> spriteTrackerZOffset;

		public ConfigEntry<float> maxZPosition;

		public ConfigEntry<float> visibleCacheSeconds;

		public ConfigEntry<float> invisibleCacheSeconds;

		public ConfigEntry<Color> hpColor;

		public ConfigEntry<Color> delayedEffectColor;

		public ConfigEntry<Color> hpBarBackgroundColor;

		public ConfigEntry<Color> hpNumberColor;

		public ConfigEntry<bool> displayHpNumbers;

		public ConfigEntry<float> hpNumberFontSizeScaler;

		public ConfigEntry<float> bossNameFontSizeScaler;

		public ConfigEntry<Color> defaultColor;

		public ConfigEntry<Color> poisonColor;

		public ConfigEntry<Color> fireColor;

		public ConfigEntry<Color> critHitColor;

		public ConfigEntry<Color> healTextColor;

		public ConfigEntry<float> weightOfNewHit;

		public ConfigEntry<bool> displayDamageText;

		public ConfigEntry<bool> displayHealText;

		public ConfigEntry<float> damageFontSizeScaler;

		public ConfigEntry<FontOption> damageFont;

		public ConfigEntry<string> damageOsFontName;

		public ConfigEntry<FontOption> hpBarFont;

		public ConfigEntry<string> hpBarOsFontName;

		internal ConfigEntry<LanguageOption> selectedLanguage;

		public static Configs Instance
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				if ((Object)(object)__instance == (Object)null)
				{
					GameObject val = new GameObject("Configs");
					__instance = val.AddComponent<Configs>();
					Object.DontDestroyOnLoad((Object)val);
				}
				return __instance;
			}
		}

		private ConfigFile config => ((BaseUnityPlugin)Plugin.Instance).Config;

		private void Awake()
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)__instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			BindLanguage(LanguageOption.English);
			LoadLanguageConfigs(selectedLanguage.Value);
		}

		private void BindLanguage(LanguageOption defaultOption)
		{
			new MyConfigSection("Language", config).AddAdvancedEntry(ref selectedLanguage, defaultOption, "Selected Language", "Choose config language (requires reopening the config manager window)");
			selectedLanguage.SettingChanged += OnLanguageChanged;
		}

		private void OnLanguageChanged(object sender, EventArgs e)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			try
			{
				object boxedValue = ((SettingChangedEventArgs)e).ChangedSetting.BoxedValue;
				_ = selectedLanguage;
				config.Clear();
				LanguageOption valueOrDefault = (boxedValue as LanguageOption?).GetValueOrDefault();
				LoadLanguageConfigs(valueOrDefault);
				BindLanguage(valueOrDefault);
			}
			finally
			{
				config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		private void LoadLanguageConfigs(LanguageOption language)
		{
			LocalizedConfigs.Load(this, language);
		}

		public float GetHpBarWidth(float maxHp, bool isBoss)
		{
			if (isBoss)
			{
				return bossBarWidth.Value;
			}
			if (maxHp >= minLongBarHp.Value)
			{
				return longBarWidth.Value;
			}
			if (maxHp >= minMediumBarHp.Value)
			{
				return mediumBarWidth.Value;
			}
			return shortBarWidth.Value;
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

		public bool? ShowRangeAsPercent;

		public Action<ConfigEntryBase> CustomDrawer;

		public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

		public bool? Browsable;

		public string Category;

		public object DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string Description;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		public Func<object, string> ObjToStr;

		public Func<string, object> StrToObj;
	}
	internal class MyConfigEntry<T>
	{
		public string Section;

		public string Key;

		public T DefaultValue;

		public string Description;

		public bool IsAdvanced;

		public int Order;

		public bool Browsable;

		public ConfigEntry<T> Bind(ConfigFile config)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			return config.Bind<T>(Section, Key, DefaultValue, new ConfigDescription(Description, (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					IsAdvanced = IsAdvanced,
					Order = Order,
					Browsable = Browsable
				}
			}));
		}
	}
	internal class MyConfigSliderEntry<T> : MyConfigEntry<T> where T : IComparable
	{
		public T MinValue;

		public T MaxValue;

		public new ConfigEntry<T> Bind(ConfigFile config)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			return config.Bind<T>(Section, Key, DefaultValue, new ConfigDescription(Description, (AcceptableValueBase)(object)new AcceptableValueRange<T>(MinValue, MaxValue), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					IsAdvanced = IsAdvanced,
					Order = Order,
					Browsable = Browsable
				}
			}));
		}
	}
	internal class MyConfigSection
	{
		public ConfigFile configFile;

		private int _nextOrder = int.MaxValue;

		public string Name { get; }

		public MyConfigSection(string name, ConfigFile configFile)
		{
			Name = name;
			this.configFile = configFile;
		}

		public MyConfigSection AddEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description, bool isAdvanced = false, bool browsable = true)
		{
			int order = _nextOrder--;
			MyConfigEntry<T> myConfigEntry = new MyConfigEntry<T>
			{
				Section = Name,
				Key = key,
				DefaultValue = defaultValue,
				Description = description,
				IsAdvanced = isAdvanced,
				Order = order,
				Browsable = browsable
			};
			entry = myConfigEntry.Bind(configFile);
			return this;
		}

		public MyConfigSection AddSliderEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description, T minValue, T maxValue, bool isAdvanced = false, bool browsable = true) where T : IComparable
		{
			int order = _nextOrder--;
			MyConfigSliderEntry<T> myConfigSliderEntry = new MyConfigSliderEntry<T>
			{
				Section = Name,
				Key = key,
				DefaultValue = defaultValue,
				Description = description,
				IsAdvanced = isAdvanced,
				Order = order,
				Browsable = browsable,
				MinValue = minValue,
				MaxValue = maxValue
			};
			entry = myConfigSliderEntry.Bind(configFile);
			return this;
		}

		public MyConfigSection AddEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config, bool isAdvanced = false, bool browsable = true)
		{
			return AddEntry(ref entry, defaultValue, config.key, config.description, isAdvanced, browsable);
		}

		public MyConfigSection AddSliderEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config, T minValue, T maxValue, bool isAdvanced = false, bool browsable = true) where T : IComparable
		{
			return AddSliderEntry(ref entry, defaultValue, config.key, config.description, minValue, maxValue, isAdvanced, browsable);
		}

		public MyConfigSection AddHiddenEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description, bool isAdvanced = false)
		{
			return AddEntry(ref entry, defaultValue, key, description, isAdvanced, browsable: false);
		}

		public MyConfigSection AddHiddenEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config, bool isAdvanced = false)
		{
			return AddEntry(ref entry, defaultValue, config.key, config.description, isAdvanced, browsable: false);
		}

		public MyConfigSection AddAdvancedEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description, bool browsable = true)
		{
			return AddEntry(ref entry, defaultValue, key, description, isAdvanced: true, browsable);
		}

		public MyConfigSection AddAdvancedEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config, bool browsable = true)
		{
			return AddEntry(ref entry, defaultValue, config.key, config.description, isAdvanced: true, browsable);
		}

		public MyConfigSection AddDebugOnlyEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description)
		{
			return AddHiddenEntry(ref entry, defaultValue, key, description);
		}

		public MyConfigSection AddDebugOnlyEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config)
		{
			return AddHiddenEntry(ref entry, defaultValue, config.key, config.description);
		}
	}
	internal enum LanguageOption
	{
		English,
		简体中文,
		Deutsch,
		Español,
		Français,
		Italiano,
		日本語,
		한국어,
		Português,
		Русский
	}
	[Serializable]
	public class ConfigEntry
	{
		[JsonProperty]
		public string key;

		[JsonProperty]
		public string description;
	}
	[Serializable]
	public class ConfigSection
	{
		[JsonProperty]
		public string name;

		[JsonProperty]
		public Dictionary<string, ConfigEntry> entries = new Dictionary<string, ConfigEntry>();

		public ConfigEntry this[string key] => entries[key];

		public (string key, string description) Get(string key)
		{
			ConfigEntry configEntry = entries[key];
			return (configEntry.key, configEntry.description);
		}
	}
	[Serializable]
	public class LocalizationData
	{
		[JsonProperty("sections")]
		private Dictionary<string, ConfigSection> sections = new Dictionary<string, ConfigSection>();

		public ConfigSection this[string sectionName] => sections[sectionName];
	}
	internal class LocalizedConfigs
	{
		private static LocalizationData localization;

		private static LanguageOption? loadedLanguage;

		protected static string JsonFileName(LanguageOption option)
		{
			return option switch
			{
				LanguageOption.English => "en.json", 
				LanguageOption.简体中文 => "zh.json", 
				LanguageOption.Deutsch => "de.json", 
				LanguageOption.Español => "es.json", 
				LanguageOption.Français => "fr.json", 
				LanguageOption.Italiano => "it.json", 
				LanguageOption.日本語 => "ja.json", 
				LanguageOption.한국어 => "ko.json", 
				LanguageOption.Português => "pt.json", 
				LanguageOption.Русский => "ru.json", 
				_ => "en.json", 
			};
		}

		private static void LoadLocalizationIfNeeded(LanguageOption option)
		{
			if (!loadedLanguage.HasValue || loadedLanguage != option)
			{
				loadedLanguage = option;
			}
			try
			{
				localization = JsonConvert.DeserializeObject<LocalizationData>(File.ReadAllText(Path.Combine(Plugin.AssetsFolder, "Localization", JsonFileName(loadedLanguage.Value))));
			}
			catch (Exception ex)
			{
				loadedLanguage = null;
				throw ex;
			}
		}

		public static void Load(Configs configs, LanguageOption option)
		{
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				LoadLocalizationIfNeeded(option);
			}
			catch (Exception arg)
			{
				PluginLogger.LogFatal($"[LocalizedConfigs][Load] Load failed, language={option} error={arg}");
				return;
			}
			ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
			ConfigSection configSection = localization["User: Health Bar Sizes"];
			new MyConfigSection(configSection.name, ((BaseUnityPlugin)Plugin.Instance).Config).AddEntry(ref configs.shortBarWidth, 2f, configSection.Get("Short Bar Width")).AddEntry(ref configs.mediumBarWidth, 4f, configSection.Get("Medium Bar Width")).AddEntry(ref configs.longBarWidth, 6f, configSection.Get("Long Bar Width"))
				.AddEntry(ref configs.bossBarWidth, 13f, configSection.Get("Boss Bar Width"));
			ConfigSection configSection2 = localization["User: Visibility Control"];
			new MyConfigSection(configSection2.name, config).AddEntry(ref configs.displayMobHpBar, defaultValue: true, configSection2.Get("Display Mob HP Bar")).AddEntry(ref configs.displayBossHpBar, defaultValue: true, configSection2.Get("Display Boss HP Bar")).AddEntry(ref configs.displayDamageText, defaultValue: true, configSection2.Get("Display Damage Text"))
				.AddEntry(ref configs.displayHealText, defaultValue: true, configSection2.Get("Display Heal Text"))
				.AddEntry(ref configs.displayHpNumbers, defaultValue: false, configSection2.Get("Display Health Numbers"));
			ConfigSection configSection3 = localization["User: Health Bar Thresholds"];
			new MyConfigSection(configSection3.name, config).AddAdvancedEntry(ref configs.minMobHp, 5f, configSection3.Get("Min Mob HP")).AddAdvancedEntry(ref configs.minMediumBarHp, 50f, configSection3.Get("Min Medium Bar HP")).AddAdvancedEntry(ref configs.minLongBarHp, 100f, configSection3.Get("Min Long Bar HP"))
				.AddAdvancedEntry(ref configs.minBossBarHp, 120f, configSection3.Get("Min Boss Bar HP"));
			ConfigSection configSection4 = localization["User: Health Bar Shapes"];
			new MyConfigSection(configSection4.name, config).AddEntry(ref configs.healthBarShape, HealthBarShape.Diamond, configSection4.Get("Health Bar Shape"));
			ConfigSection configSection5 = localization["User: Health Bar Colors"];
			new MyConfigSection(configSection5.name, config).AddEntry(ref configs.hpColor, ColourPalette.HP, configSection5.Get("HP Color")).AddEntry(ref configs.delayedEffectColor, ColourPalette.DelayedEffect, configSection5.Get("Delayed Effect Color")).AddEntry(ref configs.hpBarBackgroundColor, ColourPalette.HpBarBackground, configSection5.Get("HP Bar Background Color"))
				.AddEntry(ref configs.hpNumberColor, ColourPalette.HpNumber, configSection5.Get("HP Number Color"));
			ConfigSection configSection6 = localization["User: Health Bar Font Size"];
			new MyConfigSection(configSection6.name, config).AddSliderEntry(ref configs.hpNumberFontSizeScaler, 1f, configSection6.Get("HP Number Font Size Scaler"), 0.1f, 2f).AddSliderEntry(ref configs.bossNameFontSizeScaler, 1f, configSection6.Get("Boss Name Font Size Scaler"), 0.1f, 2f);
			ConfigSection configSection7 = localization["User: Damage Text Colors"];
			new MyConfigSection(configSection7.name, config).AddEntry(ref configs.defaultColor, ColourPalette.HornetDress, configSection7.Get("Default Color")).AddEntry(ref configs.critHitColor, ColourPalette.Geo, configSection7.Get("Crit Hit Color")).AddEntry(ref configs.poisonColor, ColourPalette.Electro, configSection7.Get("Poison Color"))
				.AddEntry(ref configs.fireColor, ColourPalette.Pyro, configSection7.Get("Fire Color"))
				.AddEntry(ref configs.healTextColor, ColourPalette.HealTextColor, configSection7.Get("Heal Color"));
			ConfigSection configSection8 = localization["User: Damage Text Settings"];
			new MyConfigSection(configSection8.name, config).AddSliderEntry(ref configs.damageFontSizeScaler, 1f, configSection8.Get("Damage Font Scaler"), 0.1f, 2f).AddDebugOnlyEntry(ref configs.weightOfNewHit, 0.2f, configSection8.Get("Weight Of New Hit"));
			ConfigSection configSection9 = localization["User: Font Settings"];
			new MyConfigSection(configSection9.name, config).AddEntry(ref configs.damageFont, FontOption.SmileySans, configSection9.Get("Damage Font")).AddEntry(ref configs.damageOsFontName, "Arial", configSection9.Get("Damage OS Font Name")).AddEntry(ref configs.hpBarFont, FontOption.SmileySans, configSection9.Get("HP Bar Font"))
				.AddEntry(ref configs.hpBarOsFontName, "Arial", configSection9.Get("HP Bar OS Font Name"));
			ConfigSection configSection10 = localization["Dev: Visibility Controller Settings"];
			new MyConfigSection(configSection10.name, config).AddDebugOnlyEntry(ref configs.maxZPosition, 1f, configSection10.Get("Max Z Position")).AddDebugOnlyEntry(ref configs.visibleCacheSeconds, 0.5f, configSection10.Get("Visible Cache Seconds")).AddDebugOnlyEntry(ref configs.invisibleCacheSeconds, 0.5f, configSection10.Get("Invisible Cache Seconds"))
				.AddDebugOnlyEntry(ref configs.infHp, 10000f, configSection10.Get("Infinite HP Threshold"))
				.AddDebugOnlyEntry(ref configs.spriteTrackerZOffset, -1.5f, configSection10.Get("Sprite Tracker Z Offset"));
		}
	}
	public static class DamageTextSpawnUtils
	{
		public static float avgDamagePerHit = -1f;

		public static float weightOfNew => Configs.Instance.weightOfNewHit.Value;

		private static void spawnTextOn(HealthManager hm, GameObject textGO, string content, float horizontalOffsetScale, float verticalOffsetScale, float sizeScale, Color color)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			((Object)textGO).name = content + " -> " + ((Object)((Component)hm).gameObject).name;
			Renderer component = ((Component)hm).gameObject.GetComponent<Renderer>();
			? val;
			if (!Object.op_Implicit((Object)(object)component))
			{
				val = new Vector3(1f, 1f, 0f);
			}
			else
			{
				Bounds bounds = component.bounds;
				val = ((Bounds)(ref bounds)).size;
			}
			Vector3 val2 = (Vector3)val;
			val2.x *= horizontalOffsetScale / 2f;
			val2.y *= verticalOffsetScale / 2f;
			textGO.transform.position = ((Component)hm).gameObject.transform.position + val2;
			textGO.transform.SetParent(((Component)WorldSpaceCanvas.GetWorldSpaceCanvas).transform, true);
			DamageText component2 = textGO.GetComponent<DamageText>();
			component2.DamageString = content;
			component2.TextColor = color;
			component2.TextFont = Singleton<FontManager>.instance.DamageFontLoader.Load();
			component2.ResetForSpawn(sizeScale);
		}

		public static void SpawnDamageText(HealthManager hm, float damage, bool isCritHit, NailElements element = 0, Color? color = null)
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if (!(damage <= 0f) && Configs.Instance.displayDamageText.Value)
			{
				float horizontalOffsetScale = Random.Range(-1f, 1f);
				float verticalOffsetScale = Random.Range(-0.4f, 0.7f);
				float num = Random.Range(1f, 1.1f) * (isCritHit ? Mathf.Clamp(damageScale(damage), 2f, 2.5f) : Mathf.Clamp(damageScale(damage), 0.5f, 1.5f));
				num *= Configs.Instance.damageFontSizeScaler.Value;
				updateAvgDamagePerHit(damage);
				GameObject val = PooledObjectService.Instance.Acquire("Assets/Addressables/Prefabs/DamageOldText.prefab", "DamageText", ((Component)WorldSpaceCanvas.GetWorldSpaceCanvas).transform);
				if (!((Object)(object)val == (Object)null))
				{
					spawnTextOn(hm, val, ((int)damage).ToString(), horizontalOffsetScale, verticalOffsetScale, num, (Color)(((??)color) ?? textColor(element, isCritHit)));
				}
			}
		}

		public static void SpawnHealText(HealthManager hm, float amount, Color? color = null)
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if (!(amount <= 0f) && Configs.Instance.displayHealText.Value)
			{
				float horizontalOffsetScale = Random.Range(-0.5f, 0.5f);
				float verticalOffsetScale = Random.Range(0f, 0.8f);
				float num = Random.Range(1.5f, 1.8f);
				num *= Configs.Instance.damageFontSizeScaler.Value;
				GameObject val = PooledObjectService.Instance.Acquire("Assets/Addressables/Prefabs/HealOldText.prefab", "HealText", ((Component)WorldSpaceCanvas.GetWorldSpaceCanvas).transform);
				if (!((Object)(object)val == (Object)null))
				{
					spawnTextOn(hm, val, $"+{(int)amount}", horizontalOffsetScale, verticalOffsetScale, num, (Color)(((??)color) ?? Configs.Instance.healTextColor.Value));
				}
			}
		}

		private static void updateAvgDamagePerHit(float damage)
		{
			if (!(damage <= 0f) && !(damage >= 9999f))
			{
				if (avgDamagePerHit <= 0f)
				{
					avgDamagePerHit = damage;
				}
				else
				{
					avgDamagePerHit = weightOfNew * damage + (1f - weightOfNew) * avgDamagePerHit;
				}
			}
		}

		private static float damageScale(float damage)
		{
			if (avgDamagePerHit <= 0f)
			{
				return 1f;
			}
			float num = damage / avgDamagePerHit;
			return 0.5f + 0.5f * Mathf.Pow(num, 0.5f);
		}

		private static Color textColor(NailElements element, bool isCritHit)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			if ((int)element != 1)
			{
				if ((int)element == 2)
				{
					return Configs.Instance.poisonColor.Value;
				}
				return isCritHit ? Configs.Instance.critHitColor.Value : Configs.Instance.defaultColor.Value;
			}
			return Configs.Instance.fireColor.Value;
		}
	}
	public abstract class ConfigFontLoaderAdapter : IFontLoader
	{
		private FontArgs cachedArgs;

		private IFontLoader fontLoader;

		private IFontLoader fallbackLoader = new SmileySansLoader();

		protected abstract FontArgs CurrentArgs { get; }

		public Font Load()
		{
			FontArgs currentArgs = CurrentArgs;
			Font val = null;
			if (cachedArgs == null || !cachedArgs.Equals(currentArgs))
			{
				fontLoader = FontLoaderFactory.CreateFontLoader(currentArgs);
				cachedArgs = currentArgs;
			}
			val = fontLoader.Load();
			if ((Object)(object)val == (Object)null)
			{
				return fallbackLoader.Load();
			}
			return val;
		}
	}
	public class DamageFontLoader : ConfigFontLoaderAdapter
	{
		protected override FontArgs CurrentArgs => Configs.Instance.damageFont.Value switch
		{
			FontOption.SmileySans => new SmileySansFontArgs(), 
			FontOption.InGameFont => new InGameFontArgs(), 
			FontOption.OSFont => new OSFontArgs(Configs.Instance.damageOsFontName.Value), 
			_ => throw new ArgumentOutOfRangeException(), 
		};
	}
	public class HpBarFontLoader : ConfigFontLoaderAdapter
	{
		protected override FontArgs CurrentArgs => Configs.Instance.hpBarFont.Value switch
		{
			FontOption.SmileySans => new SmileySansFontArgs(), 
			FontOption.InGameFont => new InGameFontArgs(), 
			FontOption.OSFont => new OSFontArgs(Configs.Instance.hpBarOsFontName.Value), 
			_ => throw new ArgumentOutOfRangeException(), 
		};
	}
	public static class FontLoaderFactory
	{
		private static IFontLoader FallbackFontLoader(FontArgs args)
		{
			return new SmileySansLoader();
		}

		public static IFontLoader CreateFontLoader(FontArgs args)
		{
			return args.FontOption switch
			{
				FontOption.SmileySans => new SmileySansLoader(), 
				FontOption.InGameFont => new GameFontLoader(), 
				FontOption.OSFont => new OSFontLoader(((OSFontArgs)args).FontName), 
				_ => FallbackFontLoader(args), 
			};
		}
	}
	public class FontManager : Singleton<FontManager>
	{
		public IFontLoader DamageFontLoader { get; private set; } = new DamageFontLoader();


		public IFontLoader HpBarFontLoader { get; private set; } = new HpBarFontLoader();

	}
	public interface IFontLoader
	{
		Font Load();
	}
	public enum FontOption
	{
		SmileySans,
		InGameFont,
		OSFont
	}
	public abstract record FontArgs(FontOption FontOption);
	public sealed record SmileySansFontArgs : FontArgs
	{
		public SmileySansFontArgs()
			: base(FontOption.SmileySans)
		{
		}
	}
	public sealed record InGameFontArgs : FontArgs
	{
		public InGameFontArgs()
			: base(FontOption.InGameFont)
		{
		}
	}
	public sealed record OSFontArgs(string FontName) : FontArgs(FontOption.OSFont);
	public abstract class CachedFontLoader : IFontLoader
	{
		protected Font cachedFont;

		protected abstract Font DoLoad();

		public Font Load()
		{
			if ((Object)(object)cachedFont == (Object)null)
			{
				cachedFont = DoLoad();
			}
			return cachedFont;
		}
	}
	public class GameFontLoader : CachedFontLoader
	{
		private string fontName = "TrajanPro-Regular";

		protected override Font DoLoad()
		{
			Font? obj = ((IEnumerable<Font>)Resources.FindObjectsOfTypeAll<Font>()).FirstOrDefault((Func<Font, bool>)((Font f) => ((Object)f).name.Contains(fontName)));
			_ = (Object)(object)obj == (Object)null;
			return obj;
		}
	}
	public class OSFontLoader : CachedFontLoader
	{
		public string FontName { get; set; }

		public OSFontLoader(string fontName)
		{
			FontName = fontName;
		}

		protected override Font DoLoad()
		{
			string[] oSInstalledFontNames = Font.GetOSInstalledFontNames();
			bool flag = false;
			string[] array = oSInstalledFontNames;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] == FontName)
				{
					flag = true;
					break;
				}
			}
			return Font.CreateDynamicFontFromOSFont(FontName, 16);
		}
	}
	public class SmileySansLoader : CachedFontLoader
	{
		protected override Font DoLoad()
		{
			AssetBundle bundle = Plugin.bundle;
			if ((Object)(object)bundle == (Object)null)
			{
				return null;
			}
			return bundle.LoadAsset<Font>("Assets/Addressables/Fonts/SmileySans-Oblique.ttf");
		}
	}
	public abstract class BaseHealthBarController<EventType, OwnerType> : MonoBehaviour where OwnerType : MonoBehaviour, IHealthBarOwner
	{
		protected Dictionary<GameObject, HealthBar> healthBarOf = new Dictionary<GameObject, HealthBar>();

		protected LinkBuffer linkBuffer;

		public abstract GameObject GetNewHealthBar { get; }

		public abstract Canvas BarCanvas { get; }

		protected void RegisterEventHandlers()
		{
			EventHandle<EventType>.Register<GameObject, float>(HealthBarOwnerEventType.Spawn, OnEnemySpawn);
			EventHandle<EventType>.Register<GameObject, GameObject>(HealthBarOwnerEventType.Link, LinkEnemy);
			EventHandle<EventType>.Register<GameObject>(HealthBarOwnerEventType.Die, OnEnemyDie);
			EventHandle<EventType>.Register<GameObject, float>(HealthBarOwnerEventType.Heal, OnEnemyHeal);
			EventHandle<EventType>.Register<GameObject, float>(HealthBarOwnerEventType.Damage, OnEnemyDamage);
			EventHandle<EventType>.Register<GameObject>(HealthBarOwnerEventType.Hide, OnEnemyHide);
			EventHandle<EventType>.Register<GameObject>(HealthBarOwnerEventType.Show, OnEnemyShow);
			EventHandle<EventType>.Register<GameObject, float>(HealthBarOwnerEventType.SetHP, OnEnemySetHP);
			EventHandle<EventType>.Register(HealthBarOwnerEventType.CheckHP, delegate(GameObject go)
			{
				OnCheckHP(go);
			});
		}

		protected virtual void Awake()
		{
			RegisterEventHandlers();
			linkBuffer = new LinkBuffer(TryLinkEnemy);
			((MonoBehaviour)this).InvokeRepeating("MatchVisualsWithConfigs", 0f, 1f);
		}

		protected void OnCheckHP(GameObject enemyGO, bool fixMismatch = false)
		{
			float num = 0f;
			HealthManager component = enemyGO.GetComponent<HealthManager>();
			num = ((!((Object)(object)component.SendDamageTo != (Object)null)) ? ((float)component.hp) : ((float)component.SendDamageTo.hp));
			if (!guardExist(enemyGO))
			{
				return;
			}
			HealthBar healthBar = healthBarOf[enemyGO];
			if (!(Mathf.Abs(healthBar.CurrentHealth - num) > 0.01f))
			{
				return;
			}
			float num2 = healthBar.CurrentHealth - num;
			if (fixMismatch)
			{
				if (num2 > 0f)
				{
					healthBar.TakeDamage(num2);
				}
				else
				{
					healthBar.Heal(0f - num2);
				}
			}
		}

		protected bool guardExist(GameObject enemyGO)
		{
			if (!healthBarOf.ContainsKey(enemyGO))
			{
				return false;
			}
			return true;
		}

		public GameObject GetRandomEnemyGO()
		{
			foreach (KeyValuePair<GameObject, HealthBar> item in healthBarOf)
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					return item.Key.gameObject;
				}
			}
			return null;
		}

		protected virtual void OnEnemyShow(GameObject enemyGO)
		{
			if (guardExist(enemyGO))
			{
				healthBarOf[enemyGO].SetVisibility(visible: true);
			}
		}

		protected abstract float BarWidth(float maxHp);

		protected bool TryLinkEnemy(GameObject originGO, GameObject relayGO)
		{
			if (!guardExist(originGO))
			{
				return false;
			}
			if (healthBarOf.ContainsKey(relayGO))
			{
				GameObject gameObject = ((Component)healthBarOf[relayGO]).gameObject;
				PooledObjectService.Instance.Release(gameObject);
			}
			healthBarOf[relayGO] = healthBarOf[originGO];
			IHealthBarOwner healthBarOwner = default(IHealthBarOwner);
			if (relayGO.TryGetComponent<IHealthBarOwner>(ref healthBarOwner))
			{
				healthBarOwner.RemoveVisibilityController();
			}
			IHealthBarOwner healthBarOwner2 = default(IHealthBarOwner);
			if (originGO.TryGetComponent<IHealthBarOwner>(ref healthBarOwner2))
			{
				healthBarOwner2.LinkVisibilityControl(relayGO);
			}
			return true;
		}

		protected void LinkEnemy(GameObject sourceGO, GameObject withGO)
		{
			if (!Object.op_Implicit((Object)(object)withGO.GetComponent<OwnerType>()))
			{
				withGO.AddComponent<OwnerType>().RemoveVisibilityController();
			}
			linkBuffer.RegisterRelay(sourceGO, withGO);
		}

		protected void MatchVisualsWithConfigs(HealthBar bar)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)bar))
			{
				bar.SetHpColor(Configs.Instance.hpColor.Value);
				bar.SetDelayedEffectColor(Configs.Instance.delayedEffectColor.Value);
				bar.SetBackgroundColor(Configs.Instance.hpBarBackgroundColor.Value);
				bar.SetWidth(BarWidth(bar.MaxHealth));
				UIHealthBar component = ((Component)bar).GetComponent<UIHealthBar>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetHpTextEnabled(Configs.Instance.displayHpNumbers.Value);
					component.SetHpTextColor(Configs.Instance.hpNumberColor.Value);
					component.SetFont(Singleton<FontManager>.instance.HpBarFontLoader.Load());
					component.SetNameScale(Configs.Instance.bossNameFontSizeScaler.Value);
					component.SetHpNumberScale(Configs.Instance.hpNumberFontSizeScaler.Value);
				}
			}
		}

		protected virtual void MatchVisualsWithConfigs()
		{
			foreach (KeyValuePair<GameObject, HealthBar> item in healthBarOf)
			{
				MatchVisualsWithConfigs(item.Value);
			}
		}

		protected virtual void OnEnemySpawn(GameObject enemyGO, float maxHp)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (healthBarOf.ContainsKey(enemyGO))
			{
				HealthBar healthBar = healthBarOf[enemyGO];
				healthBar.SetMaxHealth(maxHp);
				return;
			}
			GameObject getNewHealthBar = GetNewHealthBar;
			((Object)getNewHealthBar).name = "HealthBar_" + ((Object)enemyGO).name;
			if (!((Object)(object)getNewHealthBar == (Object)null))
			{
				getNewHealthBar.transform.SetParent(((Component)BarCanvas).transform);
				getNewHealthBar.transform.localScale = Vector3.one;
				HealthBar healthBar = getNewHealthBar.GetComponent<HealthBar>();
				healthBar.SetMaxHealth(maxHp);
				MatchVisualsWithConfigs(healthBar);
				healthBarOf[enemyGO] = healthBar;
				if (!Object.op_Implicit((Object)(object)enemyGO.GetComponent<OwnerType>()))
				{
					enemyGO.AddComponent<OwnerType>();
				}
				ApplySpecialPatches(enemyGO);
				linkBuffer.RegisterOrigin(enemyGO);
			}
		}

		protected void ApplySpecialPatches(GameObject enemyGO)
		{
			if (DeathWatcher.IngameGameObjectNames.Contains(((Object)enemyGO).name.ToLower()) && !Object.op_Implicit((Object)(object)enemyGO.GetComponent<DeathWatcher>()))
			{
				enemyGO.AddComponent<DeathWatcher>().Init(enemyGO);
			}
			if (!Object.op_Implicit((Object)(object)enemyGO.GetComponent<InitHpWatcher>()))
			{
				enemyGO.AddComponent<InitHpWatcher>();
			}
		}

		protected void OnEnemyDamage(GameObject enemyGO, float amount)
		{
			if (guardExist(enemyGO))
			{
				healthBarOf[enemyGO].TakeDamage(amount);
				OnCheckHP(enemyGO);
			}
		}

		protected void OnEnemyHeal(GameObject enemyGO, float amount)
		{
			if (guardExist(enemyGO))
			{
				healthBarOf[enemyGO].Heal(amount);
				OnCheckHP(enemyGO);
			}
		}

		protected virtual void OnEnemyHide(GameObject enemyGO)
		{
			if (guardExist(enemyGO))
			{
				healthBarOf[enemyGO].SetVisibility(visible: false);
			}
		}

		protected virtual void OnEnemyDie(GameObject enemyGO)
		{
			if (guardExist(enemyGO))
			{
				HealthBar healthBar = healthBarOf[enemyGO];
				PooledObjectService.Instance.Release(((Component)healthBar).gameObject);
				healthBarOf.Remove(enemyGO);
			}
		}

		protected void OnEnemySetHP(GameObject enemyGO, float hp)
		{
			if (guardExist(enemyGO))
			{
				healthBarOf[enemyGO].ResetHealth(hp);
				OnCheckHP(enemyGO, fixMismatch: true);
			}
		}
	}
	public class BaseHealthBarOwner<EventType> : MonoBehaviour, IHealthBarOwner
	{
		private IVisibilityController visibilityController;

		public Dispatcher Dispatcher { get; private set; }

		private void Awake()
		{
			HealthManager component = ((Component)this).GetComponent<HealthManager>();
			visibilityController = new VisibilityController(component);
			Dispatcher = new Dispatcher(this);
		}

		private void Update()
		{
			if (visibilityController != null)
			{
				if (!visibilityController.Update())
				{
					return;
				}
				CheckHP();
				if (visibilityController.IsVisible)
				{
					Show();
				}
				else
				{
					Hide();
				}
			}
			((Component)this).GetComponent<HealthManager>();
		}

		private void OnDisable()
		{
			updateVisibilityImmediate();
		}

		private void OnEnable()
		{
			updateVisibilityImmediate();
		}

		private void OnDestroy()
		{
			Die();
		}

		private void updateVisibilityImmediate()
		{
			if (visibilityController != null && visibilityController.Update(forceCheck: true))
			{
				if (visibilityController.IsVisible)
				{
					Show();
				}
				else
				{
					Hide();
				}
			}
		}

		public void Heal(float amount)
		{
			EventHandle<EventType>.SendEvent<GameObject, float>(HealthBarOwnerEventType.Heal, ((Component)this).gameObject, amount);
			updateVisibilityImmediate();
		}

		public void TakeDamage(float amount)
		{
			updateVisibilityImmediate();
			EventHandle<EventType>.SendEvent<GameObject, float>(HealthBarOwnerEventType.Damage, ((Component)this).gameObject, amount);
			updateVisibilityImmediate();
		}

		public void Die()
		{
			EventHandle<EventType>.SendEvent<GameObject>(HealthBarOwnerEventType.Die, ((Component)this).gameObject);
			updateVisibilityImmediate();
		}

		public void Hide()
		{
			EventHandle<EventType>.SendEvent<GameObject>(HealthBarOwnerEventType.Hide, ((Component)this).gameObject);
		}

		public void Show()
		{
			EventHandle<EventType>.SendEvent<GameObject>(HealthBarOwnerEventType.Show, ((Component)this).gameObject);
		}

		public void SetHP(float hp)
		{
			EventHandle<EventType>.SendEvent<GameObject, float>(HealthBarOwnerEventType.SetHP, ((Component)this).gameObject, hp);
			updateVisibilityImmediate();
		}

		public void CheckHP()
		{
			EventHandle<EventType>.SendEvent<GameObject>(HealthBarOwnerEventType.CheckHP, ((Component)this).gameObject);
		}

		public void RemoveVisibilityController()
		{
			visibilityController = null;
		}

		public void LinkVisibilityControl(GameObject go)
		{
			if (visibilityController == null || visibilityController is VisibilityController)
			{
				visibilityController = new LinkedVisibilityController();
				visibilityController.Inspect(((Component)this).GetComponent<HealthManager>());
			}
			HealthManager healthManager = default(HealthManager);
			if (go.TryGetComponent<HealthManager>(ref healthManager))
			{
				visibilityController.Inspect(healthManager);
			}
		}
	}
	public static class BossResolver
	{
		public static bool IsBoss(HealthManager healthManager)
		{
			DisplayBossTitle bossTitleAction = GetBossTitleAction(((Component)healthManager).gameObject);
			if (bossTitleAction == null)
			{
				Transform parent = ((Component)healthManager).gameObject.transform.parent;
				bossTitleAction = GetBossTitleAction((parent != null) ? ((Component)parent).gameObject : null, searchInChildren: true);
			}
			return bossTitleAction != null;
		}

		public static string BossName(HealthManager healthManager)
		{
			string text = null;
			if (((Object)((Component)healthManager).gameObject).name == "Dock Guard Thrower")
			{
				text = "DOCK_GUARD_DUO";
			}
			else
			{
				DisplayBossTitle bossTitleAction = GetBossTitleAction(((Component)healthManager).gameObject);
				if (bossTitleAction == null)
				{
					Transform parent = ((Component)healthManager).gameObject.transform.parent;
					bossTitleAction = GetBossTitleAction((parent != null) ? ((Component)parent).gameObject : null, searchInChildren: true);
				}
				text = ((bossTitleAction != null) ? bossTitleAction.bossTitle.Value : null);
			}
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			return LocalizedDisplayName(text);
		}

		private static string Localized(string titleKey)
		{
			string text = "Titles";
			string text2 = Language.Get(titleKey, text);
			if (text2.StartsWith("#"))
			{
				return null;
			}
			if (string.IsNullOrEmpty(text2))
			{
				return null;
			}
			return text2;
		}

		private static string LocalizedDisplayName(string titleKey)
		{
			string text;
			if (titleKey == "DOCK_GUARD_DUO")
			{
				text = Localized(titleKey + "_MAIN").Split("&").Last().Trim();
				text = Localized(titleKey + "_SUPER") + text;
			}
			else
			{
				text = Localized(titleKey + "_SUPER") + Localized(titleKey + "_MAIN") + Localized(titleKey + "_SUB");
			}
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			return text;
		}

		private static DisplayBossTitle GetBossTitleAction(GameObject gameObject, bool searchInChildren = false)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return null;
			}
			PlayMakerFSM[] array = (searchInChildren ? gameObject.GetComponentsInChildren<PlayMakerFSM>() : gameObject.GetComponents<PlayMakerFSM>());
			for (int i = 0; i < array.Length; i++)
			{
				FsmState[] fsmStates = array[i].FsmStates;
				for (int j = 0; j < fsmStates.Length; j++)
				{
					FsmStateAction[] actions = fsmStates[j].Actions;
					foreach (FsmStateAction val in actions)
					{
						if (val is DisplayBossTitle)
						{
							return (DisplayBossTitle)(object)((val is DisplayBossTitle) ? val : null);
						}
					}
				}
			}
			return null;
		}
	}
	public class BossHealthBarController : BaseHealthBarController<BossOwnerEvent, BossHealthBarOwner>
	{
		private BossHealthBarContainer container;

		protected string containerPrefabPath = "Assets/Addressables/Prefabs/Container.prefab";

		protected string healthBarPrefabPath => AssetPaths.HealthBars.ForBossShape(Configs.Instance.healthBarShape.Value);

		public override GameObject GetNewHealthBar => PooledObjectService.Instance.Acquire(healthBarPrefabPath, "BossHealthBar", ((Component)BarCanvas).transform);

		public override Canvas BarCanvas => ScreenSpaceCanvas.GetScreenSpaceCanvas;

		private void UpdateContainerWidth()
		{
			float value = Configs.Instance.bossBarWidth.Value;
			container.SetWidth(value);
		}

		private void prepareContainer()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Plugin.InstantiateFromAssetsBundle(containerPrefabPath, "BossHealthBarContainer");
			container = val.GetComponent<BossHealthBarContainer>();
			((Component)container).transform.SetParent(((Component)ScreenSpaceCanvas.GetScreenSpaceCanvas).transform);
			RectTransform component = ((Component)container).GetComponent<RectTransform>();
			component.anchoredPosition = new Vector2(0f, 1.3f);
			component.sizeDelta = new Vector2(Configs.Instance.bossBarWidth.Value, component.sizeDelta.y);
			Image component2 = ((Component)container).GetComponent<Image>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				((Graphic)component2).color = new Color(1f, 1f, 1f, 0f);
			}
		}

		protected override void Awake()
		{
			base.Awake();
			prepareContainer();
		}

		protected override void MatchVisualsWithConfigs()
		{
			base.MatchVisualsWithConfigs();
			UpdateContainerWidth();
		}

		protected override void OnEnemyShow(GameObject enemyGO)
		{
			if (guardExist(enemyGO))
			{
				base.OnEnemyShow(enemyGO);
				HealthBar bar = healthBarOf[enemyGO];
				container.AddBar(bar);
			}
		}

		protected override void OnEnemySpawn(GameObject bossGO, float maxHp)
		{
			base.OnEnemySpawn(bossGO, maxHp);
			UIHealthBar component = ((Component)healthBarOf[bossGO]).GetComponent<UIHealthBar>();
			if (Object.op_Implicit((Object)(object)component))
			{
				string nameText = HealthManagerPatch.LocalisedName(bossGO.GetComponent<HealthManager>());
				component.SetNameText(nameText);
			}
		}

		protected override void OnEnemyHide(GameObject bossGO)
		{
			if (guardExist(bossGO))
			{
				base.OnEnemyHide(bossGO);
				HealthBar bar = healthBarOf[bossGO];
				container.RemoveBar(bar);
			}
		}

		protected override void OnEnemyDie(GameObject bossGO)
		{
			if (guardExist(bossGO))
			{
				HealthBar bar = healthBarOf[bossGO];
				container.RemoveBar(bar);
				base.OnEnemyDie(bossGO);
			}
		}

		protected override float BarWidth(float maxHp)
		{
			return Configs.Instance.bossBarWidth.Value;
		}
	}
	public class BossHealthBarOwner : BaseHealthBarOwner<BossOwnerEvent>
	{
	}
	public class HealthBarEventArgs
	{
		public HealthBarOwnerEventType type { get; protected set; }

		public HealthBarEventArgs(HealthBarOwnerEventType type)
		{
			this.type = type;
		}
	}
	public class HealEventArgs : HealthBarEventArgs
	{
		public float amount;

		public HealEventArgs(float amount = 0f)
			: base(HealthBarOwnerEventType.Heal)
		{
			this.amount = amount;
		}
	}
	public class SetHpEventArgs : HealthBarEventArgs
	{
		public float amount;

		public SetHpEventArgs(float amount = 0f)
			: base(HealthBarOwnerEventType.SetHP)
		{
			this.amount = amount;
		}
	}
	public class DamageEventArgs : HealthBarEventArgs
	{
		public float amount;

		public DamageEventArgs(float amount = 0f)
			: base(HealthBarOwnerEventType.Damage)
		{
			this.amount = amount;
		}
	}
	public class Dispatcher
	{
		private class EventEntry
		{
			public HealthBarEventArgs args;

			public bool ready;

			public EventEntry(HealthBarEventArgs args)
			{
				this.args = args;
			}
		}

		private LinkedList<EventEntry> queue = new LinkedList<EventEntry>();

		private Dictionary<HealthBarOwnerEventType, Action<HealthBarEventArgs>> handlers = new Dictionary<HealthBarOwnerEventType, Action<HealthBarEventArgs>>();

		private int counter;

		private Dictionary<int, EventEntry> pendingEntries = new Dictionary<int, EventEntry>();

		private void Dispatch()
		{
			while (queue.Count > 0)
			{
				EventEntry value = queue.First.Value;
				if (value.ready)
				{
					if (handlers.TryGetValue(value.args.type, out var value2))
					{
						value2(value.args);
					}
					queue.RemoveFirst();
					continue;
				}
				break;
			}
		}

		public Dispatcher(IHealthBarOwner owner)
		{
			handlers[HealthBarOwnerEventType.Heal] = delegate(HealthBarEventArgs evt)
			{
				owner.Heal(((HealEventArgs)evt).amount);
			};
			handlers[HealthBarOwnerEventType.SetHP] = delegate(HealthBarEventArgs evt)
			{
				owner.SetHP(((SetHpEventArgs)evt).amount);
			};
			handlers[HealthBarOwnerEventType.Damage] = delegate(HealthBarEventArgs evt)
			{
				owner.TakeDamage(((DamageEventArgs)evt).amount);
			};
		}

		public int Enqueue<T>() where T : HealthBarEventArgs
		{
			EventEntry eventEntry = new EventEntry(null);
			queue.AddLast(eventEntry);
			eventEntry.ready = false;
			pendingEntries[counter] = eventEntry;
			return counter++;
		}

		public void EnqueueReady<T>(T args) where T : HealthBarEventArgs
		{
			EventEntry eventEntry = new EventEntry(args);
			eventEntry.ready = true;
			queue.AddLast(eventEntry);
			Dispatch();
		}

		public void Submit<T>(int id, T args) where T : HealthBarEventArgs
		{
			if (pendingEntries.TryGetValue(id, out var value))
			{
				value.ready = true;
				value.args = args;
				pendingEntries.Remove(id);
				Dispatch();
			}
		}

		public void Cancel(int id)
		{
			if (pendingEntries.TryGetValue(id, out var value))
			{
				queue.Remove(value);
				pendingEntries.Remove(id);
				Dispatch();
			}
		}
	}
	public static class EventHandle<E>
	{
		private static readonly Dictionary<HealthBarOwnerEventType, Delegate> affairDict = new Dictionary<HealthBarOwnerEventType, Delegate>();

		private static void beforeAdd(HealthBarOwnerEventType eventType, Delegate handler)
		{
			affairDict.TryAdd(eventType, null);
			Delegate @delegate = affairDict[eventType];
			if ((object)@delegate != null && @delegate.GetType() != handler.GetType())
			{
				throw new Exception($"Handler type mismatch for event '{eventType}'. Expected: {@delegate.GetType().Name}, Actual: {handler.GetType().Name}");
			}
		}

		public static void Register(HealthBarOwnerEventType eventType, Action handler)
		{
			beforeAdd(eventType, handler);
			affairDict[eventType] = Delegate.Combine(affairDict[eventType], handler);
		}

		public static void Register<T>(HealthBarOwnerEventType eventType, Action<T> handler)
		{
			beforeAdd(eventType, handler);
			affairDict[eventType] = Delegate.Combine(affairDict[eventType], handler);
		}

		public static void Register<T1, T2>(HealthBarOwnerEventType eventType, Action<T1, T2> handler)
		{
			beforeAdd(eventType, handler);
			affairDict[eventType] = Delegate.Combine(affairDict[eventType], handler);
		}

		public static void Deregister(HealthBarOwnerEventType eventType, Action handler)
		{
			if (affairDict.TryGetValue(eventType, out var value))
			{
				affairDict[eventType] = Delegate.Remove(value, handler);
			}
		}

		public static void Deregister<T>(HealthBarOwnerEventType eventType, Action<T> handler)
		{
			if (affairDict.TryGetValue(eventType, out var value))
			{
				affairDict[eventType] = Delegate.Remove(value, handler);
			}
		}

		public static void Deregister<T1, T2>(HealthBarOwnerEventType eventType, Action<T1, T2> handler)
		{
			if (affairDict.TryGetValue(eventType, out var value))
			{
				affairDict[eventType] = Delegate.Remove(value, handler);
			}
		}

		public static void SendEvent(HealthBarOwnerEventType type)
		{
			if (affairDict.TryGetValue(type, out var value))
			{
				if (!(value is Action action))
				{
					throw new Exception($"Handler type mismatch when sending event '{type}'. Expected: {value.GetType().Name}, Actual: Action");
				}
				action();
			}
		}

		public static void SendEvent<T>(HealthBarOwnerEventType type, T args)
		{
			if (affairDict.TryGetValue(type, out var value))
			{
				if (!(value is Action<T> action))
				{
					throw new Exception($"Handler type mismatch when sending event '{type}'. Expected: {value.GetType().Name}, Actual: Action<{typeof(T).Name}>");
				}
				action(args);
			}
		}

		public static void SendEvent<T1, T2>(HealthBarOwnerEventType type, T1 arg1, T2 arg2)
		{
			if (affairDict.TryGetValue(type, out var value))
			{
				if (!(value is Action<T1, T2> action))
				{
					throw new Exception($"Handler type mismatch when sending event '{type}'. Expected: {value.GetType().Name}, Actual: Action<{typeof(T1).Name}, {typeof(T2).Name}>");
				}
				action(arg1, arg2);
			}
		}
	}
	public enum HealthBarOwnerEventType
	{
		Spawn,
		Link,
		Show,
		Hide,
		Die,
		Damage,
		Heal,
		SetHP,
		CheckHP
	}
	public class BossOwnerEvent
	{
		public HealthBarOwnerEventType EventType;
	}
	public class MobOwnerEvent
	{
		public HealthBarOwnerEventType eventType;
	}
	public interface IHealthBarOwner
	{
		Dispatcher Dispatcher { get; }

		void Heal(float amount);

		void TakeDamage(float amount);

		void SetHP(float hp);

		void Die();

		void Hide();

		void Show();

		void CheckHP();

		void RemoveVisibilityController();

		void LinkVisibilityControl(GameObject go);
	}
	public static class JournalRecordResolver
	{
		public static string ResolveLocalizedEnemyName(HealthManager healthManager)
		{
			if ((Object)(object)healthManager == (Object)null)
			{
				return null;
			}
			string text = ResolveFromDeathEffect(healthManager);
			if (text != null)
			{
				return text;
			}
			string text2 = ResolveFromFsm(healthManager);
			if (text2 != null)
			{
				return text2;
			}
			return FallBack(healthManager);
		}

		private static string ResolveFromDeathEffect(HealthManager healthManager)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			EnemyDeathEffects component = ((Component)healthManager).gameObject.GetComponent<EnemyDeathEffects>();
			if ((Object)(object)component != (Object)null)
			{
				EnemyJournalRecord value = Traverse.Create((object)component).Field<EnemyJournalRecord>("journalRecord").Value;
				if (Object.op_Implicit((Object)(object)value))
				{
					return LocalisedString.op_Implicit(value.DisplayName);
				}
			}
			return null;
		}

		private static string ResolveFromFsm(HealthManager healthManager)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			PlayMakerFSM[] components = ((Component)healthManager).gameObject.GetComponents<PlayMakerFSM>();
			for (int i = 0; i < components.Length; i++)
			{
				FsmState[] fsmStates = components[i].FsmStates;
				for (int j = 0; j < fsmStates.Length; j++)
				{
					FsmStateAction[] actions = fsmStates[j].Actions;
					foreach (FsmStateAction val in actions)
					{
						if (val is RecordJournalKill)
						{
							Object value = ((RecordJournalKill)((val is RecordJournalKill) ? val : null)).Record.Value;
							EnemyJournalRecord val2 = (EnemyJournalRecord)(object)((value is EnemyJournalRecord) ? value : null);
							if (Object.op_Implicit((Object)(object)val2))
							{
								return LocalisedString.op_Implicit(val2.DisplayName);
							}
						}
					}
				}
			}
			return null;
		}

		private static string FallBack(HealthManager healthManager)
		{
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			List<EnemyJournalRecord> allEnemies = EnemyJournalManager.GetAllEnemies();
			string text = ((Object)((Component)healthManager).gameObject).name;
			if (text.EndsWith("NPC"))
			{
				text = "Shakra";
			}
			string[] array = text.Split(new char[5] { ' ', '(', ')', '_', '-' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (EnemyJournalRecord item in allEnemies)
			{
				if ((Object)(object)item == (Object)null || string.IsNullOrEmpty(((Object)item).name))
				{
					continue;
				}
				string[] array2 = ((Object)item).name.Split(new char[5] { ' ', '(', ')', '_', '-' }, StringSplitOptions.RemoveEmptyEntries);
				int num = 0;
				string[] array3 = array;
				foreach (string text2 in array3)
				{
					if (string.IsNullOrEmpty(text2) || text2.Length < 2)
					{
						continue;
					}
					string[] array4 = array2;
					foreach (string text3 in array4)
					{
						if (!string.IsNullOrEmpty(text3) && text3.Length >= 2 && string.Equals(text2, text3, StringComparison.OrdinalIgnoreCase))
						{
							num++;
							break;
						}
					}
				}
				if (num >= 2 && !string.IsNullOrEmpty(LocalisedString.op_Implicit(item.DisplayName)))
				{
					return LocalisedString.op_Implicit(item.DisplayName);
				}
			}
			foreach (EnemyJournalRecord item2 in allEnemies)
			{
				if ((Object)(object)item2 == (Object)null || string.IsNullOrEmpty(((Object)item2).name))
				{
					continue;
				}
				string[] array5 = ((Object)item2).name.Split(new char[5] { ' ', '(', ')', '_', '-' }, StringSplitOptions.RemoveEmptyEntries);
				string[] array3 = array;
				foreach (string text4 in array3)
				{
					if (string.IsNullOrEmpty(text4) || text4.Length < 3)
					{
						continue;
					}
					string[] array4 = array5;
					foreach (string text5 in array4)
					{
						if (!string.IsNullOrEmpty(text5) && text5.Length >= 3 && string.Equals(text4, text5, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(LocalisedString.op_Implicit(item2.DisplayName)))
						{
							return LocalisedString.op_Implicit(item2.DisplayName);
						}
					}
				}
			}
			return CleanGameObjectName(((Object)((Component)healthManager).gameObject).name);
			static string CleanGameObjectName(string originalName)
			{
				if (string.IsNullOrEmpty(originalName))
				{
					return "未知Boss";
				}
				int num2 = originalName.IndexOf('(');
				if (num2 >= 0)
				{
					originalName = originalName.Substring(0, num2).Trim();
				}
				string[] array6 = new string[4] { " Clone", "(Clone)", " Instance", "(Instance)" };
				foreach (string text6 in array6)
				{
					if (originalName.EndsWith(text6))
					{
						originalName = originalName.Substring(0, originalName.Length - text6.Length).Trim();
					}
				}
				if (!string.IsNullOrEmpty(originalName))
				{
					return originalName;
				}
				return "未知Boss";
			}
		}
	}
	public class LinkBuffer
	{
		private Dictionary<GameObject, Queue<GameObject>> relaysOfOrigin = new Dictionary<GameObject, Queue<GameObject>>();

		private Func<GameObject, GameObject, bool> TryLink;

		public LinkBuffer(Func<GameObject, GameObject, bool> tryLinkFunc)
		{
			TryLink = tryLinkFunc;
		}

		private void WaitForLink(GameObject origin, GameObject relay)
		{
			if (!relaysOfOrigin.ContainsKey(origin))
			{
				relaysOfOrigin[origin] = new Queue<GameObject>();
			}
			relaysOfOrigin[origin].Enqueue(relay);
		}

		public void RegisterRelay(GameObject origin, GameObject relay)
		{
			if (!TryLink(origin, relay))
			{
				WaitForLink(origin, relay);
			}
		}

		public void RegisterOrigin(GameObject origin)
		{
			if (relaysOfOrigin.ContainsKey(origin))
			{
				Queue<GameObject> queue = relaysOfOrigin[origin];
				while (queue.Count > 0)
				{
					GameObject arg = queue.Dequeue();
					TryLink(origin, arg);
				}
				relaysOfOrigin.Remove(origin);
			}
		}
	}
	public class MobHealthBarController : BaseHealthBarController<MobOwnerEvent, MobHealthBarOwner>
	{
		private string prefabPath => AssetPaths.HealthBars.ForMobShape(Configs.Instance.healthBarShape.Value);

		public override GameObject GetNewHealthBar => PooledObjectService.Instance.Acquire(prefabPath, "MobHealthBar", ((Component)BarCanvas).transform);

		public override Canvas BarCanvas => WorldSpaceCanvas.GetWorldSpaceCanvas;

		protected override float BarWidth(float maxHp)
		{
			return Configs.Instance.GetHpBarWidth(maxHp, isBoss: false);
		}

		protected override void OnEnemySpawn(GameObject enemyGO, float maxHp)
		{
			base.OnEnemySpawn(enemyGO, maxHp);
			GameObject gameObject = ((Component)healthBarOf[enemyGO]).gameObject;
			SpriteTracker spriteTracker = default(SpriteTracker);
			if (!gameObject.TryGetComponent<SpriteTracker>(ref spriteTracker))
			{
				spriteTracker = gameObject.AddComponent<SpriteTracker>();
			}
			spriteTracker.SetTarget(enemyGO);
			spriteTracker.zOffset = Configs.Instance.spriteTrackerZOffset.Value;
		}
	}
	public class MobHealthBarOwner : BaseHealthBarOwner<MobOwnerEvent>
	{
	}
	public class SpawnManager : Singleton<SpawnManager>
	{
		public bool IsBoss(HealthManager hm, float? overrideHp = null)
		{
			if ((overrideHp ?? ((float)hm.hp)) >= Configs.Instance.minBossBarHp.Value)
			{
				return true;
			}
			return false;
		}

		private void DoLink(HealthManager origin, HealthManager relay)
		{
			float? overrideHpIfAny = LinkPolicy.Instance.GetOverrideHpIfAny(origin);
			if (IsBoss(origin, overrideHpIfAny))
			{
				if (Configs.Instance.displayBossHpBar.Value)
				{
					EventHandle<BossOwnerEvent>.SendEvent<GameObject, GameObject>(HealthBarOwnerEventType.Link, ((Component)origin).gameObject, ((Component)relay).gameObject);
				}
			}
			else if (Configs.Instance.displayMobHpBar.Value)
			{
				EventHandle<MobOwnerEvent>.SendEvent<GameObject, GameObject>(HealthBarOwnerEventType.Link, ((Component)origin).gameObject, ((Component)relay).gameObject);
			}
		}

		private void DoSpawnHealthBar(HealthManager hm, float? overrideHp = null)
		{
			float arg = overrideHp ?? ((float)hm.hp);
			if (IsBoss(hm, overrideHp))
			{
				if (Configs.Instance.displayBossHpBar.Value)
				{
					EventHandle<BossOwnerEvent>.SendEvent<GameObject, float>(HealthBarOwnerEventType.Spawn, ((Component)hm).gameObject, arg);
					EventHandle<BossOwnerEvent>.SendEvent<GameObject>(HealthBarOwnerEventType.Hide, ((Component)hm).gameObject);
				}
			}
			else if (Configs.Instance.displayMobHpBar.Value)
			{
				EventHandle<MobOwnerEvent>.SendEvent<GameObject, float>(HealthBarOwnerEventType.Spawn, ((Component)hm).gameObject, arg);
				EventHandle<MobOwnerEvent>.SendEvent<GameObject>(HealthBarOwnerEventType.Hide, ((Component)hm).gameObject);
			}
		}

		public void SpawnHealthBar(HealthManager hm)
		{
			if (LinkPolicy.Instance.TryGetOriginHealthManager(hm, out var originHm))
			{
				if (!((Object)(object)originHm == (Object)null))
				{
					DoLink(originHm, hm);
				}
			}
			else
			{
				float? overrideHpIfAny = LinkPolicy.Instance.GetOverrideHpIfAny(hm);
				DoSpawnHealthBar(hm, overrideHpIfAny);
			}
		}
	}
	internal class DeathWatcher : MonoBehaviour
	{
		public static HashSet<string> IngameGameObjectNames = new HashSet<string> { "garmond fighter" };

		private HealthManager hm;

		private IHealthBarOwner hpBarOwner;

		private void Start()
		{
			float value = Configs.Instance.visibleCacheSeconds.Value;
			((MonoBehaviour)this).InvokeRepeating("CheckHealth", 0f, value);
		}

		private void CheckHealth()
		{
			if (Object.op_Implicit((Object)(object)hm) && hm.hp <= 0)
			{
				hpBarOwner?.Die();
				((MonoBehaviour)this).CancelInvoke("CheckHealth");
				Object.Destroy((Object)(object)this);
			}
		}

		internal void Init(GameObject enemyGO)
		{
			hm = enemyGO.GetComponent<HealthManager>();
			hpBarOwner = enemyGO.GetComponent<IHealthBarOwner>();
		}
	}
	internal class InitHpWatcher : MonoBehaviour
	{
		private int? previousInitHp;

		private Traverse<int> initHpGetter;

		private IHealthBarOwner owner;

		private HealthManager hm;

		private void Awake()
		{
			hm = ((Component)this).GetComponent<HealthManager>();
			owner = ((Component)this).GetComponent<IHealthBarOwner>();
			if (!((Object)(object)hm == (Object)null) && owner != null)
			{
				initHpGetter = Traverse.Create((object)hm).Field<int>("initHp");
				previousInitHp = initHpGetter.Value;
			}
		}

		private void Update()
		{
			MonitorInitHp();
		}

		private void MonitorInitHp()
		{
			if ((Object)(object)hm == (Object)null || owner == null || initHpGetter == null)
			{
				return;
			}
			if (!previousInitHp.HasValue)
			{
				previousInitHp = initHpGetter.Value;
				return;
			}
			int value = initHpGetter.Value;
			if (value != previousInitHp)
			{
				owner.SetHP(value);
				previousInitHp = value;
			}
		}
	}
	public class LinkPolicy
	{
		private enum EndpointType
		{
			RelayEndpoint,
			OriginEndpoint
		}

		private class Endpoint
		{
			internal string gameObjectName;

			internal EndpointType type;

			internal float? overrideOriginHp;

			private Func<HealthManager> findHealthManager;

			internal static Endpoint RelayEndpoint(string name)
			{
				return new Endpoint
				{
					gameObjectName = name,
					type = EndpointType.RelayEndpoint,
					overrideOriginHp = null
				};
			}

			internal Endpoint SetHealthManagerFinder(Func<HealthManager> finder)
			{
				findHealthManager = finder;
				return this;
			}

			internal HealthManager FindHealthManager()
			{
				if (findHealthManager == null)
				{
					return null;
				}
				return findHealthManager();
			}

			internal static Endpoint OriginEndpoint(string name, float? overrideHp = null)
			{
				return new Endpoint
				{
					gameObjectName = name,
					type = EndpointType.OriginEndpoint,
					overrideOriginHp = overrideHp
				};
			}
		}

		private static LinkPolicy __instance;

		private Dictionary<string, Endpoint> endpointOfName;

		private Dictionary<Endpoint, Endpoint> originOfRelayEndpoint = new Dictionary<Endpoint, Endpoint> { 
		{
			Endpoint.RelayEndpoint("Giant Centipede Butt"),
			Endpoint.OriginEndpoint("Giant Centipede Head", 800f).SetHealthManagerFinder(delegate
			{
				GameObject obj = GameObject.Find("Giant Centipede Head");
				return (obj == null) ? null : obj.GetComponent<HealthManager>();
			})
		} };

		public static LinkPolicy Instance
		{
			get
			{
				if (__instance == null)
				{
					__instance = new LinkPolicy();
					__instance.endpointOfName = new Dictionary<string, Endpoint>();
					foreach (KeyValuePair<Endpoint, Endpoint> item in __instance.originOfRelayEndpoint)
					{
						__instance.endpointOfName[item.Key.gameObjectName] = item.Key;
						__instance.endpointOfName[item.Value.gameObjectName] = item.Value;
					}
				}
				return __instance;
			}
		}

		public bool TryGetOriginHealthManager(HealthManager relayHm, out HealthManager originHm)
		{
			originHm = null;
			if ((Object)(object)relayHm.SendDamageTo != (Object)null)
			{
				originHm = relayHm.SendDamageTo;
				return true;
			}
			endpointOfName.TryGetValue(((Object)((Component)relayHm).gameObject).name, out var value);
			if (value == null)
			{
				return false;
			}
			originHm = originOfRelayEndpoint.GetValueOrDefault(value, null)?.FindHealthManager() ?? null;
			return (Object)(object)originHm != (Object)null;
		}

		public float? GetOverrideHpIfAny(HealthManager hm)
		{
			if (!endpointOfName.TryGetValue(((Object)((Component)hm).gameObject).name, out var value))
			{
				return null;
			}
			if (value != null)
			{
				_ = value.type;
				_ = 1;
			}
			return value?.overrideOriginHp ?? null;
		}
	}
	internal class SpawnPreventionPolicy
	{
		public static float minMobHealth => Configs.Instance.minMobHp.Value;

		public static float INF => Configs.Instance.infHp.Value;

		public static bool ShouldPreventSpawn(HealthManager hm)
		{
			if ((float)hm.hp < minMobHealth)
			{
				return ((Object)hm).name != "Driller B";
			}
			if ((float)hm.hp >= INF)
			{
				return true;
			}
			return false;
		}
	}
	internal interface IVisibilityController
	{
		bool IsVisible { get; set; }

		void Inspect(HealthManager healthManager);

		bool Update(bool forceCheck = false);
	}
	internal class LinkedVisibilityController : IVisibilityController
	{
		private List<IVisibilityController> controllers = new List<IVisibilityController>();

		private bool visibilityCache;

		public bool IsVisible
		{
			get
			{
				for (int i = 0; i < controllers.Count; i++)
				{
					if (controllers[i].IsVisible)
					{
						return true;
					}
				}
				return false;
			}
			set
			{
			}
		}

		public void Inspect(HealthManager healthManager)
		{
			VisibilityController item = new VisibilityController(healthManager);
			controllers.Add(item);
		}

		public bool Update(bool forceCheck = false)
		{
			bool flag = false;
			for (int i = 0; i < controllers.Count; i++)
			{
				if (controllers[i].Update(forceCheck))
				{
					flag = true;
				}
			}
			if (flag)
			{
				bool isVisible = IsVisible;
				if (isVisible != visibilityCache)
				{
					visibilityCache = isVisible;
					return true;
				}
			}
			return false;
		}
	}
	internal class VisibilityController : IVisibilityController
	{
		private static readonly int enemyLayer = LayerMask.NameToLayer("Enemies");

		private static readonly float maxZ = Configs.Instance.maxZPosition.Value;

		private static readonly float visibleCacheTime = Configs.Instance.visibleCacheSeconds.Value;

		private static readonly float invisibleCacheTime = Configs.Instance.invisibleCacheSeconds.Value;

		private GameObject gameObject;

		private HealthManager hm;

		private Collider2D defaultCollider;

		private Renderer renderer;

		private Collider2D physicalPusherCollider;

		private bool visibilityCache;

		private float timeSinceLastCheck;

		public bool IsVisible
		{
			get
			{
				return visibilityCache;
			}
			set
			{
				visibilityCache = value;
				timeSinceLastCheck = 0f;
			}
		}

		private void tryGetColliders()
		{
			if (!Object.op_Implicit((Object)(object)defaultCollider))
			{
				defaultCollider = ((Component)hm).GetComponent<Collider2D>();
			}
			if (!Object.op_Implicit((Object)(object)physicalPusherCollider))
			{
				GameObject physicalPusher = hm.GetPhysicalPusher();
				physicalPusherCollider = ((physicalPusher != null) ? physicalPusher.GetComponent<Collider2D>() : null);
			}
		}

		private void tryGetRenderer()
		{
			if (!Object.op_Implicit((Object)(object)renderer))
			{
				renderer = ((Component)hm).GetComponent<Renderer>();
			}
			if (Object.op_Implicit((Object)(object)renderer))
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)hm).GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (val.enabled)
				{
					renderer = val;
					break;
				}
			}
		}

		public VisibilityController(HealthManager healthManager)
		{
			Inspect(healthManager);
		}

		public bool Update(bool forceCheck = false)
		{
			if (!forceCheck && timeSinceLastCheck < (visibilityCache ? visibleCacheTime : invisibleCacheTime))
			{
				timeSinceLastCheck += Time.deltaTime;
				return false;
			}
			timeSinceLastCheck = 0f;
			tryGetColliders();
			tryGetRenderer();
			bool flag = mobIsShowing();
			if (flag == visibilityCache)
			{
				return false;
			}
			visibilityCache = flag;
			return true;
		}

		private bool mobIsShowing()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Behaviour)hm).isActiveAndEnabled || hm.isDead)
			{
				return false;
			}
			if (gameObject.layer != enemyLayer)
			{
				return false;
			}
			if (Mathf.Abs(gameObject.transform.position.z) > maxZ)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)physicalPusherCollider) && Object.op_Implicit((Object)(object)defaultCollider))
			{
				if (!((Behaviour)physicalPusherCollider).isActiveAndEnabled && !((Behaviour)defaultCollider).isActiveAndEnabled)
				{
					return false;
				}
			}
			else
			{
				if (Object.op_Implicit((Object)(object)physicalPusherCollider) && !((Behaviour)physicalPusherCollider).isActiveAndEnabled)
				{
					return false;
				}
				if (Object.op_Implicit((Object)(object)defaultCollider) && !((Behaviour)defaultCollider).isActiveAndEnabled)
				{
					return false;
				}
			}
			if (Object.op_Implicit((Object)(object)renderer) && (!renderer.enabled || !renderer.isVisible))
			{
				return false;
			}
			return true;
		}

		public void Inspect(HealthManager healthManager)
		{
			hm = healthManager;
			gameObject = ((Component)hm).gameObject;
			defaultCollider = ((Component)hm).GetComponent<Collider2D>();
			renderer = ((Component)hm).GetComponent<Renderer>();
			GameObject physicalPusher = hm.GetPhysicalPusher();
			physicalPusherCollider = ((physicalPusher != null) ? physicalPusher.GetComponent<Collider2D>() : null);
		}
	}
	public class Playground : MonoBehaviour
	{
		public HealthBarController target;

		public GameObject bean;

		public GameObject bean2;

		private GameObject _player;

		private List<Color> colors = ColourPalette.AllElementColors;

		private GameObject _stubTemplate;

		private static Playground _instance;

		public GameObject Player
		{
			get
			{
				if ((Object)(object)_player == (Object)null)
				{
					_player = GameObject.Find("Hero_Hornet(Clone)");
				}
				return _player;
			}
		}

		public static Playground Instance
		{
			get
			{
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_instance == (Object)null)
				{
					_instance = Object.FindFirstObjectByType<Playground>();
					if ((Object)(object)_instance != (Object)null)
					{
						return _instance;
					}
					_instance = new GameObject(typeof(Playground).Name).AddComponent<Playground>();
				}
				return _instance;
			}
		}

		private GameObject Stub
		{
			get
			{
				if ((Object)(object)_stubTemplate == (Object)null)
				{
					GameObject val = null;
					val = Object.FindFirstObjectByType<MobHealthBarController>()?.GetRandomEnemyGO();
					if (!Object.op_Implicit((Object)(object)val))
					{
						return null;
					}
					_stubTemplate = Object.Instantiate<GameObject>(val);
					((Object)_stubTemplate).name = "Stub Template";
					_stubTemplate.SetActive(false);
					makeCleanStubTemplate(_stubTemplate);
					Object.DontDestroyOnLoad((Object)(object)_stubTemplate);
				}
				GameObject val2 = Object.Instantiate<GameObject>(_stubTemplate);
				((Object)val2).name = "Stub";
				val2.SetActive(true);
				List<MonoBehaviour> list = new List<MonoBehaviour>();
				list.AddRange((IEnumerable<MonoBehaviour>)(object)val2.GetComponents<tk2dSpriteAnimator>());
				list.AddRange((IEnumerable<MonoBehaviour>)(object)val2.GetComponents<DamageHero>());
				foreach (MonoBehaviour item in list)
				{
					((Behaviour)item).enabled = false;
				}
				return val2;
			}
		}

		protected virtual void Awake()
		{
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			else if ((Object)(object)_instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void makeCleanStubTemplate(GameObject go)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if ((Object)(object)_stubTemplate == (Object)null)
			{
				return;
			}
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in go.transform)
			{
				Transform val = item;
				list.Add(((Component)val).gameObject);
			}
			foreach (GameObject item2 in list)
			{
				Object.DestroyImmediate((Object)(object)item2);
			}
			Type[] array = new Type[15]
			{
				typeof(Transform),
				typeof(MeshFilter),
				typeof(MeshRenderer),
				typeof(tk2dSprite),
				typeof(tk2dSpriteAnimator),
				typeof(Rigidbody2D),
				typeof(Collider2D),
				typeof(HealthManager),
				typeof(MobHealthBarOwner),
				typeof(DamageHero),
				typeof(EnemyDeathEffects),
				typeof(EnemyHitEffectsRegular),
				typeof(TagDamageTaker),
				typeof(PlayMakerProxyBase),
				typeof(PlayMakerFSM)
			};
			Component[] components = go.GetComponents<Component>();
			List<Component> list2 = new List<Component>();
			Component[] array2 = components;
			foreach (Component val2 in array2)
			{
				bool flag = false;
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Type type = ((object)val2).GetType();
				Type[] array3 = array;
				for (int j = 0; j < array3.Length; j++)
				{
					if (array3[j].IsAssignableFrom(type))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list2.Add(val2);
				}
			}
			foreach (Component item3 in list2)
			{
				try
				{
					Object.DestroyImmediate((Object)(object)item3);
				}
				catch (Exception)
				{
				}
			}
		}
	}
	[BepInPlugin("com.kokomi.silkenimpact", "Silken Impact", "1.6.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		private Harmony _harmony;

		private static Plugin __instance;

		public static string PluginFolder { get; private set; }

		public static string AssetsFolder => Path.Combine(PluginFolder, "Assets");

		public static AssetBundle bundle { get; private set; }

		public static Plugin Instance => __instance;

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			__instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			LoadAssetBundle();
			PooledObjectService.Instance.InitializeAndPrewarm();
			_harmony = new Harmony("com.kokomi.silkenimpact");
			_harmony.PatchAll();
			GameObject val = new GameObject("Playground");
			val.AddComponent<Playground>();
			Object.DontDestroyOnLoad((Object)val);
			summon();
		}

		private void summon()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			GameObject val = new GameObject("MobHealthManager");
			val.AddComponent<MobHealthBarController>();
			Object.DontDestroyOnLoad((Object)val);
			GameObject val2 = new GameObject("BossHealthManager");
			val2.AddComponent<BossHealthBarController>();
			Object.DontDestroyOnLoad((Object)val2);
		}

		private void OnDestroy()
		{
			PooledObjectService.Instance.ClearAll();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)286))
			{
				PooledObjectService.Instance.ClearAll();
				LoadAssetBundle();
				PooledObjectService.Instance.InitializeAndPrewarm();
			}
		}

		public string LatestBundleInFolder(string folderPath)
		{
			return (from f in new DirectoryInfo(folderPath).GetFiles("default*.bundle")
				orderby f.LastWriteTime descending
				select f).FirstOrDefault()?.FullName;
		}

		public void LoadAssetBundle()
		{
			if ((Object)(object)bundle != (Object)null)
			{
				bundle.Unload(true);
			}
			PluginFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			bundle = AssetBundle.LoadFromFile(LatestBundleInFolder(AssetsFolder));
		}

		public static GameObject InstantiateFromAssetsBundle(string path, string name)
		{
			GameObject val = bundle.LoadAsset<GameObject>(path);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = null;
			try
			{
				val2 = Object.Instantiate<GameObject>(val);
			}
			catch (Exception ex)
			{
				PluginLogger.LogFatal(ex.ToString());
				return null;
			}
			((Object)val2).name = name;
			return val2;
		}
	}
	public static class PluginLogger
	{
		[Conditional("DEBUG")]
		public static void LogInfo(string message)
		{
			Plugin.Logger.LogInfo((object)message);
		}

		[Conditional("DEBUG")]
		public static void LogWarning(string message)
		{
			Plugin.Logger.LogWarning((object)message);
		}

		[Conditional("DEBUG")]
		public static void LogError(string message)
		{
			Plugin.Logger.LogError((object)message);
		}

		[Conditional("DEBUG")]
		public static void LogDebug(string message)
		{
			Plugin.Logger.LogDebug((object)message);
		}

		public static void LogFatal(string message)
		{
			Plugin.Logger.LogFatal((object)message);
		}

		[Conditional("DETAIL")]
		public static void LogDetail(string message)
		{
			Plugin.Logger.LogInfo((object)message);
		}
	}
	internal interface IPoolable
	{
		void OnAcquireFromPool();

		void OnReleaseToPool();
	}
	internal struct ObjectPoolSettings
	{
		public int initialSize;

		public int maxSize;

		public ObjectPoolSettings(int initialSize, int maxSize)
		{
			this.initialSize = initialSize;
			this.maxSize = maxSize;
		}
	}
	internal class PooledObject : MonoBehaviour
	{
		internal string PoolKey { get; set; }

		internal PooledObjectService Owner { get; set; }
	}
	internal class PooledObjectService
	{
		private class PoolBucket
		{
			internal readonly Stack<GameObject> inactive = new Stack<GameObject>();

			internal ObjectPoolSettings settings;

			internal string prefabPath;
		}

		private static PooledObjectService _instance;

		private readonly Dictionary<string, PoolBucket> _buckets = new Dictionary<string, PoolBucket>();

		private readonly Dictionary<string, ObjectPoolSettings> _defaultSettings = new Dictionary<string, ObjectPoolSettings>
		{
			["Assets/Addressables/Prefabs/DamageOldText.prefab"] = new ObjectPoolSettings(4, 24),
			["Assets/Addressables/Prefabs/HealOldText.prefab"] = new ObjectPoolSettings(2, 8),
			["Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab"] = new ObjectPoolSettings(8, 64),
			["Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Diamond.prefab"] = new ObjectPoolSettings(8, 64),
			["Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab"] = new ObjectPoolSettings(2, 12),
			["Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/DiamondBoss.prefab"] = new ObjectPoolSettings(2, 12)
		};

		private Transform _poolRoot;

		internal static PooledObjectService Instance => _instance ?? (_instance = new PooledObjectService());

		private PooledObjectService()
		{
		}

		private void EnsureRoot()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			if (!((Object)(object)_poolRoot != (Object)null))
			{
				GameObject val = new GameObject("SilkenImpact.ObjectPool");
				Object.DontDestroyOnLoad((Object)(object)val);
				_poolRoot = val.transform;
			}
		}

		private PoolBucket GetOrCreateBucket(string prefabPath)
		{
			if (_buckets.TryGetValue(prefabPath, out var value))
			{
				return value;
			}
			ObjectPoolSettings value2;
			ObjectPoolSettings settings = (_defaultSettings.TryGetValue(prefabPath, out value2) ? value2 : new ObjectPoolSettings(0, 32));
			PoolBucket poolBucket = new PoolBucket
			{
				prefabPath = prefabPath,
				settings = settings
			};
			_buckets[prefabPath] = poolBucket;
			return poolBucket;
		}

		private GameObject InstantiateForPool(string prefabPath, string displayName)
		{
			GameObject val = Plugin.InstantiateFromAssetsBundle(prefabPath, displayName);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			PooledObject pooledObject = val.GetComponent<PooledObject>();
			if ((Object)(object)pooledObject == (Object)null)
			{
				pooledObject = val.AddComponent<PooledObject>();
			}
			pooledObject.PoolKey = prefabPath;
			pooledObject.Owner = this;
			return val;
		}

		internal void InitializeAndPrewarm()
		{
			EnsureRoot();
			foreach (KeyValuePair<string, ObjectPoolSettings> defaultSetting in _defaultSettings)
			{
				string key = defaultSetting.Key;
				PoolBucket orCreateBucket = GetOrCreateBucket(key);
				for (int i = orCreateBucket.inactive.Count; i < orCreateBucket.settings.initialSize; i++)
				{
					GameObject val = InstantiateForPool(key, "Pooled");
					if ((Object)(object)val == (Object)null)
					{
						break;
					}
					Release(val);
				}
			}
		}

		internal GameObject Acquire(string prefabPath, string displayName, Transform parent = null)
		{
			if (string.IsNullOrEmpty(prefabPath))
			{
				return null;
			}
			EnsureRoot();
			PoolBucket orCreateBucket = GetOrCreateBucket(prefabPath);
			GameObject val = null;
			while (orCreateBucket.inactive.Count > 0 && (Object)(object)val == (Object)null)
			{
				orCreateBucket.inactive.AsEnumerable().ToList().ForEach(delegate
				{
				});
				val = orCreateBucket.inactive.Pop();
			}
			if ((Object)(object)val == (Object)null)
			{
				val = InstantiateForPool(prefabPath, displayName);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
			}
			((Object)val).name = displayName;
			val.transform.SetParent(parent, false);
			val.SetActive(true);
			IPoolable poolable = default(IPoolable);
			if (val.TryGetComponent<IPoolable>(ref poolable))
			{
				poolable.OnAcquireFromPool();
			}
			return val;
		}

		internal void Release(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			PooledObject component = go.GetComponent<PooledObject>();
			if ((Object)(object)component == (Object)null || component.Owner != this || string.IsNullOrEmpty(component.PoolKey))
			{
				Object.Destroy((Object)(object)go);
				return;
			}
			PoolBucket orCreateBucket = GetOrCreateBucket(component.PoolKey);
			if (orCreateBucket.inactive.Count >= orCreateBucket.settings.maxSize)
			{
				Object.Destroy((Object)(object)go);
			}
			else if (!orCreateBucket.inactive.Contains(go))
			{
				IPoolable poolable = default(IPoolable);
				if (go.TryGetComponent<IPoolable>(ref poolable))
				{
					poolable.OnReleaseToPool();
				}
				go.SetActive(false);
				go.transform.SetParent(_poolRoot, false);
				orCreateBucket.inactive.Push(go);
			}
		}

		internal void ClearAll()
		{
			foreach (PoolBucket value in _buckets.Values)
			{
				while (value.inactive.Count > 0)
				{
					GameObject val = value.inactive.Pop();
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
			_buckets.Clear();
			if ((Object)(object)_poolRoot != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_poolRoot).gameObject);
				_poolRoot = null;
			}
		}
	}
	public class CameraFollow : MonoBehaviour
	{
		public Transform target;

		public float smoothSpeed = 5f;

		public Vector3 offset = new Vector3(0f, 0f, -10f);

		private void LateUpdate()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)target == (Object)null))
			{
				Vector3 val = target.position + offset;
				Vector3 position = Vector3.Lerp(((Component)this).transform.position, val, smoothSpeed * Time.deltaTime);
				((Component)this).transform.position = position;
			}
		}
	}
	public static class ColourPalette
	{
		public static Color Hydro => FromHexString("#1EC5E3");

		public static Color Cryo => FromHexString("#78FDFF");

		public static Color Pyro => FromHexString("#FF6400");

		public static Color Anemo => FromHexString("#24FFD3");

		public static Color Geo => FromHexString("#FFE064");

		public static Color Electro => FromHexString("#D272FF");

		public static Color Dendro => FromHexString("#00C94E");

		public static Color Physical => FromHexString("#FFFFFF");

		public static Color HornetDress => FromHexString("#A83448");

		public static Color HealTextColor => FromHexString("#BDFF37");

		public static Color HP => FromHexString("#FC5A49");

		public static Color DelayedEffect => FromHexString("#FFCE89");

		public static Color HpBarBackground => FromHexString("#00000059");

		public static Color HpNumber => FromHexString("#bfbfbfff");

		public static List<Color> AllElementColors => new List<Color> { Hydro, Cryo, Pyro, Anemo, Geo, Electro, Dendro, Physical, HornetDress };

		public static Color FromHexString(string hex)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if ((hex.Length != 7 && hex.Length != 9) || hex[0] != '#')
			{
				throw new ArgumentException("Invalid hex color format. Expected format: #RRGGBB or #RRGGBBAA");
			}
			float num = 1f;
			if (hex.Length == 9)
			{
				num = (float)int.Parse(hex.Substring(7, 2), NumberStyles.HexNumber) / 255f;
			}
			return new Color((float)int.Parse(hex.Substring(1, 2), NumberStyles.HexNumber) / 255f, (float)int.Parse(hex.Substring(3, 2), NumberStyles.HexNumber) / 255f, (float)int.Parse(hex.Substring(5, 2), NumberStyles.HexNumber) / 255f, num);
		}
	}
	public class DamageOldText : DamageText
	{
		public Text textComponent;

		public override string DamageString
		{
			get
			{
				return textComponent.text;
			}
			set
			{
				textComponent.text = value;
			}
		}

		public override Color TextColor
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return ((Graphic)textComponent).color;
			}
			set
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				((Graphic)textComponent).color = value;
			}
		}

		public override Font TextFont
		{
			set
			{
				if (!((Object)(object)value == (Object)null))
				{
					textComponent.font = value;
				}
			}
		}
	}
	public abstract class DamageText : MonoBehaviour, IPoolable
	{
		public DamageTextAnimationConfig config;

		public float maxWidth;

		public float maxHeight;

		public RectTransform rectTransform;

		public Material fontMaterial;

		[SerializeField]
		private float secondsElapsed;

		[SerializeField]
		private Vector3 startPosition;

		[SerializeField]
		private Vector3 baseScale;

		[SerializeField]
		private Vector3 prefabScale;

		[SerializeField]
		private Color baseColor;

		[SerializeField]
		private Vector2 baseSize => new Vector2(maxWidth, maxHeight);

		[SerializeField]
		public Vector3 BaseScale
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return ((Component)this).transform.localScale;
			}
			set
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				((Component)this).transform.localScale = value;
				baseScale = value;
			}
		}

		public abstract string DamageString { get; set; }

		public abstract Color TextColor { get; set; }

		public abstract Font TextFont { set; }

		private void Awake()
		{
			//IL_0007: 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)
			prefabScale = ((Component)this).transform.localScale;
		}

		private void Start()
		{
			ResetAnimationState();
		}

		public void ResetForSpawn(float sizeScale)
		{
			//IL_0007: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.localScale = prefabScale;
			BaseScale = prefabScale * sizeScale;
			ResetAnimationState();
		}

		private void ResetAnimationState()
		{
			//IL_0007: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			startPosition = ((Component)this).transform.position;
			secondsElapsed = 0f;
			baseColor = TextColor;
			baseScale = ((Component)this).transform.localScale;
		}

		private void Update()
		{
			secondsElapsed += Time.deltaTime;
			if ((double)secondsElapsed < 1.1 * (double)config.durationSeconds)
			{
				DoAnimation();
			}
			else
			{
				PooledObjectService.Instance.Release(((Component)this).gameObject);
			}
		}

		private void DoAnimation()
		{
			//IL_0014: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			float num = secondsElapsed / config.durationSeconds;
			Color val = baseColor;
			val.a = 0f;
			val.r = Mathf.Clamp01(val.r - 0.5f);
			val.g = Mathf.Clamp01(val.g - 0.5f);
			val.b = Mathf.Clamp01(val.b - 0.5f);
			TextColor = Color.Lerp(val, baseColor, config.alphaCurve.Evaluate(num));
			((Transform)rectTransform).localScale = baseScale * config.scaleCurve.Evaluate(num);
			((Component)this).transform.position = startPosition + new Vector3(0f, baseScale.y * config.verticalOffsetCurve.Evaluate(num) * maxHeight, 0f);
		}

		public void OnAcquireFromPool()
		{
			ResetAnimationState();
		}

		public void OnReleaseToPool()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			secondsElapsed = 0f;
			((Component)this).transform.localScale = prefabScale;
			((Transform)rectTransform).localScale = Vector3.one;
		}
	}
	[CreateAssetMenu(fileName = "DamageTextAnimationConfig", menuName = "ScriptableObjects/DamageTextAnimationConfig")]
	public class DamageTextAnimationConfig : ScriptableObject
	{
		public AnimationCurve alphaCurve;

		public AnimationCurve blurCurve;

		public AnimationCurve scaleCurve;

		public AnimationCurve verticalOffsetCurve;

		public float durationSeconds = 0.9f;
	}
	public class DamageTextTMPro : DamageText
	{
		public TextMeshProUGUI textComponent;

		public override string DamageString
		{
			get
			{
				return ((TMP_Text)textComponent).text;
			}
			set
			{
				((TMP_Text)textComponent).text = DamageString;
			}
		}

		public override Color TextColor
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return ((Graphic)textComponent).color;
			}
			set
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				((Graphic)textComponent).color = value;
			}
		}

		public override Font TextFont
		{
			set
			{
				if (!((Object)(object)value == (Object)null))
				{
					TMP_FontAsset font = TMP_FontAsset.CreateFontAsset(value);
					((TMP_Text)textComponent).font = font;
				}
			}
		}
	}
	public class HealthBarController : MonoBehaviour
	{
	}
	public abstract class Bar : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <AnimateTo>d__12 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float duration;

			public float startPercentage;

			public float targetPercentage;

			public Bar <>4__this;

			private float <elapsedTime>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AnimateTo>d__12(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				Bar bar = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<elapsedTime>5__2 = 0f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<elapsedTime>5__2 < duration)
				{
					<elapsedTime>5__2 += Time.deltaTime;
					float num2 = Mathf.Clamp01(<elapsedTime>5__2 / duration);
					float percentage = Mathf.Lerp(startPercentage, targetPercentage, num2);
					bar.MatchWithPercentage(percentage);
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				bar.MatchWithPercentage(targetPercentage);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public float verticalMargin;

		public float h