Decompiled source of HereticUnchained v2.0.2

HereticUnchained.dll

Decompiled a year ago
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using AncientScepter;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using EntityStates;
using EntityStates.GlobalSkills.LunarDetonator;
using EntityStates.GlobalSkills.LunarNeedle;
using EntityStates.Heretic;
using EntityStates.Huntress;
using EntityStates.Mage.Weapon;
using EntityStates.Treebot.Weapon;
using HereticUnchained.Components;
using HereticUnchained.CoreModules;
using HereticUnchained.EntityState;
using HereticUnchained.Properties;
using HereticUnchained.Skills;
using HereticUnchained.SurvivorTweaks;
using HereticUnchained.Unlocks;
using IL.RoR2;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On.EntityStates;
using On.EntityStates.Mage.Weapon;
using On.RoR2;
using On.RoR2.UI;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.Achievements;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.UI;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("HereticUnchained")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HereticUnchained")]
[assembly: AssemblyTitle("HereticUnchained")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
internal class SkillDefInfo
{
	public string skillName;

	public string skillNameToken;

	public string skillDescriptionToken;

	public Sprite skillIcon;

	public SerializableEntityStateType activationState;

	public string activationStateMachineName;

	public int baseMaxStock;

	public float baseRechargeInterval;

	public bool beginSkillCooldownOnSkillEnd;

	public bool canceledFromSprinting;

	public bool forceSprintDuringState;

	public bool fullRestockOnAssign;

	public InterruptPriority interruptPriority;

	public bool resetCooldownTimerOnUse;

	public bool isCombatSkill;

	public bool mustKeyPress;

	public bool cancelSprintingOnActivation;

	public int rechargeStock;

	public int requiredStock;

	public int stockToConsume;

	public string[] keywordTokens;
}
namespace HereticUnchained
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.Borbo.HereticUnchained", "HereticUnchained", "2.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[R2APISubmoduleDependency(new string[] { "LoadoutAPI", "LanguageAPI", "PrefabAPI", "RecalculateStatsAPI", "ContentAddition" })]
	public class HereticPlugin : BaseUnityPlugin
	{
		public const string ModGUID = "com.Borbo.HereticUnchained";

		public const string ModName = "HereticUnchained";

		public const string ModVer = "2.0.2";

		public static AssetBundle iconBundle = Tools.LoadAssetBundle(Resources.hereticunchained);

		public static string iconsPath = "Assets/HereticIcons/";

		public static string TokenName = "HERETICUNCHAINED_";

		public static bool isScepterLoaded = Tools.isLoaded("com.DestroyedClone.AncientScepter");

		public static bool isAutosprintLoaded = Tools.isLoaded("com.johnedwa.RTAutoSprintEx");

		public static bool is2R4RLoaded = Tools.isLoaded("com.HouseOfFruits.RiskierRain");

		public static string hereticBodyName = "HeresyBody";

		internal static BodyIndex hereticBodyIndex;

		internal static SurvivorDef hereticSurvivorDef;

		internal static GameObject hereticDisplayPrefab;

		internal static GameObject hereticPrefab;

		internal static CharacterBody hereticBodyPrefab;

		public static SkillLocator skillLocator;

		public static SkillFamily passiveFamily;

		public static SkillFamily primaryFamily;

		public static SkillFamily secondaryFamily;

		public static SkillFamily utilityFamily;

		public static SkillFamily specialFamily;

		public static ItemDef lunarPrimary;

		public static string visionsShortDescriptionToken;

		public static string visionsLongDescriptionToken;

		public static ItemDef lunarSecondary;

		public static string hooksShortDescriptionToken;

		public static string hooksLongDescriptionToken;

		public static ItemDef lunarUtility;

		public static string stridesShortDescriptionToken;

		public static string stridesLongDescriptionToken;

		public static ItemDef lunarSpecial;

		public static string essenceShortDescriptionToken;

		public static string essenceLongDescriptionToken;

		public static Dictionary<UnlockBase, UnlockableDef> UnlockBaseDictionary = new Dictionary<UnlockBase, UnlockableDef>();

		public static List<SkillBase> Skills = new List<SkillBase>();

		public static Dictionary<uint, SkillDef> ScepterSkills = new Dictionary<uint, SkillDef>();

		public static Dictionary<SkillBase, bool> SkillStatusDictionary = new Dictionary<SkillBase, bool>();

		internal static ConfigFile CustomConfigFile { get; set; }

		public void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			Debug.Log((object)"Heretic Unchained is loading!");
			lunarPrimary = Addressables.LoadAssetAsync<ItemDef>((object)"RoR2/Base/LunarSkillReplacements/LunarPrimaryReplacement.asset").WaitForCompletion();
			visionsShortDescriptionToken = lunarPrimary.pickupToken;
			visionsLongDescriptionToken = lunarPrimary.descriptionToken;
			lunarSecondary = Addressables.LoadAssetAsync<ItemDef>((object)"RoR2/Base/LunarSkillReplacements/LunarSecondaryReplacement.asset").WaitForCompletion();
			hooksShortDescriptionToken = lunarSecondary.pickupToken;
			hooksLongDescriptionToken = lunarSecondary.descriptionToken;
			lunarUtility = Addressables.LoadAssetAsync<ItemDef>((object)"RoR2/Base/LunarSkillReplacements/LunarUtilityReplacement.asset").WaitForCompletion();
			stridesShortDescriptionToken = lunarUtility.pickupToken;
			stridesLongDescriptionToken = lunarUtility.descriptionToken;
			lunarSpecial = Addressables.LoadAssetAsync<ItemDef>((object)"RoR2/Base/LunarSkillReplacements/LunarSpecialReplacement.asset").WaitForCompletion();
			essenceShortDescriptionToken = lunarSpecial.pickupToken;
			essenceLongDescriptionToken = lunarSpecial.descriptionToken;
			InitializeConfig();
			InitializeUnlocks();
			InitializePrefab();
			InitializeSkins();
			CreateSkillFamilies(hereticPrefab);
			HereticTweaks.Init();
			Survivors.SurvivorDefInfo survivorDefInfo = default(Survivors.SurvivorDefInfo);
			survivorDefInfo.bodyPrefab = hereticPrefab;
			survivorDefInfo.displayPrefab = hereticDisplayPrefab;
			survivorDefInfo.primaryColor = Color.grey;
			survivorDefInfo.displayNameToken = "HERETIC_BODY_NAME";
			survivorDefInfo.descriptionToken = "HERETIC_DESCRIPTION";
			survivorDefInfo.outroFlavorToken = "HERETIC_OUTRO_FLAVOR";
			survivorDefInfo.mainEndingEscapeFailureFlavorToken = "HERETIC_MAIN_ENDING_ESCAPE_FAILURE_FLAVOR";
			survivorDefInfo.desiredSortPosition = 30f;
			survivorDefInfo.unlockableDef = null;
			hereticSurvivorDef = Survivors.RegisterNewSurvivor(survivorDefInfo);
			LanguageAPI.Add("HERETIC_DESCRIPTION", "The Heretic is a powerful character who may be accessed through extraordinary means.<style=cSub>\r\n\r\n< ! > Remember that The Heretic’s skills can be used on other survivors at any time! It might be worth considering skill combinations that work best on your favorite characters instead of The Heretic themself.\r\n\r\n< ! > Health decay can kill The Heretic if you aren't careful! Good Shadowfade timing is essential for survival, but it will also halt your damage output.\r\n\r\n< ! > While their skills are powerful, The Heretic’s strength is offset by long waits to recharge. Cooldown reduction effects can be immensely valuable!\r\n\r\n< ! > Detonating Ruin at the right moment can devastate crowds and bosses. Hungering Gaze can be your most effective tool for applying Ruin, but may also easily be wasted on overkill against fodder enemies. Use it carefully!\r\n</style>\r\n");
			LanguageAPI.Add("HERETIC_PASSIVE_NAME", "Dissident Will");
			LanguageAPI.Add("HERETIC_PASSIVE_DESC", "The Heretic can jump three times... <style=cIsHealth>BUT their health decays rapidly over time.</style>");
			LanguageAPI.Add("SKILL_LUNAR_PRIMARY_REPLACEMENT_DESCRIPTION", "Fire a flurry of <style=cIsUtility>tracking shards</style> that detonate after a delay, dealing <style=cIsDamage>120% damage</style>.");
			LanguageAPI.Add("SKILL_LUNAR_SPECIAL_REPLACEMENT_NAME", "Ruinous Wake");
			LanguageAPI.Add("SKILL_LUNAR_SPECIAL_REPLACEMENT_DESCRIPTION", "<style=cIsUtility>Ruinous.</style> Activating this skill <style=cIsDamage>detonates</style> all Ruin at an unlimited range, dealing <style=cIsDamage>300% damage</style> plus <style=cIsDamage>120% per stack of Ruin</style>.");
			LanguageAPI.Add("KEYWORD_RUINOUS", "<style=cKeywordName>Ruinous</style><style=cSub>PASSIVE: While this skill is ready to use, <style=cIsDamage>your attacks</style> can apply a stack of <style=cIsDamage>Ruin</style> for 10 seconds. <i>Applying Ruin resets the duration of all stacks on the same target.</i></style>");
			HereticSkills.YoinkSkillDefs();
			InitializeCoreModules();
			InitializeSkills();
			InitializeScepterSkills();
		}

		public void Start()
		{
		}

		private void InitializeConfig()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			CustomConfigFile = new ConfigFile(Paths.ConfigPath + "\\HereticUnchained.cfg", true);
		}

		private void InitializeCoreModules()
		{
			IEnumerable<Type> enumerable = from type in Assembly.GetExecutingAssembly().GetTypes()
				where !type.IsAbstract && type.IsSubclassOf(typeof(CoreModule))
				select type;
			foreach (Type item in enumerable)
			{
				CoreModule coreModule = (CoreModule)Activator.CreateInstance(item);
				coreModule.Init();
				Debug.Log((object)("Core Module: " + coreModule?.ToString() + " Initialized!"));
			}
		}

		private void InitializeUnlocks()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			IEnumerable<Type> enumerable = from type in Assembly.GetExecutingAssembly().GetTypes()
				where !type.IsAbstract && type.IsSubclassOf(typeof(UnlockBase))
				select type;
			foreach (Type item in enumerable)
			{
				UnlockBase unlockBase = (UnlockBase)Activator.CreateInstance(item);
				if (!unlockBase.HideUnlock)
				{
					unlockBase.Init(CustomConfigFile);
					MethodInfo method = typeof(UnlockableAPI).GetMethod("AddUnlockable");
					UnlockableDef value = (UnlockableDef)method.MakeGenericMethod(item).Invoke(null, new object[1] { true });
					bool flag = unlockBase.ForceDisable;
					if (!flag)
					{
						flag = CustomConfigFile.Bind<bool>("Config: UNLOCKS", "Force Unlock Achievement: " + unlockBase.UnlockName, false, "Force this achievement to unlock: " + unlockBase.UnlockName + "?").Value;
					}
					if (!flag)
					{
						UnlockBaseDictionary.Add(unlockBase, value);
					}
					else
					{
						UnlockBaseDictionary.Add(unlockBase, ScriptableObject.CreateInstance<UnlockableDef>());
					}
				}
			}
		}

		public static UnlockableDef GetUnlockDef(Type type)
		{
			UnlockableDef result = null;
			foreach (KeyValuePair<UnlockBase, UnlockableDef> item in UnlockBaseDictionary)
			{
				string text = ((object)item.Key).ToString();
				UnlockableDef value = item.Value;
				if (text == type.ToString())
				{
					result = value;
					break;
				}
			}
			return result;
		}

		private void InitializeSkills()
		{
			IEnumerable<Type> enumerable = from type in Assembly.GetExecutingAssembly().GetTypes()
				where !type.IsAbstract && type.IsSubclassOf(typeof(SkillBase))
				select type;
			foreach (Type item in enumerable)
			{
				SkillBase skillBase = (SkillBase)Activator.CreateInstance(item);
				if (ValidateSkill(skillBase))
				{
					skillBase.Init(CustomConfigFile);
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private void InitializeScepterSkills()
		{
			IEnumerable<Type> enumerable = from type in Assembly.GetExecutingAssembly().GetTypes()
				where !type.IsAbstract && type.IsSubclassOf(typeof(ScepterSkillBase))
				select type;
			foreach (Type item in enumerable)
			{
				ScepterSkillBase scepterSkillBase = (ScepterSkillBase)Activator.CreateInstance(item);
				if (ValidateScepterSkill(scepterSkillBase))
				{
					scepterSkillBase.Init(CustomConfigFile);
				}
			}
		}

		private bool ValidateSkill(SkillBase item)
		{
			bool flag = true;
			if (flag)
			{
				Skills.Add(item);
			}
			SkillStatusDictionary.Add(item, flag);
			return flag;
		}

		private bool ValidateScepterSkill(ScepterSkillBase item)
		{
			return isScepterLoaded;
		}

		private void FixSetStateOnHurt()
		{
			SetStateOnHurt val = hereticPrefab.GetComponent<SetStateOnHurt>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = hereticPrefab.AddComponent<SetStateOnHurt>();
			}
			val.canBeStunned = false;
			val.canBeHitStunned = false;
			val.canBeFrozen = true;
			val.hitThreshold = 5f;
			EntityStateMachine[] componentsInChildren = hereticPrefab.GetComponentsInChildren<EntityStateMachine>();
			foreach (EntityStateMachine val2 in componentsInChildren)
			{
				if (val2.customName == "Body")
				{
					val.targetStateMachine = val2;
					break;
				}
			}
		}

		private static void AddHeresyItems(orig_Start orig, CharacterMaster self)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)self.teamIndex == 1)
			{
				bool flag = !NetworkServer.active || !Object.op_Implicit((Object)(object)Run.instance) || (Run.instance.stageClearCount != 0 && !RunArtifactManager.instance.IsArtifactEnabled(Artifacts.randomSurvivorOnRespawnArtifactDef));
				if ((Object)(object)self.bodyPrefab == (Object)(object)hereticPrefab)
				{
					if (!flag)
					{
						Inventory inventory = self.inventory;
						if (Object.op_Implicit((Object)(object)inventory))
						{
							Debug.Log((object)"Adding Heretic items!");
							ItemDef[] array = (ItemDef[])(object)new ItemDef[4]
							{
								Items.LunarPrimaryReplacement,
								Items.LunarSecondaryReplacement,
								Items.LunarUtilityReplacement,
								Items.LunarSpecialReplacement
							};
							ItemDef[] array2 = array;
							foreach (ItemDef val in array2)
							{
								if (inventory.GetItemCount(val) < 1)
								{
									inventory.GiveItem(val, 1);
								}
							}
						}
					}
					self.bodyPrefab = LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterBodies/HereticBody");
				}
			}
			orig.Invoke(self);
		}

		private static void SkillReplacementIntercept(orig_ReplaceSkillIfItemPresent orig, CharacterBody self, GenericSkill skill, ItemIndex itemIndex, SkillDef skillDef)
		{
			//IL_011a: 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_0021: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)self.teamComponent != (Object)null && (int)self.teamComponent.teamIndex == 1)
			{
				Loadout loadout = self.master.loadout;
				if (itemIndex == Items.LunarPrimaryReplacement.itemIndex)
				{
					skillDef = GetSkillPreferenceFromLoadout(loadout, 0, skillDef);
				}
				if (itemIndex == Items.LunarSecondaryReplacement.itemIndex)
				{
					skillDef = GetSkillPreferenceFromLoadout(loadout, 1, skillDef);
				}
				if (itemIndex == Items.LunarUtilityReplacement.itemIndex)
				{
					skillDef = GetSkillPreferenceFromLoadout(loadout, 2, skillDef);
				}
				if (itemIndex == Items.LunarSpecialReplacement.itemIndex)
				{
					bool flag = false;
					bool flag2 = false;
					if (isScepterLoaded)
					{
						flag = HasAncientScepter(self);
					}
					if (flag)
					{
						uint skillPreferenceFromLoadout = GetSkillPreferenceFromLoadout(loadout, 3);
						SkillDef val = ScepterSkills[skillPreferenceFromLoadout];
						if ((Object)(object)val != (Object)null)
						{
							skillDef = val;
							flag2 = true;
						}
					}
					if (!flag2)
					{
						skillDef = GetSkillPreferenceFromLoadout(loadout, 3, skillDef);
					}
				}
			}
			orig.Invoke(self, skill, itemIndex, skillDef);
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static bool HasAncientScepter(CharacterBody body)
		{
			Inventory inventory = body.inventory;
			if (inventory != null && inventory.GetItemCount(((ItemBase)ItemBase<AncientScepterItem>.instance).ItemDef) > 0)
			{
				return true;
			}
			return false;
		}

		private static void PickupTokenIntercept(orig_SetItemIndex orig, ItemIcon self, ItemIndex newItemIndex, int newItemCount)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			CharacterMaster val = CharacterMaster.instancesList[0];
			Loadout loadout = val.loadout;
			if (newItemIndex == Items.LunarPrimaryReplacement.itemIndex)
			{
				SkillDef skillPreferenceFromLoadout = GetSkillPreferenceFromLoadout(loadout, 0, null);
			}
			orig.Invoke(self, newItemIndex, newItemCount);
		}

		private static void InterceptPickupToken(orig_GiveItem_ItemIndex_int orig, Inventory self, ItemIndex itemIndex, int count)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: 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)
			if (NetworkServer.active && (ulong)(long)itemIndex < (ulong)self.itemStacks.Length && count > 0)
			{
				CharacterMaster val = CharacterMaster.instancesList[0];
				Loadout loadout = val.loadout;
				ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
				if ((Object)(object)itemDef == (Object)(object)Items.LunarPrimaryReplacement)
				{
					switch (GetSkillPreferenceFromLoadout(loadout, 0))
					{
					case 0u:
						Items.LunarPrimaryReplacement.pickupToken = visionsShortDescriptionToken;
						Items.LunarPrimaryReplacement.descriptionToken = visionsLongDescriptionToken;
						break;
					case 1u:
					{
						string skillLangTokenName2 = new BloodPrimarySkill().SkillLangTokenName;
						Items.LunarPrimaryReplacement.pickupToken = SkillBase.Token + skillLangTokenName2 + SkillBase.ShortDescToken;
						Items.LunarPrimaryReplacement.descriptionToken = SkillBase.Token + skillLangTokenName2 + SkillBase.FullDescToken;
						break;
					}
					case 2u:
					{
						string skillLangTokenName = new MassPrimarySkill().SkillLangTokenName;
						Items.LunarPrimaryReplacement.pickupToken = SkillBase.Token + skillLangTokenName + SkillBase.ShortDescToken;
						Items.LunarPrimaryReplacement.descriptionToken = SkillBase.Token + skillLangTokenName + SkillBase.FullDescToken;
						break;
					}
					}
				}
				if ((Object)(object)itemDef == (Object)(object)Items.LunarSecondaryReplacement)
				{
					switch (GetSkillPreferenceFromLoadout(loadout, 0))
					{
					case 0u:
						Items.LunarSecondaryReplacement.pickupToken = visionsShortDescriptionToken;
						Items.LunarSecondaryReplacement.descriptionToken = visionsLongDescriptionToken;
						break;
					case 1u:
					{
						string skillLangTokenName3 = new BloodSecondarySkill().SkillLangTokenName;
						Items.LunarSecondaryReplacement.pickupToken = SkillBase.Token + skillLangTokenName3 + SkillBase.ShortDescToken;
						Items.LunarSecondaryReplacement.descriptionToken = SkillBase.Token + skillLangTokenName3 + SkillBase.FullDescToken;
						break;
					}
					}
				}
				if ((Object)(object)itemDef == (Object)(object)Items.LunarUtilityReplacement)
				{
					switch (GetSkillPreferenceFromLoadout(loadout, 0))
					{
					case 0u:
						Items.LunarUtilityReplacement.pickupToken = stridesShortDescriptionToken;
						Items.LunarUtilityReplacement.descriptionToken = stridesLongDescriptionToken;
						break;
					case 1u:
					{
						string skillLangTokenName4 = new BloodUtilitySkill().SkillLangTokenName;
						Items.LunarUtilityReplacement.pickupToken = SkillBase.Token + skillLangTokenName4 + SkillBase.ShortDescToken;
						Items.LunarUtilityReplacement.descriptionToken = SkillBase.Token + skillLangTokenName4 + SkillBase.FullDescToken;
						break;
					}
					}
				}
				if ((Object)(object)itemDef == (Object)(object)Items.LunarSpecialReplacement)
				{
					switch (GetSkillPreferenceFromLoadout(loadout, 0))
					{
					case 0u:
						Items.LunarSpecialReplacement.pickupToken = essenceShortDescriptionToken;
						Items.LunarSpecialReplacement.descriptionToken = essenceLongDescriptionToken;
						break;
					case 1u:
					{
						string skillLangTokenName5 = new BloodSpecialSkill().SkillLangTokenName;
						Items.LunarSpecialReplacement.pickupToken = SkillBase.Token + skillLangTokenName5 + SkillBase.ShortDescToken;
						Items.LunarSpecialReplacement.descriptionToken = SkillBase.Token + skillLangTokenName5 + SkillBase.FullDescToken;
						break;
					}
					}
				}
			}
			orig.Invoke(self, itemIndex, count);
		}

		private static SkillDef GetSkillPreferenceFromLoadout(Loadout loadout, int skillSlot, SkillDef defaultSkill)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			SkillDef result = defaultSkill;
			uint skillPreferenceFromLoadout = GetSkillPreferenceFromLoadout(loadout, skillSlot);
			if (skillPreferenceFromLoadout != 0)
			{
				BodyLoadout readOnlyBodyLoadout = loadout.bodyLoadoutManager.GetReadOnlyBodyLoadout(hereticBodyIndex);
				result = readOnlyBodyLoadout.GetSkillFamily(skillSlot).variants[skillPreferenceFromLoadout].skillDef;
			}
			return result;
		}

		private static uint GetSkillPreferenceFromLoadout(Loadout loadout, int skillSlot)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//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_003e: Unknown result type (might be due to invalid IL or missing references)
			if (loadout == null || loadout.bodyLoadoutManager == null)
			{
				Debug.Log((object)"WTF!");
				return 0u;
			}
			if ((int)hereticBodyIndex != -1)
			{
				hereticBodyIndex = BodyCatalog.FindBodyIndex(hereticBodyPrefab);
			}
			return loadout.bodyLoadoutManager.GetSkillVariant(hereticBodyIndex, skillSlot);
		}

		private static void InitializePrefab()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			GameObject val = LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterBodies/HereticBody");
			hereticPrefab = PrefabAPI.InstantiateClone(val, hereticBodyName);
			hereticBodyPrefab = hereticPrefab.GetComponent<CharacterBody>();
			Assets.RegisterBodyPrefab(hereticPrefab);
			hereticDisplayPrefab = PrefabAPI.InstantiateClone(((Component)hereticPrefab.GetComponent<ModelLocator>().modelBaseTransform).gameObject, "HereticUnchainedDisplay");
			hereticDisplayPrefab.transform.localScale = Vector3.one * 0.7f;
			hereticDisplayPrefab.AddComponent<NetworkIdentity>();
			hereticDisplayPrefab.AddComponent<HereticMenuAnimation>();
			Animator component = ((Component)hereticPrefab.GetComponent<ModelLocator>().modelTransform).GetComponent<Animator>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				Debug.Log((object)"Heretic has no animator?");
			}
			CharacterMaster.Start += new hook_Start(AddHeresyItems);
			CharacterBody.ReplaceSkillIfItemPresent += new hook_ReplaceSkillIfItemPresent(SkillReplacementIntercept);
			Inventory.GiveItem_ItemIndex_int += new hook_GiveItem_ItemIndex_int(InterceptPickupToken);
		}

		private static void InitializeSkins()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = ((Component)hereticPrefab.GetComponentInChildren<ModelLocator>().modelTransform).gameObject;
			CharacterModel component = gameObject.GetComponent<CharacterModel>();
			Object.DestroyImmediate((Object)(object)gameObject.GetComponent<ModelSkinController>());
			ModelSkinController val = gameObject.AddComponent<ModelSkinController>();
			ChildLocator component2 = gameObject.GetComponent<ChildLocator>();
			SkinnedMeshRenderer mainSkinnedMeshRenderer = component.mainSkinnedMeshRenderer;
			RendererInfo[] baseRendererInfos = component.baseRendererInfos;
			List<SkinDef> list = new List<SkinDef>();
			SkinDef item = Skins.CreateSkinDef("Default", LoadoutAPI.CreateSkinIcon(new Color(0.7f, 0.05f, 0.1f), new Color(0.6f, 0.5f, 0.6f), new Color(0.1f, 0.1f, 0.15f), new Color(0.15f, 0.1f, 0.2f)), baseRendererInfos, mainSkinnedMeshRenderer, gameObject);
			list.Add(item);
			val.skins = list.ToArray();
		}

		private static void CreateSkillFamilies(GameObject targetPrefab)
		{
			GenericSkill[] componentsInChildren = targetPrefab.GetComponentsInChildren<GenericSkill>();
			foreach (GenericSkill val in componentsInChildren)
			{
				Object.DestroyImmediate((Object)(object)val);
			}
			skillLocator = targetPrefab.GetComponent<SkillLocator>();
			SkillBase.characterSkillLocators.Add(hereticBodyName, skillLocator);
			skillLocator.passiveSkill.enabled = true;
			skillLocator.passiveSkill.skillNameToken = "HERETIC_PASSIVE_NAME";
			skillLocator.passiveSkill.skillDescriptionToken = "HERETIC_PASSIVE_DESC";
			skillLocator.passiveSkill.icon = iconBundle.LoadAsset<Sprite>(iconsPath + "DissidentWill.png");
			skillLocator.primary = targetPrefab.AddComponent<GenericSkill>();
			primaryFamily = ScriptableObject.CreateInstance<SkillFamily>();
			((Object)primaryFamily).name = ((Object)targetPrefab).name + "PrimaryFamily";
			primaryFamily.variants = (Variant[])(object)new Variant[0];
			skillLocator.primary._skillFamily = primaryFamily;
			skillLocator.secondary = targetPrefab.AddComponent<GenericSkill>();
			secondaryFamily = ScriptableObject.CreateInstance<SkillFamily>();
			((Object)secondaryFamily).name = ((Object)targetPrefab).name + "SecondaryFamily";
			secondaryFamily.variants = (Variant[])(object)new Variant[0];
			skillLocator.secondary._skillFamily = secondaryFamily;
			skillLocator.utility = targetPrefab.AddComponent<GenericSkill>();
			utilityFamily = ScriptableObject.CreateInstance<SkillFamily>();
			((Object)utilityFamily).name = ((Object)targetPrefab).name + "UtilityFamily";
			utilityFamily.variants = (Variant[])(object)new Variant[0];
			skillLocator.utility._skillFamily = utilityFamily;
			skillLocator.special = targetPrefab.AddComponent<GenericSkill>();
			specialFamily = ScriptableObject.CreateInstance<SkillFamily>();
			((Object)specialFamily).name = ((Object)targetPrefab).name + "SpecialFamily";
			specialFamily.variants = (Variant[])(object)new Variant[0];
			skillLocator.special._skillFamily = specialFamily;
			Assets.RegisterSkillFamily(primaryFamily);
			Assets.RegisterSkillFamily(secondaryFamily);
			Assets.RegisterSkillFamily(utilityFamily);
			Assets.RegisterSkillFamily(specialFamily);
		}
	}
	internal static class Tools
	{
		public static string modPrefix = string.Format("@{0}+{1}", "ArtificerExtended", "artiskillicons");

		public static AssetBundle LoadAssetBundle(byte[] resourceBytes)
		{
			if (resourceBytes == null)
			{
				throw new ArgumentNullException("resourceBytes");
			}
			return AssetBundle.LoadFromMemory(resourceBytes);
		}

		public static string GetModPrefix(this BaseUnityPlugin plugin, string bundleName)
		{
			return $"@{plugin.Info.Metadata.Name}+{bundleName}";
		}

		internal static bool isLoaded(string modguid)
		{
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				string key = pluginInfo.Key;
				PluginInfo value = pluginInfo.Value;
				if (key == modguid)
				{
					return true;
				}
			}
			return false;
		}

		internal static string ConvertDecimal(float d)
		{
			return d * 100f + "%";
		}

		internal static void GetMaterial(GameObject model, string childObject, Color color, ref Material material, float scaleMultiplier = 1f, bool replaceAll = false)
		{
			//IL_0030: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = model.GetComponentsInChildren<Renderer>();
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				Renderer val2 = val;
				if (string.Equals(((Object)val).name, childObject))
				{
					if (color == Color.clear)
					{
						Object.Destroy((Object)(object)val);
						break;
					}
					if ((Object)(object)material == (Object)null)
					{
						material = new Material(val.material);
						material.mainTexture = val.material.mainTexture;
						material.shader = val.material.shader;
						material.color = color;
					}
					val.material = material;
					Transform transform = ((Component)val).transform;
					transform.localScale *= scaleMultiplier;
					if (!replaceAll)
					{
						break;
					}
				}
			}
		}

		internal static void DebugMaterial(GameObject model)
		{
			Renderer[] componentsInChildren = model.GetComponentsInChildren<Renderer>();
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				Renderer val2 = val;
				Debug.Log((object)("Material: " + ((Object)val2).name.ToString()));
			}
		}

		internal static void GetParticle(GameObject model, string childObject, Color color, float sizeMultiplier = 1f, bool replaceAll = false)
		{
			//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)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystem[] componentsInChildren = model.GetComponentsInChildren<ParticleSystem>();
			ParticleSystem[] array = componentsInChildren;
			foreach (ParticleSystem val in array)
			{
				ParticleSystem val2 = val;
				MainModule main = val2.main;
				ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
				ColorBySpeedModule colorBySpeed = val2.colorBySpeed;
				if (string.Equals(((Object)val2).name, childObject))
				{
					((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(color);
					((MainModule)(ref main)).startSizeMultiplier = ((MainModule)(ref main)).startSizeMultiplier * sizeMultiplier;
					((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(color);
					((ColorBySpeedModule)(ref colorBySpeed)).color = MinMaxGradient.op_Implicit(color);
					if (!replaceAll)
					{
						break;
					}
				}
			}
		}

		internal static void DebugParticleSystem(GameObject model)
		{
			ParticleSystem[] componentsInChildren = model.GetComponentsInChildren<ParticleSystem>();
			ParticleSystem[] array = componentsInChildren;
			foreach (ParticleSystem val in array)
			{
				ParticleSystem val2 = val;
				Debug.Log((object)("Particle: " + ((Object)val2).name.ToString()));
			}
		}

		internal static void GetLight(GameObject model, string childObject, Color color, bool replaceAll = false)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Light[] componentsInChildren = model.GetComponentsInChildren<Light>();
			Light[] array = componentsInChildren;
			foreach (Light val in array)
			{
				Light val2 = val;
				if (string.Equals(((Object)val2).name, childObject))
				{
					val2.color = color;
					if (!replaceAll)
					{
						break;
					}
				}
			}
		}

		internal static void DebugLight(GameObject model)
		{
			Light[] componentsInChildren = model.GetComponentsInChildren<Light>();
			Light[] array = componentsInChildren;
			foreach (Light val in array)
			{
				Light val2 = val;
				Debug.Log((object)("Light: " + ((Object)val2).name.ToString()));
			}
		}

		public static T GetCopyOf<T>(this Component comp, T other) where T : Component
		{
			Type type = ((object)comp).GetType();
			if (type != ((object)other).GetType())
			{
				return default(T);
			}
			BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			PropertyInfo[] properties = type.GetProperties(bindingAttr);
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				if (propertyInfo.CanWrite)
				{
					try
					{
						propertyInfo.SetValue(comp, propertyInfo.GetValue(other, null), null);
					}
					catch
					{
					}
				}
			}
			FieldInfo[] fields = type.GetFields(bindingAttr);
			FieldInfo[] array2 = fields;
			foreach (FieldInfo fieldInfo in array2)
			{
				fieldInfo.SetValue(comp, fieldInfo.GetValue(other));
			}
			return (T)(object)((comp is T) ? comp : null);
		}

		public static T AddComponent<T>(this GameObject go, T toAdd) where T : Component
		{
			return ((Component)(object)go.AddComponent<T>()).GetCopyOf(toAdd);
		}
	}
}
namespace HereticUnchained.Unlocks
{
	internal static class ArrayHelper
	{
		public static T[] Append<T>(ref T[] array, List<T> list)
		{
			int num = array.Length;
			int count = list.Count;
			Array.Resize(ref array, num + count);
			list.CopyTo(array, num);
			return array;
		}

