Decompiled source of Silken Impact v1.4.1

plugins/com.kokomi.silkenimpact.dll

Decompiled 2 days 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.4.1.0")]
[assembly: AssemblyInformationalVersion("1.4.1+aac4ab4bf4e2023b172cf828634e2109aa02d62d")]
[assembly: AssemblyProduct("Silken Impact")]
[assembly: AssemblyTitle("com.kokomi.silkenimpact")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.1.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.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 SilkenImpact
{
	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<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;

		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 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 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 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_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				LoadLocalizationIfNeeded(option);
			}
			catch (Exception arg)
			{
				PluginLogger.LogFatal($"Failed to load localization: {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: Damage Text Colors"];
			new MyConfigSection(configSection6.name, config).AddEntry(ref configs.defaultColor, ColourPalette.HornetDress, configSection6.Get("Default Color")).AddEntry(ref configs.critHitColor, ColourPalette.Geo, configSection6.Get("Crit Hit Color")).AddEntry(ref configs.poisonColor, ColourPalette.Electro, configSection6.Get("Poison Color"))
				.AddEntry(ref configs.fireColor, ColourPalette.Pyro, configSection6.Get("Fire Color"))
				.AddEntry(ref configs.healTextColor, ColourPalette.HealTextColor, configSection6.Get("Heal Color"));
			ConfigSection configSection7 = localization["Dev: Visibility Controller Settings"];
			new MyConfigSection(configSection7.name, config).AddDebugOnlyEntry(ref configs.maxZPosition, 1f, configSection7.Get("Max Z Position")).AddDebugOnlyEntry(ref configs.visibleCacheSeconds, 0.5f, configSection7.Get("Visible Cache Seconds")).AddDebugOnlyEntry(ref configs.invisibleCacheSeconds, 0.5f, configSection7.Get("Invisible Cache Seconds"))
				.AddDebugOnlyEntry(ref configs.infHp, 10000f, configSection7.Get("Infinite HP Threshold"))
				.AddDebugOnlyEntry(ref configs.spriteTrackerZOffset, -1.5f, configSection7.Get("Sprite Tracker Z Offset"));
			ConfigSection configSection8 = localization["Dev: Damage Text Settings"];
			new MyConfigSection(configSection8.name, config).AddDebugOnlyEntry(ref configs.weightOfNewHit, 0.2f, configSection8.Get("Weight Of New Hit"));
		}
	}
	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 = enemyGO.GetComponent<HealthManager>().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))
			{
				Object.Destroy((Object)(object)((Component)healthBarOf[relayGO]).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);
				}
			}
		}

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

		protected virtual void OnEnemySpawn(GameObject enemyGO, float maxHp)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			HealthBar healthBar;
			if (healthBarOf.ContainsKey(enemyGO))
			{
				healthBar = healthBarOf[enemyGO];
				healthBar.SetMaxHealth(maxHp);
				return;
			}
			GameObject getNewHealthBar = GetNewHealthBar;
			getNewHealthBar.transform.SetParent(((Component)BarCanvas).transform);
			getNewHealthBar.transform.localScale = Vector3.one;
			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))
			{
				Object.Destroy((Object)(object)((Component)healthBarOf[enemyGO]).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 && visibilityController.Update())
			{
				CheckHP();
				if (visibilityController.IsVisible)
				{
					Show();
				}
				else
				{
					Hide();
				}
			}
		}

		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 class BossHealthBarController : BaseHealthBarController<BossOwnerEvent, BossHealthBarOwner>
	{
		private BossHealthBarContainer container;

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

		protected string healthBarPrefabPath => Configs.Instance.healthBarShape.Value switch
		{
			HealthBarShape.Rounded => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab", 
			HealthBarShape.Diamond => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/DiamondBoss.prefab", 
			_ => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab", 
		};

		public override GameObject GetNewHealthBar => Plugin.InstantiateFromAssetsBundle(healthBarPrefabPath, "BossHealthBar");

		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 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 => Configs.Instance.healthBarShape.Value switch
		{
			HealthBarShape.Rounded => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab", 
			HealthBarShape.Diamond => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Diamond.prefab", 
			_ => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab", 
		};

		public override GameObject GetNewHealthBar => Plugin.InstantiateFromAssetsBundle(prefabPath, "MobHealthBar");

		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 (((Component)hm).CompareTag("Boss"))
			{
				return true;
			}
			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)
			{
				PluginLogger.LogFatal($"Detected initHP change on {((Object)hm).name}: {previousInitHp} -> {value}!");
				PluginLogger.LogFatal("Either Team Cherry added a new method to modify initHP after initialization, or another mod is interfering.");
				PluginLogger.LogFatal($"Current HP: {value}");
				PluginLogger.LogFatal("Attempting to make automatic adaptation. Updating health bar accordingly.");
				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 true;
			}
			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.4.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		private static AssetBundle bundle;

		private Harmony _harmony;

		private static Plugin __instance;

		public static string PluginFolder { get; private set; }

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

		public static Plugin Instance => __instance;

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			__instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"Plugin com.kokomi.silkenimpact is loaded!");
			LoadAssetBundle();
			_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()
		{
			Logger.LogDebug((object)"Plugin is being unloaded");
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)286))
			{
				Logger.LogInfo((object)"Reloading AssetBundle...");
				LoadAssetBundle();
			}
		}

		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);
			string text = LatestBundleInFolder(AssetsFolder);
			bundle = AssetBundle.LoadFromFile(text);
			Logger.LogInfo((object)("Loaded AssetBundle from " + text));
		}

		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)
			{
				Logger.LogFatal((object)ex);
				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);
		}
	}
	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 abstract class DamageText : MonoBehaviour
	{
		public DamageTextAnimationConfig config;

		public float maxWidth;

		public float maxHeight;

		private float yScale;

		public RectTransform rectTransform;

		public Material fontMaterial;

		[SerializeField]
		private float secondsElapsed;

		[SerializeField]
		private Vector3 startPosition;

		[SerializeField]
		private Color baseColor;

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

		public abstract string DamageString { get; set; }

		public abstract Color TextColor { get; set; }

		private void Start()
		{
			//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)
			startPosition = ((Component)this).transform.position;
			secondsElapsed = 0f;
			baseColor = TextColor;
			yScale = ((Component)this).transform.lossyScale.y;
		}

		private void Update()
		{
			secondsElapsed += Time.deltaTime;
			if ((double)secondsElapsed < 1.1 * (double)config.durationSeconds)
			{
				DoAnimation();
			}
			else
			{
				Object.Destroy((Object)(object)((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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			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));
			rectTransform.sizeDelta = baseSize * config.scaleCurve.Evaluate(num);
			((Component)this).transform.position = startPosition + new Vector3(0f, yScale * config.verticalOffsetCurve.Evaluate(num) * maxHeight, 0f);
		}
	}
	[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 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 horizontalMargin;

		public float maxHeight;

		public float maxWidth;

		public abstract float CurrentPercentage { get; }

		protected abstract void MatchWithPercentage(float percentage);

		public abstract void UpdateSize(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin);

		public abstract void SetVisibility(bool visible);

		public abstract void SetColor(Color color);

		public void Init(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin)
		{
			UpdateSize(maxHeight, maxWidth, verticalMargin, horizontalMargin);
			MatchWithPercentage(1f);
		}

		public void SetPercentage(float percentage, float animationDurationSeconds)
		{
			percentage = Mathf.Clamp01(percentage);
			if (animationDurationSeconds <= 0f)
			{
				MatchWithPercentage(percentage);
				return;
			}
			((MonoBehaviour)this).StopAllCoroutines();
			((MonoBehaviour)this).StartCoroutine(AnimateTo(CurrentPercentage, percentage, animationDurationSeconds));
		}

		[IteratorStateMachine(typeof(<AnimateTo>d__12))]
		private IEnumerator AnimateTo(float startPercentage, float targetPercentage, float duration)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AnimateTo>d__12(0)
			{
				<>4__this = this,
				startPercentage = startPercentage,
				targetPercentage = targetPercentage,
				duration = duration
			};
		}
	}
	public class HealthBar : MonoBehaviour
	{
		[SerializeField]
		protected HealthBarConfig config;

		[SerializeField]
		protected Bar hp;

		[SerializeField]
		protected Bar delayedEffect;

		[SerializeField]
		protected Bar background;

		[SerializeField]
		protected float height;

		[SerializeField]
		protected float width;

		[SerializeField]
		protected float verticalMargin;

		[SerializeField]
		protected float horizontalMargin;

		[SerializeField]
		protected float maxHealth = 100f;

		[SerializeField]
		protected float currentHealth = 100f;

		[SerializeField]
		protected float decayTimer;

		[SerializeField]
		protected float DecayingHealth
		{
			get
			{
				float num = delayedEffect.CurrentPercentage * maxHealth;
				if ((double)Mathf.Abs(currentHealth - num) < 1E-05)
				{
					return currentHealth;
				}
				return num;
			}
		}

		public float MaxHealth => maxHealth;

		public float CurrentHealth => currentHealth;

		public void SetHpColor(Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			hp.SetColor(color);
		}

		public void SetDelayedEffectColor(Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			delayedEffect.SetColor(color);
		}

		public void SetBackgroundColor(Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			background.SetColor(color);
		}

		public void SetHeight(float height)
		{
			this.height = height;
			Redraw();
		}

		public void SetWidth(float width)
		{
			this.width = width;
			Redraw();
		}

		public void SetMargin(float verticalMargin, float horizontalMargin)
		{
			this.verticalMargin = verticalMargin;
			this.horizontalMargin = horizontalMargin;
			Redraw();
		}

		public void SetMaxHealth(float maxHealth)
		{
			this.maxHealth = maxHealth;
			currentHealth = Mathf.Clamp(currentHealth, 0f, maxHealth);
			OnStart();
		}

		protected void Start()
		{
			OnStart();
		}

		protected virtual void Redraw()
		{
			hp.UpdateSize(height, width, verticalMargin, horizontalMargin);
			delayedEffect.UpdateSize(height, width, verticalMargin, horizontalMargin);
			background.UpdateSize(height, width, 0f, 0f);
		}

		protected virtual void OnStart()
		{
			hp.Init(height, width, verticalMargin, horizontalMargin);
			delayedEffect.Init(height, width, verticalMargin, horizontalMargin);
			background.Init(height, width, 0f, 0f);
			currentHealth = maxHealth;
			OnHealthChanged();
		}

		protected virtual void OnHealthChanged()
		{
		}

		protected void Update()
		{
			if (DecayingHealth > currentHealth)
			{
				if (decayTimer < config.decayThresholdSeconds)
				{
					decayTimer += Time.deltaTime;
					return;
				}
				delayedEffect.SetPercentage(currentHealth / maxHealth, (DecayingHealth - currentHealth) / maxHealth / config.decayPercentagePerSecond);
				decayTimer = 0f;
			}
			else
			{
				decayTimer = 0f;
			}
		}

		public void TakeDamage(float amount)
		{
			if (!(amount <= 0f))
			{
				if (decayTimer > 0f)
				{
					decayTimer -= config.timerReductionPercentageOnDamage * config.decayThresholdSeconds;
				}
				decayTimer = Mathf.Clamp(decayTimer, -0.3f * config.decayThresholdSeconds, config.decayThresholdSeconds);
				float num = Mathf.Clamp(currentHealth - amount, 0f, maxHealth);
				currentHealth = num;
				hp.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration);
				OnHealthChanged();
			}
		}

		public void Heal(float amount)
		{
			if (!(amount <= 0f))
			{
				float num = Mathf.Clamp(currentHealth + amount, 0f, maxHealth);
				currentHealth = num;
				delayedEffect.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration);
				hp.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration);
				OnHealthChanged();
			}
		}

		public void ResetHealth(float hp)
		{
			currentHealth = hp;
			maxHealth = hp;
			delayedEffect.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration);
			this.hp.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration);
			OnHealthChanged();
		}

		public virtual void SetVisibility(bool visible)
		{
			hp.SetVisibility(visible);
			delayedEffect.SetVisibility(visible);
			background.SetVisibility(visible);
		}

		private void OnDestroy()
		{
		}
	}
	[CreateAssetMenu(fileName = "HealthBarConfig", menuName = "ScriptableObjects/HealthBarConfig")]
	public class HealthBarConfig : ScriptableObject
	{
		public float timerReductionPercentageOnDamage = 0.5f;

		public float decayThresholdSeconds = 0.2f;

		public float decayPercentagePerSecond = 0.4f;

		public float healthChangeDuration = 0.2f;
	}
	public class MaskedUIBar : UIBar
	{
		[SerializeField]
		private RectMask2D rectMask;

		private float currentWidth;

		public override float CurrentPercentage => currentWidth / maxWidth;

		public override void UpdateSize(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			float currentPercentage = CurrentPercentage;
			base.maxHeight = maxHeight - 2f * verticalMargin;
			base.maxWidth = maxWidth - 2f * horizontalMargin;
			base.verticalMargin = verticalMargin;
			base.horizontalMargin = horizontalMargin;
			rectTransform.anchorMin = new Vector2(0f, 0f);
			rectTransform.anchorMax = new Vector2(0f, 1f);
			rectTransform.pivot = new Vector2(0f, 0.5f);
			rectTransform.offsetMin = new Vector2(horizontalMargin, verticalMargin);
			rectTransform.SetSizeWithCurrentAnchors((Axis)1, base.maxHeight);
			rectTransform.SetSizeWithCurrentAnchors((Axis)0, base.maxWidth);
			MatchWithPercentage(currentPercentage);
		}

		protected override void MatchWithPercentage(float percentage)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			float num = (currentWidth = maxWidth * percentage);
			rectMask.padding = new Vector4(0f, 0f, maxWidth - num, 0f);
		}
	}
	public class SpriteBar : Bar
	{
		private SpriteRenderer spriteRenderer;

		public override float CurrentPercentage => ((Component)this).transform.localScale.x / (maxWidth - 2f * horizontalMargin);

		private void Awake()
		{
			spriteRenderer = ((Component)this).GetComponent<SpriteRenderer>();
		}

		public override void SetVisibility(bool visible)
		{
			((Renderer)spriteRenderer).enabled = visible;
		}

		public override void UpdateSize(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			base.verticalMargin = verticalMargin;
			base.horizontalMargin = horizontalMargin;
			base.maxWidth = maxWidth;
			base.maxHeight = maxHeight;
			((Component)this).transform.localScale = new Vector3(maxWidth - 2f * verticalMargin, maxHeight - 2f * horizontalMargin, 1f);
		}

		protected override void MatchWithPercentage(float percentage)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localScale = ((Component)this).transform.localScale;
			Vector3 localPosition = ((Component)this).transform.localPosition;
			localScale.x = (maxWidth - 2f * horizontalMargin) * percentage;
			localPosition.x = 0f - (maxWidth / 2f - horizontalMargin - localScale.x / 2f);
			((Component)this).transform.localScale = localScale;
			((Component)this).transform.localPosition = localPosition;
		}

		public override void SetColor(Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			spriteRenderer.color = color;
		}
	}
	public class UIBar : Bar
	{
		[SerializeField]
		protected RectTransform rectTransform;

		[SerializeField]
		protected CanvasGroup canvasGroup;

		[SerializeField]
		protected Image image;

		public override float CurrentPercentage => rectTransform.sizeDelta.x / maxWidth;

		public override void UpdateSize(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			float currentPercentage = CurrentPercentage;
			base.maxHeight = maxHeight - 2f * verticalMargin;
			base.maxWidth = maxWidth - 2f * horizontalMargin;
			base.verticalMargin = verticalMargin;
			base.horizontalMargin = horizontalMargin;
			rectTransform.anchorMin = new Vector2(0f, 0f);
			rectTransform.anchorMax = new Vector2(0f, 1f);
			rectTransform.pivot = new Vector2(0f, 0.5f);
			rectTransform.offsetMin = new Vector2(horizontalMargin, verticalMargin);
			rectTransform.SetSizeWithCurrentAnchors((Axis)1, base.maxHeight);
			rectTransform.SetSizeWithCurrentAnchors((Axis)0, base.maxWidth * currentPercentage);
		}

		protected override void MatchWithPercentage(float percentage)
		{
			float num = maxWidth * percentage;
			rectTransform.SetSizeWithCurrentAnchors((Axis)0, num);
		}

		public override void SetVisibility(bool visible)
		{
			canvasGroup.alpha = (visible ? 1 : 0);
		}

		public override void SetColor(Color color)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)image != (Object)null)
			{
				((Graphic)image).color = color;
			}
		}
	}
	public class UIHealthBar : HealthBar
	{
		[SerializeField]
		protected Text hpText;

		[SerializeField]
		protected Text nameText;

		[SerializeField]
		protected CanvasGroup canvasGroup;

		protected override void OnStart()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			base.OnStart();
			((Component)this).GetComponent<RectTransform>().sizeDelta = new Vector2(width, height);
		}

		protected override void Redraw()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			base.Redraw();
			((Component)this).GetComponent<RectTransform>().sizeDelta = new Vector2(width, height);
			OnHealthChanged();
		}

		protected override void OnHealthChanged()
		{
			hpText.text = $"{Mathf.CeilToInt(currentHealth)}/{Mathf.CeilToInt(maxHealth)}";
		}

		public void SetNameText(string name)
		{
			if (!((Object)(object)nameText == (Object)null))
			{
				nameText.text = name;
			}
		}

		public void SetHpTextColor(Color color)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)hpText == (Object)null))
			{
				((Graphic)hpText).color = color;
			}
		}

		public void SetHpTextEnabled(bool enabled)
		{
			if (!((Object)(object)hpText == (Object)null))
			{
				((Behaviour)hpText).enabled = enabled;
			}
		}

		public override void SetVisibility(bool visible)
		{
			base.SetVisibility(visible);
			canvasGroup.alpha = (visible ? 1 : 0);
		}
	}
	public static class ScreenSpaceCanvas
	{
		private static Canvas _screenSpaceCanvas;

		public static readonly string name = "SilkenImpactScreenSpaceCanvas";

		public static Canvas GetScreenSpaceCanvas
		{
			get
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_screenSpaceCanvas == (Object)null)
				{
					GameObject val = GameObject.Find(name);
					if ((Object)(object)val != (Object)null)
					{
						return val.GetComponent<Canvas>();
					}
					val = new GameObject(name);
					Object.DontDestroyOnLoad((Object)(object)val);
					_screenSpaceCanvas = val.AddComponent<Canvas>();
					_screenSpaceCanvas.renderMode = (RenderMode)0;
					_screenSpaceCanvas.vertexColorAlwaysGammaSpace = false;
					_screenSpaceCanvas.sortingOrder = 999;
					CanvasScaler obj = val.AddComponent<CanvasScaler>();
					obj.uiScaleMode = (ScaleMode)1;
					obj.referenceResolution = new Vector2(26f, 14f);
					obj.screenMatchMode = (ScreenMatchMode)0;
					obj.matchWidthOrHeight = 0.5f;
					obj.referencePixelsPerUnit = 100f;
				}
				return _screenSpaceCanvas;
			}
		}
	}
	public class SpriteTracker : MonoBehaviour
	{
		public float gapBetweenTop;

		public float zOffset;

		[SerializeField]
		private GameObject target;

		[SerializeField]
		private Vector3 basicOffset = Vector3.zero;

		private Vector3 Offset => basicOffset + new Vector3(0f, gapBetweenTop, zOffset);

		private void Start()
		{
			SetTarget(target);
		}

		private Renderer GetEnabledRendererInChildren(GameObject target)
		{
			Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>();
			Renderer result = null;
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if (val.enabled)
				{
					result = val;
					break;
				}
			}
			return result;
		}

		public void SetTarget(GameObject target)
		{
			//IL_0008: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			this.target = target;
			basicOffset = Vector3.zero;
			if ((Object)(object)target != (Object)null)
			{
				Renderer val = default(Renderer);
				Renderer val2 = ((!target.TryGetComponent<Renderer>(ref val)) ? GetEnabledRendererInChildren(target) : val);
				if ((Object)(object)val2 != (Object)null)
				{
					Bounds bounds = val2.bounds;
					float y = ((Bounds)(ref bounds)).extents.y;
					basicOffset = new Vector3(0f, y, 0f);
				}
			}
		}

		private void Update()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)target == (Object)null))
			{
				((Component)this).transform.position = target.transform.position + Offset;
			}
		}
	}
	public static class WorldSpaceCanvas
	{
		private static Canvas _worldSpaceCanvas;

		public static readonly string name = "SilkenImpactWorldSpaceCanvas";

		public static readonly float PPU = 100f;

		public static Canvas GetWorldSpaceCanvas
		{
			get
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				if ((Object)(object)_worldSpaceCanvas == (Object)null)
				{
					GameObject val = GameObject.Find(name);
					if ((Object)(object)val != (Object)null)
					{
						return val.GetComponent<Canvas>();
					}
					val = new GameObject(name);
					Object.DontDestroyOnLoad((Object)(object)val);
					_worldSpaceCanvas = val.AddComponent<Canvas>();
					_worldSpaceCanvas.renderMode = (RenderMode)2;
					_worldSpaceCanvas.worldCamera = Camera.main;
					_worldSpaceCanvas.sortingOrder = 1000;
					CanvasScaler obj = val.AddComponent<CanvasScaler>();
					obj.dynamicPixelsPerUnit = PPU;
					obj.referencePixelsPerUnit = PPU;
				}
				return _worldSpaceCanvas;
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.kokomi.silkenimpact";

		public const string PLUGIN_NAME = "Silken Impact";

		public const string PLUGIN_VERSION = "1.4.1";
	}
}
namespace SilkenImpact.Deprecated
{
	public class HealthBar : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <AnimateHealthChange>d__19 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public HealthBar <>4__this;