		public static Func<T[], T[]> AppendDel<T>(List<T> list)
		{
			return (T[] r) => Append(ref r, list);
		}
	}
	internal static class UnlockableAPI
	{
		internal struct UnlockableInfo
		{
			internal string Name;

			internal Func<string> HowToUnlockString;

			internal Func<string> UnlockedString;

			internal int SortScore;
		}

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

		internal static List<AchievementDef> achievementDefs = new List<AchievementDef>();

		internal static List<UnlockableDef> unlockableDefs = new List<UnlockableDef>();

		private static readonly List<(AchievementDef achDef, UnlockableDef unlockableDef, string unlockableName)> moddedUnlocks = new List<(AchievementDef, UnlockableDef, string)>();

		private static bool addingUnlockables;

		public static bool ableToAdd { get; private set; } = false;


		internal static UnlockableDef CreateNewUnlockable(UnlockableInfo unlockableInfo)
		{
			UnlockableDef val = ScriptableObject.CreateInstance<UnlockableDef>();
			val.nameToken = unlockableInfo.Name;
			val.cachedName = unlockableInfo.Name;
			val.getHowToUnlockString = unlockableInfo.HowToUnlockString;
			val.getUnlockedString = unlockableInfo.UnlockedString;
			val.sortScore = unlockableInfo.SortScore;
			return val;
		}

		public static UnlockableDef AddUnlockable<TUnlockable>(bool serverTracked) where TUnlockable : BaseAchievement, IModdedUnlockableDataProvider, new()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			TUnlockable instance = new TUnlockable();
			string unlockableIdentifier = instance.UnlockableIdentifier;
			if (!usedRewardIds.Add(unlockableIdentifier))
			{
				throw new InvalidOperationException("The unlockable identifier '" + unlockableIdentifier + "' is already used by another mod or the base game.");
			}
			AchievementDef val = new AchievementDef
			{
				identifier = instance.AchievementIdentifier,
				unlockableRewardIdentifier = unlockableIdentifier,
				prerequisiteAchievementIdentifier = instance.PrerequisiteUnlockableIdentifier,
				nameToken = instance.AchievementNameToken,
				descriptionToken = instance.AchievementDescToken,
				achievedIcon = instance.Sprite,
				type = instance.GetType(),
				serverTrackerType = (serverTracked ? instance.GetType() : null)
			};
			Func<string> howToUnlockString = () => Language.GetStringFormatted("UNLOCK_VIA_ACHIEVEMENT_FORMAT", new object[2]
			{
				Language.GetString(instance.AchievementNameToken),
				Language.GetString(instance.AchievementDescToken)
			});
			Func<string> unlockedString = () => Language.GetStringFormatted("UNLOCK_VIA_ACHIEVEMENT_FORMAT", new object[2]
			{
				Language.GetString(instance.AchievementNameToken),
				Language.GetString(instance.AchievementDescToken)
			});
			UnlockableInfo unlockableInfo = default(UnlockableInfo);
			unlockableInfo.Name = unlockableIdentifier;
			unlockableInfo.HowToUnlockString = howToUnlockString;
			unlockableInfo.UnlockedString = unlockedString;
			unlockableInfo.SortScore = 200;
			UnlockableDef val2 = CreateNewUnlockable(unlockableInfo);
			unlockableDefs.Add(val2);
			achievementDefs.Add(val);
			moddedUnlocks.Add((val, val2, unlockableIdentifier));
			if (!addingUnlockables)
			{
				addingUnlockables = true;
				AchievementManager.CollectAchievementDefs += new Manipulator(CollectAchievementDefs);
				UnlockableCatalog.Init += new Manipulator(Init_Il);
			}
			return val2;
		}