			public float targetHealth;

			private float <timer>5__2;

			private float <startHealth>5__3;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				HealthBar healthBar = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<timer>5__2 = 0f;
					<startHealth>5__3 = healthBar.currentHealth;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<timer>5__2 < healthBar.healthChangeDuration)
				{
					<timer>5__2 += Time.deltaTime;
					float num2 = Mathf.Clamp01(<timer>5__2 / healthBar.healthChangeDuration);
					healthBar.currentHealth = Mathf.Lerp(<startHealth>5__3, targetHealth, num2);
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				healthBar.currentHealth = targetHealth;
				healthBar.healthAnimationCoroutine = null;
				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 SpriteRenderer hp;

		public SpriteRenderer delayedEffect;

		public SpriteRenderer background;

		public float maxHealth = 100f;

		[SerializeField]
		private float currentHealth;

		[SerializeField]
		private float delayedHealth;

		public float timerReductionPercentageOnDamage = 0.5f;

		public float decayThresholdSeconds = 0.2f;

		public float decayPercentagePerSecond = 0.4f;

		[SerializeField]
		private float decayTimer;

		public float healthChangeDuration = 0.2f;

		private Coroutine healthAnimationCoroutine;

		private void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			hp.size = background.size;
			delayedEffect.size = background.size;
			Vector3 localScale = ((Component)background).transform.localScale;
			((Component)hp).transform.localScale = localScale;
			((Component)delayedEffect).transform.localScale = localScale;
			Vector3 localPosition = ((Component)background).transform.localPosition;
			((Component)hp).transform.localPosition = localPosition;
			((Component)delayedEffect).transform.localPosition = localPosition;
			((Renderer)hp).sortingOrder = 2;
			((Renderer)delayedEffect).sortingOrder = 1;
			((Renderer)background).sortingOrder = 0;
			currentHealth = maxHealth;
			delayedHealth = maxHealth;
		}

		private void SetSpritePercentage(SpriteRenderer sprite, float percentage)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			percentage = Mathf.Clamp01(percentage);
			Vector3 localScale = ((Component)sprite).transform.localScale;
			localScale.x = ((Component)background).transform.localScale.x * percentage;
			((Component)sprite).transform.localScale = localScale;
			Vector3 localPosition = ((Component)sprite).transform.localPosition;
			float x = background.size.x;
			float num = ((Component)background).transform.localScale.x - localScale.x;
			localPosition.x = ((Component)background).transform.localPosition.x - x * num * 0.5f;
			((Component)sprite).transform.localPosition = localPosition;
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)97))
			{
				TakeDamage(10f);
			}
			if (Input.GetKeyDown((KeyCode)100))
			{
				Heal(10f);
			}
			SetSpritePercentage(hp, currentHealth / maxHealth);
			if (delayedHealth > currentHealth)
			{
				if (decayTimer < decayThresholdSeconds)
				{
					decayTimer += Time.deltaTime;
				}
				else
				{
					delayedHealth -= maxHealth * Time.deltaTime * decayPercentagePerSecond;
					delayedHealth = Mathf.Clamp(delayedHealth, currentHealth, maxHealth);
				}
			}
			else
			{
				delayedHealth = currentHealth;
				decayTimer = 0f;
			}
			SetSpritePercentage(delayedEffect, delayedHealth / maxHealth);
		}

		public void TakeDamage(float amount)
		{
			decayTimer -= timerReductionPercentageOnDamage * decayThresholdSeconds;
			decayTimer = Mathf.Clamp(decayTimer, -0.3f * decayThresholdSeconds, decayThresholdSeconds);
			float newHealth = Mathf.Clamp(currentHealth - amount, 0f, maxHealth);
			AnimateHealthTo(newHealth);
		}

		public void Heal(float amount)
		{
			float newHealth = Mathf.Clamp(currentHealth + amount, 0f, maxHealth);
			AnimateHealthTo(newHealth);
		}

		public void SetHealth(float percentage)
		{
			percentage = Mathf.Clamp01(percentage);
			float num = percentage * maxHealth;
			if (num >= currentHealth)
			{
				Heal(num - currentHealth);
			}
			else
			{
				TakeDamage(currentHealth - num);
			}
		}

		private void AnimateHealthTo(float newHealth)
		{
			if (healthAnimationCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(healthAnimationCoroutine);
			}
			healthAnimationCoroutine = ((MonoBehaviour)this).StartCoroutine(AnimateHealthChange(newHealth));
		}

		[IteratorStateMachine(typeof(<AnimateHealthChange>d__19))]
		private IEnumerator AnimateHealthChange(float targetHealth)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AnimateHealthChange>d__19(0)
			{
				<>4__this = this,
				targetHealth = targetHealth
			};
		}
	}
}
namespace SilkenImpact.Patch
{
	[HarmonyPatch]
	[HarmonyPatch(typeof(BlackThreadState))]
	public class BlackThreadStatePatch
	{
		private static HealthManager GetPrivateHealthManager(BlackThreadState instance)
		{
			return Traverse.Create((object)instance).Field<HealthManager>("healthManager").Value;
		}