		public static ILCursor CallDel_<TDelegate>(this ILCursor cursor, TDelegate target, out int index) where TDelegate : Delegate
		{
			index = cursor.EmitDelegate<TDelegate>(target);
			return cursor;
		}

		public static ILCursor CallDel_<TDelegate>(this ILCursor cursor, TDelegate target) where TDelegate : Delegate
		{
			int index;
			return cursor.CallDel_(target, out index);
		}

		private static void Init_Il(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			new ILCursor(il).GotoNext((MoveType)1, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, typeof(UnlockableCatalog), "SetUnlockableDefs")
			}).CallDel_(ArrayHelper.AppendDel(unlockableDefs));
		}

		private static void CollectAchievementDefs(ILContext il)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			FieldInfo field = typeof(AchievementManager).GetField("achievementIdentifiers", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if ((object)field == null)
			{
				throw new NullReferenceException("Could not find field in AchievementManager");
			}
			ILCursor val = new ILCursor(il);
			val.GotoNext((MoveType)2, new Func<Instruction, bool>[2]
			{
				(Instruction x) => ILPatternMatchingExt.MatchEndfinally(x),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, 1)
			});
			val.Emit(OpCodes.Ldarg_0);
			val.Emit(OpCodes.Ldsfld, field);
			val.EmitDelegate<Action<List<AchievementDef>, Dictionary<string, AchievementDef>, List<string>>>((Action<List<AchievementDef>, Dictionary<string, AchievementDef>, List<string>>)EmittedDelegate);
			val.Emit(OpCodes.Ldloc_1);
			static void EmittedDelegate(List<AchievementDef> list, Dictionary<string, AchievementDef> map, List<string> identifiers)
			{
				ableToAdd = false;
				for (int i = 0; i < moddedUnlocks.Count; i++)
				{
					var (val2, val3, text) = moddedUnlocks[i];
					if (val2 != null)
					{
						identifiers.Add(val2.identifier);
						list.Add(val2);
						map.Add(val2.identifier, val2);
					}
				}
			}
		}
	}
	internal interface IModdedUnlockableDataProvider
	{
		string AchievementIdentifier { get; }

		string UnlockableIdentifier { get; }

		string AchievementNameToken { get; }

		string PrerequisiteUnlockableIdentifier { get; }

		string UnlockableNameToken { get; }

		string AchievementDescToken { get; }

		Sprite Sprite { get; }
	}
	public abstract class ModdedUnlockable : BaseAchievement, IModdedUnlockableDataProvider
	{
		public abstract bool ForceDisable { get; }

		public abstract string AchievementIdentifier { get; }

		public abstract string UnlockableIdentifier { get; }

		public abstract string AchievementNameToken { get; }

		public abstract string PrerequisiteUnlockableIdentifier { get; }

		public abstract string UnlockableNameToken { get; }

		public abstract string AchievementDescToken { get; }

		public abstract Sprite Sprite { get; }

		public override bool wantsBodyCallbacks => ((BaseAchievement)this).wantsBodyCallbacks;

		public void Revoke()
		{
			if (((BaseAchievement)this).userProfile.HasAchievement(AchievementIdentifier))
			{
				((BaseAchievement)this).userProfile.RevokeAchievement(AchievementIdentifier);
			}
			((BaseAchievement)this).userProfile.RevokeUnlockable(UnlockableCatalog.GetUnlockableDef(UnlockableIdentifier));
		}

		public override void OnGranted()
		{
			((BaseAchievement)this).OnGranted();
		}

		public override void OnInstall()
		{
			((BaseAchievement)this).OnInstall();
		}

		public override void OnUninstall()
		{
			((BaseAchievement)this).OnUninstall();
		}

		public override float ProgressForAchievement()
		{
			return ((BaseAchievement)this).ProgressForAchievement();
		}

		public override BodyIndex LookUpRequiredBodyIndex()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return ((BaseAchievement)this).LookUpRequiredBodyIndex();
		}

		public override void OnBodyRequirementBroken()
		{
			((BaseAchievement)this).OnBodyRequirementBroken();
		}

		public override void OnBodyRequirementMet()
		{
			((BaseAchievement)this).OnBodyRequirementMet();
		}
	}
	internal class HereticGlobalUnlock : UnlockBase
	{
		public override string UnlockLangTokenName => "GLOBALHERETICUNLOCK";

		public override string UnlockName => "Complete Unorthodoxy";

		public override string AchievementName => "Complete Unorthodoxy";

		public override string AchievementDesc => "As any character, beat the game having committed the greatest act of Heresy.";

		public override string PrerequisiteUnlockableIdentifier => "KillBossQuantityInRun";

		public override Sprite Sprite => LegacyResourcesAPI.Load<Sprite>("textures/bodyicons/texHereticIcon");

		public static string HereticGlobalUnlockString()
		{
			return new HereticGlobalUnlock().UnlockLangTokenName;
		}

		public override void Init(ConfigFile config)
		{
			LanguageAPI.Add(AchievementNameToken, AchievementName);
			LanguageAPI.Add(AchievementDescToken, AchievementDesc);
			LanguageAPI.Add(UnlockableNameToken, UnlockName);
		}

		public override void OnBodyRequirementMet()
		{
			base.OnBodyRequirementMet();
		}

		public override void OnBodyRequirementBroken()
		{
			base.OnBodyRequirementBroken();
		}

		public void ClearCheck(Run run, RunReport runReport)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (run == null || runReport == null || !Object.op_Implicit((Object)(object)runReport.gameEnding))
			{
				return;
			}
			Debug.Log((object)"FUCK!!!!!!!!!!");
			if (runReport.gameEnding.isWin)
			{
				ItemIndex[] itemAcquisitionOrder = runReport.FindFirstPlayerInfo().itemAcquisitionOrder;
				List<ItemIndex> list = new List<ItemIndex>(itemAcquisitionOrder);
				if (list.Contains(Items.LunarPrimaryReplacement.itemIndex) && list.Contains(Items.LunarSecondaryReplacement.itemIndex) && list.Contains(Items.LunarUtilityReplacement.itemIndex) && list.Contains(Items.LunarSpecialReplacement.itemIndex))
				{
					((BaseAchievement)this).Grant();
				}
			}
		}

		public override void OnInstall()
		{
			base.OnInstall();
			Run.onClientGameOverGlobal += ClearCheck;
		}

		public override void OnUninstall()
		{
			base.OnUninstall();
			Run.onClientGameOverGlobal -= ClearCheck;
		}
	}
	internal class HereticMastery : UnlockBase
	{
		public override bool HideUnlock => true;

		public override string UnlockLangTokenName => "HERETICMASTERYUNLOCK";

		public override string UnlockName => "Borderline Excessive Unorthodoxy";

		public override string AchievementName => "Borderline Excessive Unorthodoxy";

		public override string AchievementDesc => "As any character on Monsoon difficulty, beat the game having committed the greatest act of Heresy.";

		public override string PrerequisiteUnlockableIdentifier => "KillBossQuantityInRun";

		public override Sprite Sprite => LoadoutAPI.CreateSkinIcon(new Color(0.15f, 0.15f, 0.15f), new Color(0.15f, 0.15f, 0.15f), new Color(0.15f, 0.15f, 0.15f), new Color(0.15f, 0.15f, 0.15f));

		public override void Init(ConfigFile config)
		{
			LanguageAPI.Add(AchievementNameToken, AchievementName);
			LanguageAPI.Add(AchievementDescToken, AchievementDesc);
			LanguageAPI.Add(UnlockableNameToken, UnlockName);
		}
	}
	public abstract class UnlockBase<T> : UnlockBase where T : UnlockBase<T>
	{
		public static T instance { get; private set; }

		public UnlockBase()
		{
			if (instance != null)
			{
				throw new InvalidOperationException("Singleton class \"" + typeof(T).Name + "\" inheriting UnlockBase was instantiated twice");
			}
			instance = this as T;
		}
	}
	public abstract class UnlockBase : ModdedUnlockable
	{
		public static string Token = HereticPlugin.TokenName + "UNLOCK_";

		public abstract string UnlockLangTokenName { get; }

		public abstract string UnlockName { get; }

		public abstract string AchievementName { get; }

		public abstract string AchievementDesc { get; }

		public override bool ForceDisable => false;

		public override string AchievementIdentifier => Token + UnlockLangTokenName + "_ACHIEVEMENT_ID";

		public override string UnlockableIdentifier => Token + UnlockLangTokenName + "_REWARD_ID";

		public override string AchievementNameToken => Token + UnlockLangTokenName + "_ACHIEVEMENT_NAME";

		public override string AchievementDescToken => Token + UnlockLangTokenName + "_ACHIEVEMENT_DESC";

		public override string UnlockableNameToken => Token + UnlockLangTokenName + "_UNLOCKABLE_NAME";

		public virtual bool HideUnlock => false;

		internal Sprite GetSpriteProvider(string iconName)
		{
			return null;
		}

		public override BodyIndex LookUpRequiredBodyIndex()
		{
			//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_000e: Unknown result type (might be due to invalid IL or missing references)
			return BodyCatalog.FindBodyIndex("HereticBody");
		}

		public abstract void Init(ConfigFile config);

		protected void CreateLang()
		{
			LanguageAPI.Add(AchievementNameToken, "Heretic: " + AchievementName);
			LanguageAPI.Add(AchievementDescToken, "As The Heretic, " + AchievementDesc);
			LanguageAPI.Add(UnlockableNameToken, "Heretic: " + UnlockName);
		}
	}
}
namespace HereticUnchained.Skills
{
	internal class BloodPrimarySkill : SkillBase
	{
		public static GameObject tracerLaser;

		public override string SkillName => "Sanguine Verdict";

		public override string SkillDescription => "<style=cIsHealth>" + Tools.ConvertDecimal(BloodPrimary.healthCostFraction) + " HP</style>. <style=cIsDamage>Slayer</style>. " + $"Fire a laser <style=cIsDamage>{BloodPrimary.baseFireRate}x</style> per second that " + "deals <style=cIsDamage>" + Tools.ConvertDecimal(BloodPrimary.damageCoefficient) + " damage</style>.";

		public override string SkillFullDescription => "<style=cIsHealth>" + Tools.ConvertDecimal(BloodPrimary.healthCostFraction) + " HP</style>. <style=cIsDamage>Slayer</style>. Fire an intense laser " + $"<style=cIsDamage>{BloodPrimary.baseFireRate}</style> <style=cStack>(+{BloodPrimary.stackFireRate} per stack)</style> times per second " + "that deals <style=cIsDamage>" + Tools.ConvertDecimal(BloodPrimary.damageCoefficient) + " damage</style>.";

		public override string SkillLangTokenName => "BLOODPRIMARY";

		public override UnlockableDef UnlockDef => null;

		public override string IconName => "SanguineVerdict";

		public override Type ActivationState => typeof(BloodPrimary);

		public override string CharacterName => HereticPlugin.hereticBodyName;

		public override SkillFamilyName SkillSlot => SkillFamilyName.Primary;

		public override SimpleSkillData SkillData => new SimpleSkillData(1, 1f, beginSkillCooldownOnSkillEnd: false, canceledFromSprinting: false, cancelSprintingOnActivation: true, dontAllowPastMaxStocks: true, fullRestockOnAssign: true, (InterruptPriority)0)
		{
			stockToConsume = 0,
			requiredStock = 0,
			cancelSprintingOnActivation = true,
			interruptPriority = (InterruptPriority)0
		};

		public override Type BaseSkillDef => typeof(SkillDef);

		public override void Hooks()
		{
		}

		public override void Init(ConfigFile config)
		{
			KeywordTokens = new string[2] { "KEYWORD_PERCENT_HP", "KEYWORD_SLAYER" };
			CreateLang();
			CreateSkill();
			Hooks();
			CreateTracer();
		}