		[HarmonyPatch("SetupThreaded")]
		[HarmonyPrefix]
		public static void BlackThreadState_DoDamage_Prefix(BlackThreadState __instance, ref Tuple<int, int> __state)
		{
			HealthManager privateHealthManager = GetPrivateHealthManager(__instance);
			if (Object.op_Implicit((Object)(object)privateHealthManager))
			{
				int hp = privateHealthManager.hp;
				int item = ((Component)privateHealthManager).GetComponent<IHealthBarOwner>()?.Dispatcher.Enqueue<SetHpEventArgs>() ?? (-1);
				__state = new Tuple<int, int>(hp, item);
			}
		}

		[HarmonyPatch("SetupThreaded")]
		[HarmonyPostfix]
		public static void BlackThreadState_DoDamage_Postfix(BlackThreadState __instance, ref Tuple<int, int> __state)
		{
			HealthManager privateHealthManager = GetPrivateHealthManager(__instance);
			if (Object.op_Implicit((Object)(object)privateHealthManager))
			{
				int hp = privateHealthManager.hp;
				var (num3, id) = __state;
				if (hp != num3)
				{
					((Component)privateHealthManager).GetComponent<IHealthBarOwner>()?.Dispatcher.Submit(id, new SetHpEventArgs(hp));
				}
				else
				{
					((Component)privateHealthManager).GetComponent<IHealthBarOwner>()?.Dispatcher.Cancel(id);
				}
			}
		}
	}
	[HarmonyPatch]
	[HarmonyPatch(typeof(EnemyDeathEffects))]
	public class EnemyDeathEffectsPatch
	{
	}
	[HarmonyPatch]
	[HarmonyPatch(typeof(HealthManager))]
	public class HealthManagerPatch
	{
		public static float avgDamagePerHit = -1f;

		private static MethodInfo isImmuneToMethod = AccessTools.Method(typeof(HealthManager), "IsImmuneTo", (Type[])null, (Type[])null);

		private static MethodInfo applyDamageScalingMethod = AccessTools.Method(typeof(HealthManager), "ApplyDamageScaling", (Type[])null, (Type[])null);

		public static float weightOfNew => Configs.Instance.weightOfNewHit.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;
		}

		private static void spawnTextOn(HealthManager __instance, 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)__instance).gameObject).name;
			Renderer component = ((Component)__instance).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)__instance).gameObject.transform.position + val2;
			textGO.transform.SetParent(((Component)WorldSpaceCanvas.GetWorldSpaceCanvas).transform, true);
			DamageText component2 = textGO.GetComponent<DamageText>();
			component2.DamageString = content;
			component2.TextColor = color;
			component2.maxHeight *= sizeScale;
			component2.maxWidth *= sizeScale;
		}

		public static void SpawnDamageText(HealthManager __instance, float damage, bool isCritHit, NailElements element = 0, Color? color = null)
		{
			//IL_00b9: 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_00b0: 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 = Ra