		private void CreateTracer()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			tracerLaser = PrefabAPI.InstantiateClone(LegacyResourcesAPI.Load<GameObject>("prefabs/effects/tracers/TracerGolem"), "HereticBloodLaser", false);
			Tracer component = tracerLaser.GetComponent<Tracer>();
			component.speed = 300f;
			component.length = 15f;
			component.beamDensity = 10f;
			VFXAttributes val = tracerLaser.AddComponent<VFXAttributes>();
			val.vfxPriority = (VFXPriority)2;
			val.vfxIntensity = (VFXIntensity)2;
			Tools.GetParticle(tracerLaser, "SmokeBeam", new Color(0.2f, 0.05f, 0.15f), 0.5f);
			MainModule main = tracerLaser.GetComponentInChildren<ParticleSystem>().main;
			((MainModule)(ref main)).startSizeXMultiplier = ((MainModule)(ref main)).startSizeXMultiplier * 0.4f;
			((MainModule)(ref main)).startSizeYMultiplier = ((MainModule)(ref main)).startSizeYMultiplier * 0.4f;
			((MainModule)(ref main)).startSizeZMultiplier = ((MainModule)(ref main)).startSizeZMultiplier * 2f;
			Assets.CreateEffect(tracerLaser);
		}
	}
	internal class BloodSecondarySkill : SkillBase
	{
		public override string SkillName => "Touch of Malice";

		public override string SkillDescription => "Slash through enemies in front of you, crippling them and yourself.";

		public override string SkillFullDescription => "Hold to slash through enemies in front of you, dealing X% damage and crippling every target hit including yourself for Y seconds.";

		public override string SkillLangTokenName => "BLOODSECONDARY";

		public override UnlockableDef UnlockDef => null;

		public override string IconName => "";

		public override Type ActivationState => typeof(BloodSecondary);

		public override Type BaseSkillDef => typeof(SkillDef);

		public override string CharacterName => HereticPlugin.hereticBodyName;

		public override SkillFamilyName SkillSlot => SkillFamilyName.Secondary;

		public override SimpleSkillData SkillData => new SimpleSkillData(1, 1f, beginSkillCooldownOnSkillEnd: false, canceledFromSprinting: false, cancelSprintingOnActivation: true, dontAllowPastMaxStocks: true, fullRestockOnAssign: true, (InterruptPriority)0)
		{
			stockToConsume = 1,
			requiredStock = 1,
			cancelSprintingOnActivation = true,
			interruptPriority = (InterruptPriority)0
		};

		public override void Hooks()
		{
		}

		public override void Init(ConfigFile config)
		{
		}
	}
	internal class BloodSpecialSkill : SkillBase
	{
		public override string SkillName => "Weeping Lesions";

		public override string SkillDescription => "Hold to <style=cIsDamage>root yourself</style> in place, channeling a <style=cIsDamage>barrage of blades</style> that <style=cIsDamage>bleeds</style> everything in sight for <style=cIsDamage>" + Tools.ConvertDecimal(BloodSpecial.bleedDurationBase * 0.8f) + " damage</style>... <style=cIsHealth>including yourself</style>.";

		public override string SkillFullDescription => "Hold to <style=cIsDamage>root yourself</style> in place, channeling a <style=cIsDamage>barrage of blades</style> that <style=cIsDamage>bleeds</style> EVERYTHING in sight for <style=cIsDamage>" + Tools.ConvertDecimal(BloodSpecial.bleedDurationBase * 0.8f) + " damage</style> <style=cIsStack>(+" + Tools.ConvertDecimal(BloodSpecial.bleedDurationBase * 0.8f) + " per stack)</style>... <style=cIsHealth>including yourself</style>. " + $"Recharges after {SkillData.baseRechargeInterval} " + $"<style=cIsStack>(+{LunarLesionsSkillDef.cooldownPerStack} per stack)</style> seconds.";

		public override string SkillLangTokenName => "BLOODSPECIAL";

		public override UnlockableDef UnlockDef => null;

		public override string IconName => "";

		public override Type ActivationState => typeof(BloodSpecial);

		public override string CharacterName => HereticPlugin.hereticBodyName;

		public override SkillFamilyName SkillSlot => SkillFamilyName.Special;

		public override SimpleSkillData SkillData => new SimpleSkillData(1, 1f, beginSkillCooldownOnSkillEnd: false, canceledFromSprinting: false, cancelSprintingOnActivation: true, dontAllowPastMaxStocks: true, fullRestockOnAssign: true, (InterruptPriority)0)
		{
			interruptPriority = (InterruptPriority)1,
			baseRechargeInterval = 15f,
			canceledFromSprinting = true,
			beginSkillCooldownOnSkillEnd = true
		};

		public override Type BaseSkillDef => typeof(LunarLesionsSkillDef);

		public override void Hooks()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			CharacterBody.RecalculateStats += new hook_RecalculateStats(RootChange);
		}

		private void RootChange(orig_RecalculateStats orig, CharacterBody self)
		{
			orig.Invoke(self);
			if (self.HasBuff(Buffs.LunarSecondaryRoot) || self.HasBuff(Buffs.Nullified))
			{
				self.jumpPower = 0f;
			}
		}

		public override void Init(ConfigFile config)
		{
			CreateLang();
			CreateSkill();
			Hooks();
		}
	}
	internal class BloodUtilitySkill : SkillBase
	{
		public static float vampirismHealFraction = 0.08f;

		public static float vampirismMaxHealPortion = 0.1f;

		public static GameObject stormPrefab;

		public static float stormDuration = 3f;

		public static string vampirismKeywordToken = HereticPlugin.TokenName + "KEYWORD_VAMPIRISM";

		public override string SkillName => "Duskwarp";

		public override string SkillDescription => "<style=cIsHealing>Vampiric</style>. Dash backwards, leaving behind a <style=cIsDamage>slicing vortex</style> that deals <style=cIsDamage>" + Tools.ConvertDecimal(BloodUtility.damageCoefficient) + " damage per second</style>.";

		public override string SkillFullDescription => "Your attacks <style=cIsHealing>heal</style> for <style=cIsHealing>" + Tools.ConvertDecimal(vampirismHealFraction) + " of damage dealt</style>." + $"Dash backwards, leaving behind a <style=cIsDamage>slicing vortex</style> for {stormDuration} seconds that deals " + "<style=cIsDamage>" + Tools.ConvertDecimal(BloodUtility.damageCoefficient * stormDuration) + "</style> " + $"<style=cIsStack>(+{BloodUtility.damageCoefficient * stormDuration} per stack)</style> damage. " + $"Recharges after {SkillData.baseRechargeInterval} " + $"<style=cIsStack>(+{LunarVampirismSkillDef.cooldownPerStack} per stack)</style> seconds.";

		public override string SkillLangTokenName => "VAMPIREUTILITY";

		public override UnlockableDef UnlockDef => null;

		public override string IconName => "Duskwarp";

		public override Type ActivationState => typeof(BloodUtility);

		public override string CharacterName => HereticPlugin.hereticBodyName;

		public override SkillFamilyName SkillSlot => SkillFamilyName.Utility;

		public override SimpleSkillData SkillData => new SimpleSkillData(1, 1f, beginSkillCooldownOnSkillEnd: false, canceledFromSprinting: false, cancelSprintingOnActivation: true, dontAllowPastMaxStocks: true, fullRestockOnAssign: true, (InterruptPriority)0)
		{
			baseMaxStock = 1,
			baseRechargeInterval = 9f,
			interruptPriority = (InterruptPriority)2
		};

		public override Type BaseSkillDef => typeof(LunarVampirismSkillDef);

		public override void Hooks()
		{
		}

		public override void Init(ConfigFile config)
		{
			KeywordTokens = new string[1] { vampirismKeywordToken };
			LanguageAPI.Add(vampirismKeywordToken, "<style=cKeywordName>Vampiric</style><style=cSub>PASSIVE: While this skill is ready to use, <style=cIsDamage>your attacks</style> can <style=cIsHealing>heal</style> for <style=cIsHealing>" + Tools.ConvertDecimal(vampirismHealFraction) + "</style> of <style=cIsDamage>total damage</style>.");
			CreateLang();
			CreateSkill();
			Hooks();
			CreateStorm();
		}

		private void CreateStorm()
		{
			stormPrefab = PrefabAPI.InstantiateClone(LegacyResourcesAPI.Load<GameObject>("prefabs/projectiles/FireTornado"), "HeresyVampireStorm", true);
			Tools.DebugParticleSystem(stormPrefab);
			ProjectileOverlapAttack component = stormPrefab.GetComponent<ProjectileOverlapAttack>();
			component.overlapProcCoefficient = 0.75f;
			component.damageCoefficient = component.resetInterval;
			ProjectileSimple component2 = stormPrefab.GetComponent<ProjectileSimple>();
			component2.lifetime = 3f;
		}
	}
	internal class MassPrimarySkill : SkillBase
	{
		public static int baseMaxStock = 2;

		public static float baseRechargeInterval = 2f;

		public override string SkillName => "Blind Allegiance";

		public override string SkillDescription => "Warp forward a short distance, splicing nearby enemies.";

		public override string SkillFullDescription => $"Warp forward {0} meters, " + "splicing enemies in your immediate vicinity for " + Tools.ConvertDecimal(0f) + " damage. " + $"Hold up to {baseMaxStock} charges (+{baseMaxStock} per stack) that " + $"reload after {baseRechargeInterval} seconds (+{baseRechargeInterval} per stack).";

		public override string SkillLangTokenName => "MASSPRIMARY";

		public override UnlockableDef UnlockDef => null;

		public override string IconName => "";

		public override Type ActivationState => typeof(MassPrimary);

		public override Type BaseSkillDef => typeof(LunarPrimaryReplacementSkill);

		public override string CharacterName => HereticPlugin.hereticBodyName;

		public override SkillFamilyName SkillSlot => SkillFamilyName.Primary;

		public override SimpleSkillData SkillData => new SimpleSkillData(1, 1f, beginSkillCooldownOnSkillEnd: false, canceledFromSprinting: false, cancelSprintingOnActivation: true, dontAllowPastMaxStocks: true, fullRestockOnAssign: true, (InterruptPriority)0)
		{
			stockToConsume = 1,
			requiredStock = 1,
			cancelSprintingOnActivation = true,
			interruptPriority = (InterruptPriority)0,
			baseMaxStock = baseMaxStock,
			baseRechargeInterval = baseRechargeInterval,
			resetCooldownTimerOnUse = false,
			mustKeyPress = true
		};

		public override void Hooks()
		{
		}

		public override void Init(ConfigFile config)
		{
		}
	}
	public abstract class ScepterSkillBase<T> : ScepterSkillBase where T : ScepterSkillBase<T>
	{
		public static T instance { get; private set; }

		public ScepterSkillBase()
		{
			if (instance != null)
			{
				throw new InvalidOperationException("Singleton class \"" + typeof(T).Name + "\" inheriting ArtificerExtended SkillBase was instantiated twice");
			}
			instance = this as T;
		}
	}
	public abstract class ScepterSkillBase
	{
		public static Dictionary<string, SkillDef> ScepterDictionary = new Dictionary<string, SkillDef>();

		public static string Token = HereticPlugin.TokenName + "SKILL";

		public SkillDef skillDef;

		public virtual string TargetBodyName { get; set; } = HereticPlugin.hereticBodyName;


		public virtual SkillSlot TargetSlot { get; set; } = (SkillSlot)3;


		public abstract int TargetVariant { get; }

		public abstract string SkillName { get; }

		public abstract string SkillDescription { get; }

		public abstract string SkillLangTokenName { get; }

		public abstract string IconName { get; }

		public abstract Type ActivationState { get; }

		public abstract SimpleSkillData SkillData { get; }

		public abstract Type BaseSkillDef { get; }

		private string GetElementString(MageElement type)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected I4, but got Unknown
			string result = "";
			switch (type - 1)
			{
			case 0:
				result = "_FIRE";
				break;
			case 2:
				result = "_LIGHTNING";
				break;
			case 1:
				result = "_ICE";
				break;
			}
			return result;
		}

		public abstract void Init(ConfigFile config);

		protected void CreateLang()
		{
			LanguageAPI.Add(Token + SkillLangTokenName, SkillName);
			LanguageAPI.Add(Token + SkillLangTokenName + "_DESCRIPTION", SkillDescription);
		}

		protected void CreateSkill()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			if (!(TargetBodyName == "") && HereticPlugin.isScepterLoaded)
			{
				SkillDef val = ScriptableObject.CreateInstance<SkillDef>();
				RegisterEntityState(ActivationState);
				val.activationState = new SerializableEntityStateType(ActivationState);
				val.skillNameToken = Token + SkillLangTokenName;
				val.skillName = SkillName;
				val.skillDescriptionToken = Token + SkillLangTokenName + "_DESCRIPTION";
				val.activationStateMachineName = "Weapon";
				val.icon = HereticPlugin.iconBundle.LoadAsset<Sprite>(HereticPlugin.iconsPath + IconName + ".png");
				val.baseMaxStock = SkillData.baseMaxStock;
				val.baseRechargeInterval = SkillData.baseRechargeInterval;
				val.beginSkillCooldownOnSkillEnd = SkillData.beginSkillCooldownOnSkillEnd;
				val.canceledFromSprinting = !HereticPlugin.isAutosprintLoaded && SkillData.canceledFromSprinting;
				val.cancelSprintingOnActivation = SkillData.cancelSprintingOnActivation;
				val.dontAllowPastMaxStocks = SkillData.dontAllowPastMaxStocks;
				val.fullRestockOnAssign = SkillData.fullRestockOnAssign;
				val.interruptPriority = SkillData.interruptPriority;
				val.isCombatSkill = SkillData.isCombatSkill;
				val.mustKeyPress = SkillData.mustKeyPress;
				val.rechargeStock = SkillData.rechargeStock;
				val.requiredStock = SkillData.requiredStock;
				val.resetCooldownTimerOnUse = SkillData.resetCooldownTimerOnUse;
				val.stockToConsume = SkillData.stockToConsume;
				if (ItemBase<AncientScepterItem>.instance.RegisterScepterSkill(val, TargetBodyName, TargetSlot, TargetVariant))
				{
					Assets.RegisterSkillDef(val);
					ScepterDictionary.Add(SkillName, val);
					HereticPlugin.ScepterSkills.Add((uint)TargetVariant, val);
				}
			}
		}

		public abstract void Hooks();

		internal UnlockableDef GetUnlockDef(Type type)
		{
			return null;
		}

		public static bool RegisterEntityState(Type entityState)
		{
			if (!entityState.IsSubclassOf(typeof(EntityState)) || entityState.IsAbstract)
			{
				return false;
			}
			Assets.RegisterEntityState(entityState);
			return true;
		}
	}
	internal class ScepterLesionsSkill : ScepterSkillBase
	{
		public override int TargetVariant => 1;

		public override string SkillName => "Lamenting Lesions";

		public override string SkillDescription => "Channel a <style=cIsDamage>barrage of blades</style> that <style=cIsDamage>bleeds</style> EVERYTHING in sight for <style=cIsDamage>" + Tools.ConvertDecimal(BloodSpecial.bleedDurationBase * 0.8f) + " damage</style>... <style=cIsHealth>including yourself</style>.\n<color=#d299ff>SCEPTER: No longer roots yourself. All enemies hurt by Lesions are also slowed by 80%.</color>";

		public override string SkillLangTokenName => "SCEPTERLESIONS";

		public override string IconName => "";

		public override Type ActivationState => typeof(ScepterLesions);

		public override SimpleSkillData SkillData => new SimpleSkillData(1, 1f, beginSkillCooldownOnSkillEnd: false, canceledFromSprinting: false, cancelSprintingOnActivation: true, dontAllowPastMaxStocks: true, fullRestockOnAssign: true, (InterruptPriority)0)
		{
			interruptPriority = (InterruptPriority)1,
			baseRechargeInterval = 15f,
			canceledFromSprinting = true,
			beginSkillCooldownOnSkillEnd = true
		};

		public override Type BaseSkillDef => typeof(LunarLesionsSkillDef);

		public override void Hooks()
		{
		}

		public override void Init(ConfigFile config)
		{
			Hooks();
			CreateLang();
			CreateSkill();
		}
	}
	internal class ScepterRuinSkill : ScepterSkillBase
	{
		public override int TargetVariant => 0;

		public override string SkillName => "Calamitous Wake";

		public override string SkillDescription => "<style=cIsUtility>Ruinous.</style> Activating this skill <style=cIsDamage>detonates</style> all Ruin at an unlimited range, dealing <style=cIsDamage>300% damage</style> plus <style=cIsDamage>120% per stack of Ruin</style>. \n<color=#d299ff>SCEPTER: All enemies killed with Ruin damage explode for X% of their max health plus Y% base damage.</color>";

		public override string SkillLangTokenName => "SCEPTERRUIN";

		public override string IconName => "";

		public override Type ActivationState => typeof(ScepterRuin);

		public override SimpleSkillData SkillData => new SimpleSkillData(1, 1f, beginSkillCooldownOnSkillEnd: false, canceledFromSprinting: false, cancelSprintingOnActivation: true, dontAllowPastMaxStocks: true, fullRestockOnAssign: true, (InterruptPriority)0)
		{
			interruptPriority = (InterruptPriority)1,
			baseRechargeInterval = 15f,
			canceledFromSprinting = true,
			beginSkillCooldownOnSkillEnd = true
		};

		public override Type BaseSkillDef => typeof(LunarDetonatorSkill);

		public override void Hooks()
		{
		}

		public override void Init(ConfigFile config)
		{
			Hooks();
			CreateLang();
			CreateSkill();
		}
	}
	public class SimpleSkillData
	{
		internal int baseMaxStock;

		internal float baseRechargeInterval;

		internal bool beginSkillCooldownOnSkillEnd;

		internal bool canceledFromSprinting;

		internal bool cancelSprintingOnActivation;

		internal bool dontAllowPastMaxStocks;

		internal bool fullRestockOnAssign;

		internal InterruptPriority interruptPriority;

		internal bool isCombatSkill;

		internal bool mustKeyPress;

		internal int rechargeStock;

		internal int requiredStock;

		internal bool resetCooldownTimerOnUse;

		internal int stockToConsume;

		public SimpleSkillData(int baseMaxStock = 1, float baseRechargeInterval = 1f, bool beginSkillCooldownOnSkillEnd = false, bool canceledFromSprinting = false, bool cancelSprintingOnActivation = true, bool dontAllowPastMaxStocks = true, bool fullRestockOnAssign = true, InterruptPriority interruptPriority = 0, bool isCombatSkill = true, bool mustKeyPress = false, int rechargeStock = 1, int requiredStock = 1, bool resetCooldownTimerOnUse = false, int stockToConsume = 1)
		{
			//IL_003e: 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)
			this.baseMaxStock = baseMaxStock;
			this.baseRechargeInterval = baseRechargeInterval;
			this.beginSkillCooldownOnSkillEnd = beginSkillCooldownOnSkillEnd;
			this.canceledFromSprinting = canceledFromSprinting;
			this.cancelSprintingOnActivation = cancelSprintingOnActivation;
			this.dontAllowPastMaxStocks = dontAllowPastMaxStocks;
			this.fullRestockOnAssign = fullRestockOnAssign;
			this.interruptPriority = interruptPriority;
			this.isCombatSkill = isCombatSkill;
			this.mustKeyPress = mustKeyPress;
			this.rechargeStock = rechargeStock;
			this.requiredStock = requiredStock;
			this.resetCooldownTimerOnUse = resetCooldownTimerOnUse;
			this.stockToConsume = stockToConsume;
		}
	}
	public abstract class SkillBase<T> : SkillBase where T : SkillBase<T>
	{
		public static T instance { get; private set; }

		public SkillBase()
		{
			if (instance != null)
			{
				throw new InvalidOperationException("Singleton class \"" + typeof(T).Name + "\" inheriting ArtificerExtended SkillBase was instantiated twice");
			}
			instance = this as T;
		}
	}
	public abstract class SkillBase
	{
		public static Dictionary<string, SkillLocator> characterSkillLocators = new Dictionary<string, SkillLocator>();

		public static string Token = HereticPlugin.TokenName + "SKILL";

		public static string FullDescToken = "_FULLDESCRIPTION";

		public static string ShortDescToken = "_SHORTDESCRIPTION";

		public string[] KeywordTokens;

		public abstract string SkillName { get; }

		public abstract string SkillDescription { get; }

		public abstract string SkillFullDescription { get; }

		public abstract string SkillLangTokenName { get; }

		public abstract UnlockableDef UnlockDef { get; }

		public abstract string IconName { get; }

		public abstract Type ActivationState { get; }

		public abstract Type BaseSkillDef { get; }

		public abstract string CharacterName { get; }

		public abstract SkillFamilyName SkillSlot { get; }

		public abstract SimpleSkillData SkillData { get; }

		public abstract void Init(ConfigFile config);

		protected void CreateLang()
		{
			LanguageAPI.Add(Token + SkillLangTokenName, SkillName);
			LanguageAPI.Add(Token + SkillLangTokenName + "_DESCRIPTION", SkillDescription);
			string text = $"<style=cIsUtility>Replace your {SkillSlot} Skill</style> with <style=cIsUtility>{SkillName}</style>. ";
			LanguageAPI.Add(Token + SkillLangTokenName + ShortDescToken, text);
			LanguageAPI.Add(Token + SkillLangTokenName + FullDescToken, text + "\n\n" + SkillFullDescription);
			Debug.Log((object)text);
			Debug.Log((object)(text + SkillFullDescription));
		}

		protected void CreateSkill()
		{
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: 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_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Expected O, but got Unknown
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			string characterName = CharacterName;
			SkillLocator val;
			if (characterSkillLocators.ContainsKey(characterName))
			{
				val = characterSkillLocators[characterName];
			}
			else
			{
				GameObject val2 = LegacyResourcesAPI.Load<GameObject>("prefabs/characterbodies/" + characterName);
				val = ((val2 != null) ? val2.GetComponent<SkillLocator>() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					characterSkillLocators.Add(characterName, val);
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				SkillFamily val3 = null;
				switch (SkillSlot)
				{
				case SkillFamilyName.Primary:
					val3 = val.primary.skillFamily;
					break;
				case SkillFamilyName.Secondary:
					val3 = val.secondary.skillFamily;
					break;
				case SkillFamilyName.Utility:
					val3 = val.utility.skillFamily;
					break;
				case SkillFamilyName.Special:
					val3 = val.special.skillFamily;
					break;
				case SkillFamilyName.Misc:
					Debug.Log((object)"Special case!");
					break;
				}
				if ((Object)(object)val3 != (Object)null)
				{
					string text = "HereticUnchained: " + SkillName + " initializing!";
					SkillDef val4 = (SkillDef)ScriptableObject.CreateInstance(BaseSkillDef);
					RegisterEntityState(ActivationState);
					val4.activationState = new SerializableEntityStateType(ActivationState);
					val4.skillNameToken = Token + SkillLangTokenName;
					val4.skillName = SkillName;
					val4.skillDescriptionToken = Token + SkillLangTokenName + "_DESCRIPTION";
					val4.activationStateMachineName = "Weapon";
					val4.keywordTokens = KeywordTokens;
					if ((Object)(object)HereticPlugin.iconBundle != (Object)null)
					{
						val4.icon = HereticPlugin.iconBundle.LoadAsset<Sprite>(HereticPlugin.iconsPath + IconName + ".png");
					}
					val4.baseMaxStock = SkillData.baseMaxStock;
					val4.baseRechargeInterval = SkillData.baseRechargeInterval;
					val4.beginSkillCooldownOnSkillEnd = SkillData.beginSkillCooldownOnSkillEnd;
					val4.canceledFromSprinting = !HereticPlugin.isAutosprintLoaded && SkillData.canceledFromSprinting;
					val4.cancelSprintingOnActivation = SkillData.cancelSprintingOnActivation;
					val4.dontAllowPastMaxStocks = SkillData.dontAllowPastMaxStocks;
					val4.fullRestockOnAssign = SkillData.fullRestockOnAssign;
					val4.interruptPriority = SkillData.interruptPriority;
					val4.isCombatSkill = SkillData.isCombatSkill;
					val4.mustKeyPress = SkillData.mustKeyPress;
					val4.rechargeStock = SkillData.rechargeStock;
					val4.requiredStock = SkillData.requiredStock;
					val4.resetCooldownTimerOnUse = SkillData.resetCooldownTimerOnUse;
					val4.stockToConsume = SkillData.stockToConsume;
					Assets.RegisterSkillDef(val4);
					Array.Resize(ref val3.variants, val3.variants.Length + 1);
					Variant[] variants = val3.variants;
					int num = val3.variants.Length - 1;
					Variant val5 = new Variant
					{
						skillDef = val4,
						unlockableDef = UnlockDef
					};
					((Variant)(ref val5)).viewableNode = new Node(val4.skillNameToken, false, (Node)null);
					variants[num] = val5;
				}
				else
				{
					Debug.Log((object)("No skill family " + SkillSlot.ToString() + " found from " + CharacterName));
				}
			}
			else
			{
				Debug.Log((object)("No skill locator found from " + CharacterName));
			}
		}

		public abstract void Hooks();

		internal UnlockableDef GetUnlockDef(Type type)
		{
			return null;
		}

		public static bool RegisterEntityState(Type entityState)
		{
			if (!entityState.IsSubclassOf(typeof(EntityState)) || entityState.IsAbstract)
			{
				return false;
			}
			Assets.RegisterEntityState(entityState);
			return true;
		}
	}
	internal class LunarLesionsSkillDef : SkillDef
	{
		private class InstanceData : BaseSkillInstanceData
		{
			private GenericSkill _skillSlot;

			public GenericSkill skillSlot
			{
				get
				{
					return _skillSlot;
				}
				set
				{
					if (!((Object)(object)_skillSlot == (Object)(object)value))
					{
						if ((Object)(object)_skillSlot != (Object)null)
						{
							_skillSlot.characterBody.onInventoryChanged -= OnInventoryChanged;
						}
						_skillSlot = value;
						if ((Object)(object)_skillSlot != (Object)null)
						{
							_skillSlot.characterBody.onInventoryChanged += OnInventoryChanged;
						}
					}
				}
			}

			public void OnInventoryChanged()
			{
				skillSlot.RecalculateValues();
			}
		}

		public static float cooldownPerStack = 5f;

		public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot)
		{
			return (BaseSkillInstanceData)(object)new InstanceData
			{
				skillSlot = skillSlot
			};
		}

		public override void OnUnassigned(GenericSkill skillSlot)
		{
			((InstanceData)(object)skillSlot.skillInstanceData).skillSlot = null;
		}

		public override float GetRechargeInterval(GenericSkill skillSlot)
		{
			return base.baseRechargeInterval + cooldownPerStack * (float)(skillSlot.characterBody.inventory.GetItemCount(Items.LunarSpecialReplacement) - 1);
		}
	}
	internal class LunarVampirismSkillDef : SkillDef
	{
		private class InstanceData : BaseSkillInstanceData
		{
			private GenericSkill _skillSlot;

			private LunarVampirismPassiveAttachment passiveAttachment;

			public GenericSkill skillSlot
			{
				get
				{
					return _skillSlot;
				}
				set
				{
					if ((Object)(object)_skillSlot == (Object)(object)value)
					{
						return;
					}
					if ((Object)(object)_skillSlot != (Object)null)
					{
						_skillSlot.characterBody.onInventoryChanged -= OnInventoryChanged;
					}
					if (Object.op_Implicit((Object)(object)passiveAttachment))
					{
						Object.Destroy((Object)(object)((Component)passiveAttachment).gameObject);
					}
					passiveAttachment = null;
					_skillSlot = value;
					if ((Object)(object)_skillSlot != (Object)null)
					{
						_skillSlot.characterBody.onInventoryChanged += OnInventoryChanged;
						if (NetworkServer.active && Object.op_Implicit((Object)(object)_skillSlot.characterBody))
						{
							GameObject val = Object.Instantiate<GameObject>(Assets.lunarVampirismAttachmentPrefab);
							passiveAttachment = val.GetComponent<LunarVampirismPassiveAttachment>();
							passiveAttachment.monitoredSkill = skillSlot;
							val.GetComponent<NetworkedBodyAttachment>().AttachToGameObjectAndSpawn(((Component)_skillSlot.characterBody).gameObject, (string)null);
						}
					}
				}
			}

			public void OnInventoryChanged()
			{
				skillSlot.RecalculateValues();
			}
		}

		public static float cooldownPerStack = 3f;

		public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot)
		{
			return (BaseSkillInstanceData)(object)new InstanceData
			{
				skillSlot = skillSlot
			};
		}

		public override void OnUnassigned(GenericSkill skillSlot)
		{
			((InstanceData)(object)skillSlot.skillInstanceData).skillSlot = null;
		}

		public override float GetRechargeInterval(GenericSkill skillSlot)
		{
			return base.baseRechargeInterval + cooldownPerStack * (float)(skillSlot.characterBody.inventory.GetItemCount(Items.LunarUtilityReplacement) - 1);
		}
	}
	public enum SkillFamilyName
	{
		Misc = -1,
		Passive,
		Primary,
		Secondary,
		Utility,
		Special
	}
}
namespace HereticUnchained.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resources
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					ResourceManager resourceManager = new ResourceManager("HereticUnchained.Properties.Resources", typeof(Resources).Assembly);
					resourceMan = resourceManager;
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] hereticunchained
		{
			get
			{
				object @object = ResourceManager.GetObject("hereticunchained", resourceCulture);
				return (byte[])@object;
			}
		}

		internal Resources()
		{
		}
	}
}
namespace HereticUnchained.SurvivorTweaks
{
	public class HereticTweaks
	{
		public static GameObject secondaryProjectile = LegacyResourcesAPI.Load<GameObject>("prefabs/projectiles/LunarSecondaryProjectile");

		public static float secondaryMaxCharge = 3f;

		public static float secondaryBladesDamage = 1f;

		public static float secondaryBladesFrequency = 6f;

		public static float secondaryBladesProc = 0.5f;

		public static float secondaryExplosionDamage = 9f;

		public static float secondaryExplosionProc = 1f;

		public static GameObject bodyObject;

		public SkillLocator skillLocator;

		public SkillFamily primary;

		public SkillFamily secondary;

		public SkillFamily utility;

		public SkillFamily special;

		public static float shadowfadeBaseHealFraction = 0.25f;

		public string survivorName = "The Heretic";

		public string bodyName = "HereticBody";

		public static void Init()
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Expected O, but got Unknown
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			bodyObject = LegacyResourcesAPI.Load<GameObject>("prefabs/characterbodies/HereticBody");
			CharacterBody component = bodyObject.GetComponent<CharacterBody>();
			component.baseMaxHealth = 260f;
			component.baseRegen = -4f;
			component.baseDamage = 16f;
			component.baseArmor = 30f;
			component.levelMaxHealth = component.baseMaxHealth * 0.3f;
			component.levelRegen = component.baseRegen * 0.2f;
			component.levelDamage = component.baseDamage * 0.2f;
			ProjectileDotZone component2 = secondaryProjectile.GetComponent<ProjectileDotZone>();
			component2.damageCoefficient = secondaryBladesDamage / secondaryExplosionDamage;
			component2.resetFrequency = secondaryBladesFrequency;
			component2.fireFrequency = secondaryBladesFrequency * 3f;
			component2.overlapProcCoefficient = secondaryBladesProc / secondaryExplosionProc;
			ProjectileExplosion component3 = secondaryProjectile.GetComponent<ProjectileExplosion>();
			component3.blastDamageCoefficient = 1f;
			component3.blastProcCoefficient = secondaryExplosionProc;
			component3.falloffModel = (FalloffModel)1;
			component3.blastRadius = 17f;
			BaseThrowBombState.OnEnter += new hook_OnEnter(HooksDamageBuff);
			BaseChargeBombState.OnEnter += new hook_OnEnter(HooksChargeTweak);
			LanguageAPI.Add("SKILL_LUNAR_SECONDARY_REPLACEMENT_DESCRIPTION", "Charge up a ball of blades that deals <style=cIsDamage>" + Tools.ConvertDecimal(secondaryBladesDamage * secondaryBladesFrequency) + " damage per second</style>. After a delay, explode and <style=cIsDamage>root</style> all enemies for <style=cIsDamage>" + Tools.ConvertDecimal(secondaryExplosionDamage) + " damage</style>.");
			GhostUtilitySkillState.OnEnter += new hook_OnEnter(ShadowfadeEnter);
			GhostUtilitySkillState.OnEnter += new hook_OnEnter(ShadowfadeExit);
			LanguageAPI.Add("SKILL_LUNAR_UTILITY_REPLACEMENT_DESCRIPTION", "Fade away, becoming <style=cIsUtility>intangible</style> and <style=cIsUtility>gaining movement speed</style>. <style=cIsHealing>Heal</style> for <style=cIsHealing>" + Tools.ConvertDecimal(shadowfadeBaseHealFraction) + " of your maximum health</style>.");
		}

		private static void HooksChargeTweak(orig_OnEnter orig, BaseChargeBombState self)
		{
			if (self is ChargeLunarSecondary)
			{
				self.baseDuration = secondaryMaxCharge;
			}
			orig.Invoke(self);
		}

		private static void HooksDamageBuff(orig_OnEnter orig, BaseThrowBombState self)
		{
			if (self is ThrowLunarSecondary)
			{
				self.minDamageCoefficient = secondaryExplosionDamage;
				self.maxDamageCoefficient = secondaryExplosionDamage;
			}
			orig.Invoke(self);
		}

		private static void ShadowfadeEnter(orig_OnEnter orig, GhostUtilitySkillState self)
		{
			orig.Invoke(self);
			GhostUtilitySkillState.healFractionPerTick = shadowfadeBaseHealFraction / (GhostUtilitySkillState.baseDuration * GhostUtilitySkillState.healFrequency);
		}

		private static void ShadowfadeExit(orig_OnEnter orig, GhostUtilitySkillState self)
		{
			//IL_0018: 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)
			if (NetworkServer.active)
			{
				((EntityState)self).healthComponent.HealFraction(GhostUtilitySkillState.healFractionPerTick, default(ProcChainMask));
			}
			orig.Invoke(self);
		}
	}
}
namespace HereticUnchained.EntityState
{
	internal class BloodPrimary : BaseSkillState
	{
		public static int baseFireRate = 3;

		public static int stackFireRate = 2;

		private float fireRate;

		private float duration;

		private float stopwatch;

		public static float damageCoefficient = 1.8f;

		public static float force = 0f;

		public static float healthCostFraction = 0.05f;

		public static float spreadBloomValue = 0.2f;

		public static float maxRange = 100f;

		public static GameObject hitEffectPrefab;

		public override void OnEnter()
		{
			fireRate = baseFireRate;
			Inventory inventory = ((EntityState)this).characterBody.inventory;
			if (Object.op_Implicit((Object)(object)inventory))
			{
				fireRate += (inventory.GetItemCount(Items.LunarPrimaryReplacement) - 1) * stackFireRate;
			}
			duration = 1f / (fireRate * ((BaseState)this).attackSpeedStat);
			((BaseState)this).OnEnter();
			FireBullet();
		}

		public override void OnExit()
		{
			((EntityState)this).OnExit();
		}

		public override void FixedUpdate()
		{
			((EntityState)this).FixedUpdate();
			stopwatch += Time.fixedDeltaTime;
			if (((EntityState)this).isAuthority && !((BaseSkillState)this).IsKeyDownAuthority())
			{
				if (stopwatch > duration)
				{
					((EntityState)this).outer.SetNextStateToMain();
				}
			}
			else
			{
				while (stopwatch >= duration)
				{
					stopwatch -= duration;
					FireBullet();
				}
			}
		}

		private void FireBullet()
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active && Object.op_Implicit((Object)(object)((EntityState)this).healthComponent) && healthCostFraction >= Mathf.Epsilon)
			{
				DamageType val = (DamageType)1;
				val = (DamageType)(val | 2);
				DamageInfo val2 = new DamageInfo();
				val2.damage = ((EntityState)this).healthComponent.fullCombinedHealth * healthCostFraction;
				val2.position = ((EntityState)this).characterBody.corePosition;
				val2.force = Vector3.zero;
				val2.damageColorIndex = (DamageColorIndex)0;
				val2.crit = false;
				val2.attacker = null;
				val2.inflictor = null;
				val2.damageType = val;
				val2.procCoefficient = 0f;
				val2.procChainMask = default(ProcChainMask);
				((EntityState)this).healthComponent.TakeDamage(val2);
			}
			Ray aimRay = ((BaseState)this).GetAimRay();
			if (((EntityState)this).isAuthority)
			{
				new BulletAttack
				{
					owner = ((EntityState)this).gameObject,
					weapon = ((EntityState)this).gameObject,
					origin = ((Ray)(ref aimRay)).origin,
					aimVector = ((Ray)(ref aimRay)).direction,
					minSpread = 0f,
					maxSpread = ((EntityState)this).characterBody.spreadBloomAngle,
					damage = damageCoefficient * ((BaseState)this).damageStat,
					damageType = (DamageType)524288,
					falloffModel = (FalloffModel)1,
					force = force,
					tracerEffectPrefab = BloodPrimarySkill.tracerLaser,
					muzzleName = "Head",
					hitEffectPrefab = hitEffectPrefab,
					isCrit = Util.CheckRoll(((BaseState)this).critStat, ((EntityState)this).characterBody.master),
					radius = 0.1f,
					maxDistance = maxRange,
					smartCollision = true
				}.Fire();
			}
			EffectManager.SimpleMuzzleFlash(FireLunarNeedle.muzzleFlashEffectPrefab, ((EntityState)this).gameObject, "Head", false);
			((BaseState)this).StartAimMode(2f, false);
			((EntityState)this).PlayAnimation("Gesture, Override", "FireLunarNeedle", "FireLunarNeedle.playbackRate", duration);
			((BaseState)this).AddRecoil(-0.4f * FireLunarNeedle.recoilAmplitude, -0.8f * FireLunarNeedle.recoilAmplitude, -0.3f * FireLunarNeedle.recoilAmplitude, 0.3f * FireLunarNeedle.recoilAmplitude);
			((EntityState)this).characterBody.AddSpreadBloom(spreadBloomValue / ((BaseState)this).attackSpeedStat);
		}

		public override InterruptPriority GetMinimumInterruptPriority()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return (InterruptPriority)1;
		}
	}
	internal class BloodSecondary : BaseSkillState
	{
	}
	public class BloodSpecial : BaseSkillState
	{
		[SerializeField]
		public GameObject flamethrowerEffectPrefab = new Flamethrower().flamethrowerEffectPrefab;

		public GameObject detonationEffectPrefab = LegacyResourcesAPI.Load<GameObject>("prefabs/effects/BleedOnHitAndExplode_Explosion");

		public static GameObject impactEffectPrefab = Flamethrower.impactEffectPrefab;

		public static GameObject tracerEffectPrefab = Flamethrower.tracerEffectPrefab;

		public static float baseEntryDuration = 0.5f;

		public static float baseExitDuration = 0.5f;

		public static float minimumAttackDuration = 1f;

		public static float tickFrequency = 2f;

		public static float damageCoefficientPerTick = 0.5f;

		public static float procCoefficientPerTick = 0.5f;

		public static float bleedPercentChance = 100f;

		public static float bleedDurationBase = 3f;

		public static float bleedDurationStack = 2f;

		public static float selfBleedDamageMultiplier = 0.2f;

		public static float enemyBleedDamageMultiplier = 1f;

		private bool isCrit;

		[SerializeField]
		public static float maxDistance = 125f;

		private static float flamethrowerEffectBaseDistance = maxDistance * 0.8f;

		public static float radius;

		public static float force = 20f;

		public static float recoilForce;

		public static string startAttackSoundString;

		public static string endAttackSoundString;

		private float stopwatch;

		private float flamethrowerStopwatch;

		private float entryDuration;

		private float exitDuration;

		private float tickRate;

		private float bleedDuration;

		private float fieldOfView = new FireSonicBoom().fieldOfView;

		private bool hasBegunFlamethrower;

		private bool isExitingFlamethrower;

		private ChildLocator childLocator;

		private Transform flamethrowerTransform;

		public static string muzzleName = "Head";

		private Transform muzzleTransform;

		public override void OnEnter()
		{
			((BaseState)this).OnEnter();
			stopwatch = 0f;
			entryDuration = baseEntryDuration / ((BaseState)this).attackSpeedStat;
			exitDuration = baseExitDuration / ((BaseState)this).attackSpeedStat;
			tickRate = 1f / (tickFrequency * ((BaseState)this).attackSpeedStat);
			bleedDuration = bleedDurationBase;
			Inventory inventory = ((EntityState)this).characterBody.inventory;
			if (Object.op_Implicit((Object)(object)inventory))
			{
				bleedDuration += bleedDurationStack * (float)(((EntityState)this).characterBody.inventory.GetItemCount(Items.LunarSpecialReplacement) - 1);
			}
			Transform modelTransform = ((EntityState)this).GetModelTransform();
			if (Object.op_Implicit((Object)(object)((EntityState)this).characterBody))
			{
				((EntityState)this).characterBody.SetAimTimer(entryDuration + minimumAttackDuration + exitDuration + bleedDuration);
			}
			if (Object.op_Implicit((Object)(object)modelTransform))
			{
				childLocator = ((Component)modelTransform).GetComponent<ChildLocator>();
				muzzleTransform = childLocator.FindChild(muzzleName);
			}
			if (((EntityState)this).isAuthority && Object.op_Implicit((Object)(object)((EntityState)this).characterBody))
			{
				isCrit = Util.CheckRoll(((BaseState)this).critStat, ((EntityState)this).characterBody.master);
			}
		}

		public override void OnExit()
		{
			if (((EntityState)this).characterBody.HasBuff(Buffs.LunarSecondaryRoot))
			{
				((EntityState)this).characterBody.RemoveBuff(Buffs.LunarSecondaryRoot);
			}
			Util.PlaySound(Flamethrower.endAttackSoundString, ((EntityState)this).gameObject);
			if (Object.op_Implicit((Object)(object)flamethrowerTransform))
			{
				EntityState.Destroy((Object)(object)((Component)flamethrowerTransform).gameObject);
			}
			((EntityState)this).OnExit();
		}

		public override void FixedUpdate()
		{
			((EntityState)this).FixedUpdate();
			stopwatch += Time.fixedDeltaTime;
			if (stopwatch >= entryDuration && !hasBegunFlamethrower)
			{
				hasBegunFlamethrower = true;
				Util.PlaySound(Flamethrower.startAttackSoundString, ((EntityState)this).gameObject);
				if (Object.op_Implicit((Object)(object)childLocator))
				{
					Transform val = childLocator.FindChild(muzzleName);
					if (Object.op_Implicit((Object)(object)val))
					{
					}
					if (Object.op_Implicit((Object)(object)flamethrowerTransform))
					{
						((Component)flamethrowerTransform).GetComponent<ScaleParticleSystemDuration>().newDuration = minimumAttackDuration;
					}
				}
				FireBleed(muzzleName);
			}
			if (hasBegunFlamethrower)
			{
				if (!((EntityState)this).characterBody.HasBuff(Buffs.LunarSecondaryRoot))
				{
					((EntityState)this).characterBody.AddBuff(Buffs.LunarSecondaryRoot);
				}
				flamethrowerStopwatch += Time.fixedDeltaTime;
				if (flamethrowerStopwatch > tickRate)
				{
					flamethrowerStopwatch -= tickRate;
					FireBleed(muzzleName);
				}
				UpdateFlamethrowerEffect();
			}
			if (isExitingFlamethrower && stopwatch >= exitDuration && ((EntityState)this).isAuthority)
			{
				((EntityState)this).outer.SetNextStateToMain();
			}
			else if (!((BaseSkillState)this).IsKeyDownAuthority() && hasBegunFlamethrower && !isExitingFlamethrower && stopwatch >= entryDuration + minimumAttackDuration)
			{
				isExitingFlamethr