Decompiled source of ItemStatistics v1.1.11

patchers/ItemStatisticsPatcher.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ItemStatisticsPatcher")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.11.0")]
[assembly: AssemblyInformationalVersion("1.1.11.0+501f7195a8c691d60d936bcfa7f346d8be7ea5d8")]
[assembly: AssemblyProduct("ItemStatisticsPatcher")]
[assembly: AssemblyTitle("ItemStatisticsPatcher")]
[assembly: AssemblyVersion("1.1.11.0")]
public static class Patcher
{
	private static readonly ManualLogSource Log = Logger.CreateLogSource("ItemStatisticsPatcher");

	public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "RoR2.dll" };


	public static void Patch(AssemblyDefinition assembly)
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Expected O, but got Unknown
		ModuleDefinition mainModule = assembly.MainModule;
		string[] files = Directory.GetFiles(Paths.PluginPath, "ItemStatistics.dll", SearchOption.AllDirectories);
		if (files.Length == 0)
		{
			Log.LogFatal((object)"Failed to find ItemStatistics.dll");
			return;
		}
		AssemblyDefinition val = AssemblyDefinition.ReadAssembly(files[0]);
		TypeReference val2 = mainModule.ImportReference((TypeReference)(object)val.MainModule.GetType("ItemStatistics.ReverseTree"));
		GenericInstanceType val3 = new GenericInstanceType(mainModule.ImportReference(typeof(List<>)));
		val3.GenericArguments.Add(val2);
		TypeReference fieldType = mainModule.ImportReference((TypeReference)(object)val.MainModule.GetType("ItemStatistics.Index"));
		ModuleDefinition mainModule2 = AssemblyDefinition.ReadAssembly(Path.Combine(Paths.ManagedPath, "UnityEngine.CoreModule.dll")).MainModule;
		TypeReference fieldType2 = mainModule.ImportReference((TypeReference)(object)mainModule2.GetType("UnityEngine.GameObject"));
		AddField(mainModule.GetType("RoR2.DotController/DotStack"), val2, "dotStackTree");
		AddField(mainModule.GetType("RoR2.DotController/PendingDamage"), (TypeReference)(object)val3, "pendingDotTreeList");
		AddField(mainModule.GetType("RoR2.Orbs.GenericDamageOrb"), fieldType2, "inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.DevilOrb"), fieldType2, "inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.BounceOrb"), fieldType2, "inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.LunarDetonatorOrb"), fieldType2, "inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.HealOrb"), fieldType, "inflictor");
		AddField(mainModule.GetType("EntityStates.FrozenState"), fieldType, "freezeInflictor");
		AddField(mainModule.GetType("EntityStates.FrozenState"), (TypeReference)(object)mainModule.GetType("RoR2.CharacterMaster"), "freezeInflictorMaster");
		TypeDefinition type = mainModule.GetType("EntityStates.BasicMeleeAttack");
		AddOverrideMethod(mainModule, mainModule.GetType("EntityStates.Loader.SwingComboFist"), type, "AuthorityModifyOverlapAttack", (MethodAttributes)4);
		AddOverrideMethod(mainModule, mainModule.GetType("EntityStates.FalseSon.ClubSwing"), type, "AuthorityModifyOverlapAttack", (MethodAttributes)4);
		AddOverrideMethod(mainModule, mainModule.GetType("EntityStates.FalseSon.OverheadClubSwing"), type, "AuthorityModifyOverlapAttack", (MethodAttributes)4);
	}

	private static void AddOverrideMethod(ModuleDefinition module, TypeDefinition typeToAddTo, TypeDefinition baseType, string methodName, MethodAttributes attributes)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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_00b0: Expected O, but got Unknown
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		if (((IEnumerable<MethodDefinition>)typeToAddTo.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition a) => ((MemberReference)a).Name == methodName)) != null)
		{
			Log.LogWarning((object)(((MemberReference)typeToAddTo).Name + "." + methodName + " already exists"));
			return;
		}
		MethodDefinition val = ((IEnumerable<MethodDefinition>)baseType.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == methodName));
		if (val == null)
		{
			Log.LogError((object)("Failed to find " + ((MemberReference)baseType).Name + "." + methodName));
			return;
		}
		MethodDefinition val2 = new MethodDefinition(methodName, (MethodAttributes)(attributes | 0x40 | 0x80), module.ImportReference(((MethodReference)val).ReturnType));
		Enumerator<ParameterDefinition> enumerator = ((MethodReference)val).Parameters.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				ParameterDefinition current = enumerator.Current;
				((MethodReference)val2).Parameters.Add(new ParameterDefinition(((ParameterReference)current).Name, current.Attributes, module.ImportReference(((ParameterReference)current).ParameterType)));
			}
		}
		finally
		{
			((IDisposable)enumerator).Dispose();
		}
		ILProcessor iLProcessor = val2.Body.GetILProcessor();
		iLProcessor.Append(iLProcessor.Create(OpCodes.Ldarg_0));
		for (int i = 1; i <= ((MethodReference)val).Parameters.Count; i++)
		{
			iLProcessor.Append(iLProcessor.Create(OpCodes.Ldarg, i));
		}
		iLProcessor.Append(iLProcessor.Create(OpCodes.Call, module.ImportReference((MethodReference)(object)val)));
		iLProcessor.Append(iLProcessor.Create(OpCodes.Ret));
		val2.Overrides.Add((MethodReference)(object)val);
		typeToAddTo.Methods.Add(val2);
	}

	private static void AddField(TypeDefinition target, TypeReference fieldType, string fieldName)
	{
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Expected O, but got Unknown
		if (target == null || fieldType == null)
		{
			Log.LogError((object)("Null types in AddField: " + fieldName));
			return;
		}
		if (((IEnumerable<FieldDefinition>)target.Fields).FirstOrDefault((Func<FieldDefinition, bool>)((FieldDefinition a) => ((MemberReference)a).Name == fieldName)) != null)
		{
			Log.LogWarning((object)(((MemberReference)target).Name + "." + fieldName + " already exists"));
			return;
		}
		FieldDefinition val = new FieldDefinition(fieldName, (FieldAttributes)6, fieldType);
		target.Fields.Add(val);
	}
}

plugins/ItemStatistics.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dolso;
using Dolso.RiskofOptions;
using EntityStates;
using EntityStates.Bandit2;
using EntityStates.Bandit2.Weapon;
using EntityStates.Captain.Weapon;
using EntityStates.CaptainDefenseMatrixItem;
using EntityStates.Chef;
using EntityStates.Commando.CommandoWeapon;
using EntityStates.Croco;
using EntityStates.Engi.Mine;
using EntityStates.Engi.SpiderMine;
using EntityStates.FalseSon;
using EntityStates.GlobalSkills.LunarDetonator;
using EntityStates.GummyClone;
using EntityStates.Headstompers;
using EntityStates.Huntress.HuntressWeapon;
using EntityStates.Huntress.Weapon;
using EntityStates.Loader;
using EntityStates.Mage;
using EntityStates.Mage.Weapon;
using EntityStates.Merc;
using EntityStates.Merc.Weapon;
using EntityStates.Railgunner.Weapon;
using EntityStates.Seeker;
using EntityStates.TeleporterHealNovaController;
using EntityStates.Toolbot;
using EntityStates.Treebot.TreebotFlower;
using EntityStates.Treebot.Weapon;
using EntityStates.VoidSurvivor.Weapon;
using HG;
using HG.GeneralSerializer;
using HG.Reflection;
using ItemStatistics;
using ItemStatistics.Components;
using ItemStatistics.Hooks;
using ItemStatistics.Networking;
using ItemStatistics.Trackers;
using Magrider.Magrider;
using Magrider.Magrider.SkillStates.Weapon;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using Rewired.Integration.UnityUI;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Items;
using RoR2.Networking;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.Stats;
using RoR2.UI;
using TMPro;
using Unity;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyInformationalVersion("1.0.0+501f7195a8c691d60d936bcfa7f346d8be7ea5d8")]
[assembly: AssemblyProduct("ItemStatistics")]
[assembly: AssemblyTitle("ItemStatistics")]
[assembly: AssemblyCompany("ItemStatistics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Dolso
{
	internal static class log
	{
		private static ManualLogSource logger;

		internal static void start(ManualLogSource logSource)
		{
			logger = logSource;
		}

		internal static void start(string name)
		{
			logger = Logger.CreateLogSource(name);
		}

		internal static void debug(object data)
		{
			logger.LogDebug(data);
		}

		internal static void info(object data)
		{
			logger.LogInfo(data);
		}

		internal static void message(object data)
		{
			logger.LogMessage(data);
		}

		internal static void warning(object data)
		{
			logger.LogWarning(data);
		}

		internal static void error(object data)
		{
			logger.LogError(data);
		}

		internal static void fatal(object data)
		{
			logger.LogFatal(data);
		}

		internal static void LogError(this ILCursor c, object data)
		{
			logger.LogError((object)string.Format($"ILCursor failure, skipping: {data}\n{c}"));
		}

		internal static void LogErrorCaller(this ILCursor c, object data, [CallerMemberName] string callerName = "")
		{
			logger.LogError((object)string.Format($"ILCursor failure in {callerName}, skipping: {data}\n{c}"));
		}
	}
	internal static class HookManager
	{
		internal delegate bool ConfigEnabled<T>(ConfigEntry<T> configEntry);

		internal const BindingFlags allFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static ILHookConfig ilHookConfig = new ILHookConfig
		{
			ManualApply = true
		};

		private static HookConfig onHookConfig = new HookConfig
		{
			ManualApply = true
		};

		private static readonly ConfigEnabled<bool> boolConfigEnabled = (ConfigEntry<bool> configEntry) => configEntry.Value;

		internal static void Hook(Type typeFrom, string methodFrom, Manipulator ilHook)
		{
			HookInternal(GetMethod(typeFrom, methodFrom), ilHook);
		}

		internal static void Hook(MethodBase methodFrom, Manipulator ilHook)
		{
			HookInternal(methodFrom, ilHook);
		}

		internal static void Hook(Delegate from, Manipulator ilHook)
		{
			HookInternal(from.Method, ilHook);
		}

		internal static void Hook<T>(Expression<Action<T>> from, Manipulator ilHook)
		{
			HookInternal(((MethodCallExpression)from.Body).Method, ilHook);
		}

		internal static void Hook(Type typeFrom, string methodFrom, Delegate onHook)
		{
			HookInternal(GetMethod(typeFrom, methodFrom), onHook.Method, onHook.Target);
		}

		internal static void Hook(MethodBase methodFrom, MethodInfo onHook)
		{
			HookInternal(methodFrom, onHook, null);
		}

		internal static void Hook(MethodBase methodFrom, Delegate onHook)
		{
			HookInternal(methodFrom, onHook.Method, onHook.Target);
		}

		internal static void Hook(Delegate from, Delegate onHook)
		{
			HookInternal(from.Method, onHook.Method, onHook.Target);
		}

		internal static void Hook<T>(Expression<Action<T>> from, Delegate onHook)
		{
			HookInternal(((MethodCallExpression)from.Body).Method, onHook.Method, onHook.Target);
		}

		internal static void Hook(Type typeFrom, string methodFrom, Delegate onHook, object instance)
		{
			HookInternal(GetMethod(typeFrom, methodFrom), onHook.Method, instance);
		}

		internal static void Hook(MethodBase methodFrom, MethodInfo onHook, object target)
		{
			HookInternal(methodFrom, onHook, target);
		}

		private static void HookInternal(MethodBase methodFrom, Manipulator ilHook)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (methodFrom == null)
			{
				log.error("null MethodFrom for hook: " + ((Delegate)(object)ilHook).Method.Name);
				return;
			}
			try
			{
				new ILHook(methodFrom, ilHook, ref ilHookConfig).Apply();
			}
			catch (Exception ex)
			{
				log.error($"Failed to apply ILHook: {methodFrom.DeclaringType}.{methodFrom.Name} - {((Delegate)(object)ilHook).Method.Name}\n{ex}");
			}
		}

		private static void HookInternal(MethodBase methodFrom, MethodInfo onHook, object target)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (methodFrom == null)
			{
				log.error("null methodFrom for hook: " + onHook.Name);
				return;
			}
			try
			{
				new Hook(methodFrom, onHook, target, ref onHookConfig).Apply();
			}
			catch (Exception ex)
			{
				log.error($"Failed to apply onHook: {methodFrom.DeclaringType}.{methodFrom.Name} - {onHook.Name}\n{ex}");
			}
		}

		internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, Type typeFrom, string methodFrom, Manipulator ilHook)
		{
			configEntry.AddHookConfig(enabled, GetMethod(typeFrom, methodFrom), ilHook);
		}

		internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase methodFrom, Manipulator ilHook)
		{
			configEntry.AddHookConfig(enabled, methodFrom, ilHook);
		}

		internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, Type typeFrom, string methodFrom, Delegate onHook)
		{
			configEntry.AddHookConfig(enabled, GetMethod(typeFrom, methodFrom), onHook.Method, onHook.Target);
		}

		internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase methodFrom, Delegate onHook)
		{
			configEntry.AddHookConfig(enabled, methodFrom, onHook.Method, onHook.Target);
		}

		internal static void HookConfig(this ConfigEntry<bool> configEntry, Type typeFrom, string methodFrom, Manipulator ilHook)
		{
			configEntry.AddHookConfig(boolConfigEnabled, GetMethod(typeFrom, methodFrom), ilHook);
		}

		internal static void HookConfig(this ConfigEntry<bool> configEntry, MethodBase methodFrom, Manipulator ilHook)
		{
			configEntry.AddHookConfig(boolConfigEnabled, methodFrom, ilHook);
		}

		internal static void HookConfig(this ConfigEntry<bool> configEntry, Type typeFrom, string methodFrom, Delegate onHook)
		{
			configEntry.AddHookConfig(boolConfigEnabled, GetMethod(typeFrom, methodFrom), onHook.Method, onHook.Target);
		}

		internal static void HookConfig(this ConfigEntry<bool> configEntry, MethodBase methodFrom, Delegate onHook)
		{
			configEntry.AddHookConfig(boolConfigEnabled, methodFrom, onHook.Method, onHook.Target);
		}

		private static void AddHookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase methodFrom, Manipulator ilHook)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (methodFrom == null)
			{
				log.error("null MethodFrom for hook: " + ((Delegate)(object)ilHook).Method.Name);
				return;
			}
			try
			{
				configEntry.AddHookConfig(enabled, (IDetour)new ILHook(methodFrom, ilHook, ref ilHookConfig));
			}
			catch (Exception ex)
			{
				log.error($"Failed to ilHook {methodFrom.DeclaringType}.{methodFrom.Name} - {((Delegate)(object)ilHook).Method.Name}\n{ex}");
			}
		}

		private static void AddHookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase methodFrom, MethodInfo onHook, object target)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if (methodFrom == null)
			{
				log.error("null MethodFrom for hook: " + onHook.Name);
				return;
			}
			try
			{
				configEntry.AddHookConfig(enabled, (IDetour)new Hook(methodFrom, onHook, target, ref onHookConfig));
			}
			catch (Exception ex)
			{
				log.error($"Failed to onHook {methodFrom.DeclaringType}.{methodFrom.Name} - {onHook.Name}\n{ex}");
			}
		}

		private static void AddHookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, IDetour detour)
		{
			configEntry.SettingChanged += delegate(object sender, EventArgs args)
			{
				UpdateHook(detour, enabled(sender as ConfigEntry<T>));
			};
			if (enabled(configEntry))
			{
				detour.Apply();
			}
		}

		private static void UpdateHook(IDetour hook, bool enabled)
		{
			if (enabled)
			{
				if (!hook.IsApplied)
				{
					hook.Apply();
				}
			}
			else if (hook.IsApplied)
			{
				hook.Undo();
			}
		}

		internal static void PriorityFirst()
		{
			ilHookConfig.Before = new string[1] { "*" };
			onHookConfig.Before = new string[1] { "*" };
		}

		internal static void PriorityLast()
		{
			ilHookConfig.After = new string[1] { "*" };
			onHookConfig.After = new string[1] { "*" };
		}

		internal static void PriorityNormal()
		{
			ilHookConfig.Before = null;
			onHookConfig.Before = null;
			ilHookConfig.After = null;
			onHookConfig.After = null;
		}

		internal static IDetour ManualDetour(Type typeFrom, string methodFrom, Delegate onHook)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			try
			{
				return (IDetour)new Hook((MethodBase)GetMethod(typeFrom, methodFrom), onHook, ref onHookConfig);
			}
			catch (Exception ex)
			{
				log.error($"Failed to make onHook {typeFrom}.{methodFrom} - {onHook.Method.Name}\n{ex}");
			}
			return null;
		}

		internal static MethodInfo GetMethod(Type typeFrom, string methodFrom)
		{
			if (typeFrom == null || methodFrom == null)
			{
				return null;
			}
			IEnumerable<MethodInfo> source = from predicate in typeFrom.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where predicate.Name == methodFrom
				select predicate;
			if (source.Count() == 1)
			{
				return source.First();
			}
			if (source.Count() == 0)
			{
				log.error($"Failed to find method: {typeFrom}.{methodFrom}");
			}
			if (source.Count() > 1)
			{
				log.error($"{source.Count()} ambiguous matches found for: {typeFrom}.{methodFrom}");
			}
			return null;
		}
	}
	internal static class Utilities
	{
		private static GameObject _prefabParent;

		internal static GameObject CreatePrefab(GameObject gameObject)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)_prefabParent))
			{
				_prefabParent = new GameObject("DolsoPrefabs");
				Object.DontDestroyOnLoad((Object)(object)_prefabParent);
				((Object)_prefabParent).hideFlags = (HideFlags)61;
				_prefabParent.SetActive(false);
			}
			return Object.Instantiate<GameObject>(gameObject, _prefabParent.transform);
		}

		internal static GameObject CreatePrefab(GameObject gameObject, string name)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)_prefabParent))
			{
				_prefabParent = new GameObject("DolsoPrefabs");
				Object.DontDestroyOnLoad((Object)(object)_prefabParent);
				((Object)_prefabParent).hideFlags = (HideFlags)61;
				_prefabParent.SetActive(false);
			}
			GameObject obj = Object.Instantiate<GameObject>(gameObject, _prefabParent.transform);
			((Object)obj).name = name;
			return obj;
		}

		internal static MethodInfo MakeGenericMethod<T>(this Type type, string methodName, params Type[] parameters)
		{
			return type.GetMethod(methodName, parameters).MakeGenericMethod(typeof(T));
		}

		internal static MethodInfo MakeGenericGetComponentG<T>() where T : Component
		{
			return typeof(GameObject).GetMethod("GetComponent", Type.EmptyTypes).MakeGenericMethod(typeof(T));
		}

		internal static MethodInfo MakeGenericGetComponentC<T>() where T : Component
		{
			return typeof(Component).GetMethod("GetComponent", Type.EmptyTypes).MakeGenericMethod(typeof(T));
		}

		internal static AssetBundle LoadAssetBundle(string bundlePathName)
		{
			AssetBundle result = null;
			try
			{
				result = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), bundlePathName));
			}
			catch (Exception ex)
			{
				log.error("Failed to load assetbundle\n" + ex);
			}
			return result;
		}

		internal static Obj GetAddressable<Obj>(string addressable) where Obj : Object
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Addressables.LoadAssetAsync<Obj>((object)addressable).WaitForCompletion();
		}

		internal static GameObject GetAddressable(string addressable)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Addressables.LoadAssetAsync<GameObject>((object)addressable).WaitForCompletion();
		}

		internal static void GetAddressable<Obj>(string addressable, Action<Obj> callback) where Obj : Object
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			AsyncOperationHandle<Obj> val = Addressables.LoadAssetAsync<Obj>((object)addressable);
			val.Completed += delegate(AsyncOperationHandle<Obj> a)
			{
				callback(a.Result);
			};
		}

		internal static void GetAddressable(string addressable, Action<GameObject> callback)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable);
			val.Completed += delegate(AsyncOperationHandle<GameObject> a)
			{
				callback(a.Result);
			};
		}

		internal static void AddressableAddComp<Comp>(string addressable) where Comp : Component
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable);
			val.Completed += delegate(AsyncOperationHandle<GameObject> a)
			{
				a.Result.AddComponent<Comp>();
			};
		}

		internal static void AddressableAddComp<Comp>(string addressable, Action<Comp> callback) where Comp : Component
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable);
			val.Completed += delegate(AsyncOperationHandle<GameObject> a)
			{
				callback(a.Result.AddComponent<Comp>());
			};
		}

		internal static void AddressableAddCompSingle<Comp>(string addressable) where Comp : Component
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable);
			val.Completed += delegate(AsyncOperationHandle<GameObject> a)
			{
				if (!Object.op_Implicit((Object)(object)a.Result.GetComponent<Comp>()))
				{
					a.Result.AddComponent<Comp>();
				}
			};
		}

		internal static void SetStateConfigIndex(this EntityStateConfiguration stateConfig, string fieldName, string newValue)
		{
			ref SerializedField[] serializedFields = ref stateConfig.serializedFieldsCollection.serializedFields;
			for (int i = 0; i < serializedFields.Length; i++)
			{
				if (serializedFields[i].fieldName == fieldName)
				{
					serializedFields[i].fieldValue.stringValue = newValue;
					return;
				}
			}
			log.error("failed to find " + fieldName + " for " + ((Object)stateConfig).name);
		}

		internal static void SetStateConfigIndex(this EntityStateConfiguration stateConfig, string fieldName, Object newValue)
		{
			ref SerializedField[] serializedFields = ref stateConfig.serializedFieldsCollection.serializedFields;
			for (int i = 0; i < serializedFields.Length; i++)
			{
				if (serializedFields[i].fieldName == fieldName)
				{
					serializedFields[i].fieldValue.objectValue = newValue;
					return;
				}
			}
			log.error("failed to find " + fieldName + " for " + ((Object)stateConfig).name);
		}

		internal static bool IsKeyDown(this ConfigEntry<KeyboardShortcut> key)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = key.Value;
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			value = key.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			return true;
		}

		internal static bool IsKeyJustPressed(this ConfigEntry<KeyboardShortcut> key)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = key.Value;
			if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			value = key.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			return true;
		}

		internal static bool ContainsString(string source, string value)
		{
			return CultureInfo.InvariantCulture.CompareInfo.IndexOf(source, value, CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols) >= 0;
		}
	}
}
namespace Dolso.RiskofOptions
{
	internal static class RiskofOptions
	{
		internal const string rooGuid = "com.rune580.riskofoptions";

		internal static bool enabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions");

		internal static void SetSprite(Sprite sprite)
		{
			ModSettingsManager.SetModIcon(sprite);
		}

		internal static void SetSpriteDefaultIcon()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
			string path = ((!(directoryInfo.Name == "plugins")) ? directoryInfo.FullName : directoryInfo.Parent.FullName);
			try
			{
				Texture2D val = new Texture2D(256, 256);
				if (ImageConversion.LoadImage(val, File.ReadAllBytes(Path.Combine(path, "icon.png"))))
				{
					ModSettingsManager.SetModIcon(Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)));
				}
				else
				{
					log.error("Failed to load icon.png");
				}
			}
			catch (Exception ex)
			{
				log.error("Failed to load icon.png\n" + ex);
			}
		}

		internal static void AddBool(ConfigEntry<bool> entry)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(entry, new CheckBoxConfig
			{
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddBool(ConfigEntry<bool> entry, string categoryName, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(entry, new CheckBoxConfig
			{
				category = categoryName,
				name = name,
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddBool(ConfigEntry<bool> entry, string categoryName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(entry, new CheckBoxConfig
			{
				category = categoryName,
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddEnum<T>(ConfigEntry<T> entry) where T : Enum
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)entry, new ChoiceConfig
			{
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddColor(ConfigEntry<Color> entry)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new ColorOption(entry, new ColorOptionConfig
			{
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddKey(ConfigEntry<KeyboardShortcut> entry)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new KeyBindOption(entry, new KeyBindConfig
			{
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddFloat(ConfigEntry<float> entry, float min, float max, string format = "{0:f2}")
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new SliderOption(entry, new SliderConfig
			{
				min = min,
				max = max,
				formatString = format,
				description = ((ConfigEntryBase)(object)entry).DescWithDefault(format)
			}));
		}

		internal static void AddFloat(ConfigEntry<float> entry, string categoryName, float min, float max, string format = "{0:f2}")
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new SliderOption(entry, new SliderConfig
			{
				min = min,
				max = max,
				formatString = format,
				category = categoryName,
				description = ((ConfigEntryBase)(object)entry).DescWithDefault(format)
			}));
		}

		internal static void AddFloatField(ConfigEntry<float> entry, float min = float.MinValue, float max = float.MaxValue, string format = "{0:f2}")
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			FloatFieldConfig val = new FloatFieldConfig();
			((NumericFieldConfig<float>)val).Min = min;
			((NumericFieldConfig<float>)val).Max = max;
			((BaseOptionConfig)val).description = ((ConfigEntryBase)(object)entry).DescWithDefault(format);
			ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(entry, val));
		}

		internal static void AddInt(ConfigEntry<int> entry, int min = int.MinValue, int max = int.MaxValue)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			IntFieldConfig val = new IntFieldConfig();
			((NumericFieldConfig<int>)val).Min = min;
			((NumericFieldConfig<int>)val).Max = max;
			((BaseOptionConfig)val).description = ((ConfigEntryBase)(object)entry).DescWithDefault();
			ModSettingsManager.AddOption((BaseOption)new IntFieldOption(entry, val));
		}

		internal static void AddIntSlider(ConfigEntry<int> entry, int min, int max)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(entry, new IntSliderConfig
			{
				min = min,
				max = max,
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddIntSlider(ConfigEntry<int> entry, string categoryName, int min, int max)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(entry, new IntSliderConfig
			{
				min = min,
				max = max,
				category = categoryName,
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddString(ConfigEntry<string> entry)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(entry, new InputFieldConfig
			{
				submitOn = (SubmitEnum)6,
				lineType = (LineType)0,
				description = ((ConfigEntryBase)(object)entry).DescWithDefault()
			}));
		}

		internal static void AddOption(ConfigEntry<bool> entry)
		{
			AddBool(entry);
		}

		internal static void AddOption(ConfigEntry<bool> entry, string categoryName, string name)
		{
			AddBool(entry, categoryName, name);
		}

		internal static void AddOption(ConfigEntry<bool> entry, string categoryName)
		{
			AddBool(entry, categoryName);
		}

		internal static void AddOption<T>(ConfigEntry<T> entry) where T : Enum
		{
			AddEnum<T>(entry);
		}

		internal static void AddOption(ConfigEntry<Color> entry)
		{
			AddColor(entry);
		}

		internal static void AddOption(ConfigEntry<KeyboardShortcut> entry)
		{
			AddKey(entry);
		}

		internal static void AddOption(ConfigEntry<int> entry)
		{
			AddInt(entry);
		}

		internal static void AddOption(ConfigEntry<string> entry)
		{
			AddString(entry);
		}

		private static string DescWithDefault(this ConfigEntryBase entry)
		{
			return $"{entry.Description.Description}\n[Default: {entry.DefaultValue}]";
		}

		private static string DescWithDefault(this ConfigEntryBase entry, string format)
		{
			return string.Format("{1}\n[Default: " + format + "]", entry.DefaultValue, entry.Description.Description);
		}
	}
}
namespace ItemStatistics
{
	internal static class Config
	{
		internal enum ResetMode
		{
			Never,
			WhenNotInInventory,
			EveryPickup
		}

		private static ConfigFile configFile;

		internal static ConfigEntry<ResetMode> resetOnStackChanged;

		internal static ConfigEntry<KeyboardShortcut> resetSpamKey;

		internal static void DoConfig(ConfigFile bepConfigFile)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			configFile = bepConfigFile;
			resetOnStackChanged = configFile.Bind<ResetMode>(string.Empty, "Reset on Stack Changed", ResetMode.Never, "When item stack changes, should its stats automatically be reset? Can right click on item to force a reset. Warning: having this enabled will cause stats to be reset during Mithrix's item steal phase");
			resetSpamKey = configFile.Bind<KeyboardShortcut>(string.Empty, "Reset Spam Key", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), "Hold this key down to easily reset icons you hover over");
			if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
			{
				DoRiskOfOptions();
			}
		}

		internal static void DoRiskOfOptions()
		{
			RiskofOptions.SetSpriteDefaultIcon();
			RiskofOptions.AddOption<ResetMode>(resetOnStackChanged);
			RiskofOptions.AddOption(resetSpamKey);
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		private static void ReloadConfig(ConCommandArgs args)
		{
			configFile.Reload();
			Debug.Log((object)"ItemStatistics config reloaded");
		}
	}
	[Serializable]
	public struct Index
	{
		public int index;

		public IndexType type;

		public Index(ItemIndex itemIndex)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected I4, but got Unknown
			index = (int)itemIndex;
			type = IndexType.Item;
		}

		public Index(EquipmentIndex equipIndex)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected I4, but got Unknown
			index = (int)equipIndex;
			type = IndexType.Equip;
		}

		public Index(SkillSlot slotIndex)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected I4, but got Unknown
			index = (int)slotIndex;
			type = IndexType.SkillSlot;
		}

		public Index(int itemIndex, byte indexType)
		{
			index = itemIndex;
			type = (IndexType)indexType;
		}

		public override string ToString()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			switch (type)
			{
			case IndexType.Item:
				return Language.GetString(ItemCatalog.GetItemDef((ItemIndex)index).nameToken);
			case IndexType.Equip:
				return Language.GetString(EquipmentCatalog.GetEquipmentDef((EquipmentIndex)index).nameToken);
			case IndexType.SkillSlot:
			{
				SkillSlot val = (SkillSlot)(sbyte)index;
				return ((object)(SkillSlot)(ref val)).ToString();
			}
			default:
				return "Invalid";
			}
		}

		public static implicit operator Index(ItemIndex itemIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return new Index(itemIndex);
		}

		public static implicit operator Index(ItemDef itemDef)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return new Index(itemDef.itemIndex);
		}

		public static implicit operator Index(EquipmentIndex equipIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return new Index(equipIndex);
		}

		public static implicit operator Index(EquipmentDef equipDef)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return new Index(equipDef.equipmentIndex);
		}

		public static implicit operator Index(SkillSlot slotIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return new Index(slotIndex);
		}

		public static explicit operator ItemIndex(Index index)
		{
			if (index.type != IndexType.Item)
			{
				throw new Exception("Index type is not Item");
			}
			return (ItemIndex)index.index;
		}

		public static explicit operator EquipmentIndex(Index index)
		{
			if (index.type != IndexType.Equip)
			{
				throw new Exception("Index type is not Equip");
			}
			return (EquipmentIndex)index.index;
		}

		public static explicit operator SkillSlot(Index index)
		{
			if (index.type != IndexType.SkillSlot)
			{
				throw new Exception("Index type is not SkillSlot");
			}
			return (SkillSlot)(sbyte)index.index;
		}

		public override bool Equals(object obj)
		{
			if (obj is Index index && type == index.type)
			{
				return this.index == index.index;
			}
			return false;
		}

		public static bool operator ==(Index index, ItemIndex itemIndex)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between I4 and Unknown
			if (index.type == IndexType.Item)
			{
				return index.index == (int)itemIndex;
			}
			return false;
		}

		public static bool operator !=(Index index, ItemIndex itemIndex)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between I4 and Unknown
			if (index.type == IndexType.Item)
			{
				return index.index != (int)itemIndex;
			}
			return true;
		}

		public static bool operator ==(Index index, EquipmentIndex equipIndex)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between I4 and Unknown
			if (index.type == IndexType.Equip)
			{
				return index.index == (int)equipIndex;
			}
			return false;
		}

		public static bool operator !=(Index index, EquipmentIndex equipIndex)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between I4 and Unknown
			if (index.type == IndexType.Equip)
			{
				return index.index != (int)equipIndex;
			}
			return true;
		}

		public static bool operator ==(Index index, SkillSlot slotIndex)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between I4 and Unknown
			if (index.type == IndexType.SkillSlot)
			{
				return index.index == (int)slotIndex;
			}
			return false;
		}

		public static bool operator !=(Index index, SkillSlot slotIndex)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between I4 and Unknown
			if (index.type == IndexType.SkillSlot)
			{
				return index.index != (int)slotIndex;
			}
			return true;
		}
	}
	public enum IndexType : byte
	{
		None,
		Item,
		Equip,
		SkillSlot
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("dolso.ItemStatistics", "ItemStatistics", "1.1.11")]
	public class ItemStatisticsPlugin : BaseUnityPlugin
	{
		public static Dictionary<Index, TrackedDef> itemToTracker;

		public static Action onCatalogLoaded;

		public static GameObject playerTooltip;

		public static GameObject missileLauncher;

		public static GameObject overloadingHeadhunter;

		public static GameObject fireTrailHeadhunter;

		public static int crocoDiseaseProjectileIndex;

		public static BodyIndex falseSonCharacterBodyIndex;

		private void Awake()
		{
			log.start(((BaseUnityPlugin)this).Logger);
			Config.DoConfig(((BaseUnityPlugin)this).Config);
			try
			{
				Utilities.AddressableAddComp<TrackedInventory>("RoR2/Base/Core/PlayerMaster.prefab");
				Utilities.AddressableAddComp<IconBehaviour>("RoR2/Base/UI/ItemIcon.prefab", (Action<IconBehaviour>)delegate(IconBehaviour a)
				{
					a.type = IndexType.Item;
				});
				Utilities.AddressableAddComp<IconBehaviour>("RoR2/Base/UI/ItemIconScoreboard_InGame.prefab", (Action<IconBehaviour>)delegate(IconBehaviour a)
				{
					a.type = IndexType.Item;
				});
				Utilities.GetAddressable("RoR2/Base/UI/HUDSimple.prefab", delegate(GameObject hudsimple)
				{
					EquipmentIcon[] componentsInChildren = hudsimple.GetComponentsInChildren<EquipmentIcon>();
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						((Component)componentsInChildren[i]).gameObject.AddComponent<IconBehaviour>().type = IndexType.Equip;
					}
					SkillIcon[] componentsInChildren2 = hudsimple.GetComponentsInChildren<SkillIcon>();
					for (int i = 0; i < componentsInChildren2.Length; i++)
					{
						((Component)componentsInChildren2[i]).gameObject.AddComponent<IconBehaviour>().type = IndexType.SkillSlot;
					}
				});
				Utilities.GetAddressable("RoR2/Base/UI/ScoreboardStrip.prefab", delegate(GameObject scoreboardStrip)
				{
					((Component)scoreboardStrip.GetComponentInChildren<EquipmentIcon>()).gameObject.AddComponent<IconBehaviour>().type = IndexType.Equip;
					scoreboardStrip.AddComponent<PlayerTooltip>();
				});
				PlayerTooltip.CreateTooltipPrefab();
				Utilities.AddressableAddComp<ToolbotStance>("RoR2/Base/Toolbot/ToolbotBody.prefab");
			}
			catch (Exception ex)
			{
				log.error("Failed to do addressables\n" + ex);
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			GeneralHooks.Hook();
			HCDamage.Hook();
			HCHeal.Hook();
			GEMHooks.Hook();
			ItemHooks.Hook();
			OrbHooks.Hook();
			DotTracking.Hook();
			EquipmentHooks.Hook();
			SurvivorHooks.Hook();
			NetworkHooks.Hook();
			FreezeHooks.Hook();
			log.info($"Hooks completed in {stopwatch.Elapsed.TotalSeconds:f2}s");
			onCatalogLoaded = (Action)Delegate.Combine(onCatalogLoaded, new Action(Mods.DoMods));
		}

		[SystemInitializer(new Type[]
		{
			typeof(PickupCatalog),
			typeof(SurvivorCatalog),
			typeof(ProjectileCatalog)
		})]
		private static void Init()
		{
			//IL_0bba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bbf: Unknown result type (might be due to invalid IL or missing references)
			itemToTracker = new Dictionary<Index, TrackedDef>
			{
				{
					(SkillSlot)0,
					new TrackedDef(TrackedDef.Skill)
				},
				{
					(SkillSlot)1,
					new TrackedDef(TrackedDef.Skill)
				},
				{
					(SkillSlot)2,
					new TrackedDef(TrackedDef.Skill)
				},
				{
					(SkillSlot)3,
					new TrackedDef(TrackedDef.Skill)
				},
				{
					Items.Bear,
					new TrackedDef(TrackedDef.ArmorCount)
				},
				{
					Items.BearVoid,
					new TrackedDef(TrackedDef.ArmorCount)
				},
				{
					Items.Crowbar,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.ExplodeOnDeathVoid,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.NearbyDamageBonus,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.FragileDamageBonus,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.FragileDamageBonusConsumed,
					new TrackedDef(TrackedDef.Watch)
				},
				{
					Items.PermanentDebuffOnHit,
					new TrackedDef(TrackedDef.Chance)
				},
				{
					Items.BossDamageBonus,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.CritGlasses,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.CritDamage,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.DeathMark,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.CritGlassesVoid,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.ExecuteLowHealthElite,
					new TrackedDef(TrackedDef.Damage, TrackedDef.portionTooltip)
				},
				{
					Items.OutOfCombatArmor,
					new TrackedDef(TrackedDef.ArmorCount)
				},
				{
					Items.SprintArmor,
					new TrackedDef(TrackedDef.Armor)
				},
				{
					Items.ArmorPlate,
					new TrackedDef(TrackedDef.Armor)
				},
				{
					Items.ParentEgg,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.GoldOnHit,
					new TrackedDef(TrackedDef.Gold)
				},
				{
					Items.GoldOnHurt,
					new TrackedDef(TrackedDef.Gold)
				},
				{
					Items.Thorns,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.Seed,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.BleedOnHit,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.BleedOnHitVoid,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.SlowOnHitVoid,
					new TrackedDef(TrackedDef.Chance)
				},
				{
					Items.Missile,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.MissileVoid,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.ChainLightning,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.ChainLightningVoid,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.BounceNearby,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.StickyBomb,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.IceRing,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.FireRing,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.ElementalRingVoid,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.FireballsOnHit,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.LightningStrikeOnHit,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.HealOnCrit,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.Behemoth,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.IgniteOnKill,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.ExplodeOnDeath,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.Dagger,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.Tooth,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.Bandolier,
					new TrackedDef(TrackedDef.Chance)
				},
				{
					Items.BonusGoldPackOnKill,
					new TrackedDef(TrackedDef.Gold)
				},
				{
					Items.BleedOnHitAndExplode,
					new TrackedDef(TrackedDef.DamageChance, TrackedDef.hit_damageTooltip)
				},
				{
					Items.Plant,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.Mushroom,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.MushroomVoid,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.Medkit,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.TPHealingNova,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.HealingPotionConsumed,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.ShockNearby,
					new TrackedDef(TrackedDef.Damage, TrackedDef.portionTooltip)
				},
				{
					Items.PrimarySkillShuriken,
					new TrackedDef(TrackedDef.DamageChance, TrackedDef.hit_damageTooltip)
				},
				{
					Items.StrengthenBurn,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.LaserTurbine,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.CaptainDefenseMatrix,
					new TrackedDef(TrackedDef.Count)
				},
				{
					Items.Icicle,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.NovaOnLowHealth,
					new TrackedDef(TrackedDef.Damage, TrackedDef.portionTooltip)
				},
				{
					Items.ImmuneToDebuff,
					new TrackedDef(TrackedDef.Chance)
				},
				{
					Items.NovaOnHeal,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.SprintWisp,
					new TrackedDef(TrackedDef.Damage, TrackedDef.portionTooltip)
				},
				{
					Items.RandomlyLunar,
					new TrackedDef(TrackedDef.Chance)
				},
				{
					Items.Firework,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.Phasing,
					new TrackedDef(TrackedDef.Count)
				},
				{
					Items.FallBoots,
					new TrackedDef(TrackedDef.Damage, TrackedDef.portionTooltip)
				},
				{
					Items.SiphonOnLowHealth,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Items.LunarSun,
					new TrackedDef(TrackedDef.Damage, TrackedDef.portionTooltip)
				},
				{
					Items.Infusion,
					new TrackedDef(TrackedDef.Count)
				},
				{
					Items.HeadHunter,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.RoboBallBuddy,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.VoidMegaCrabItem,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.BeetleGland,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.DroneWeapons,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.GhostOnKill,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.MinorConstructOnKill,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.Squid,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.TitanGoldDuringTP,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.LowerHealthHigherDamage,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.NegateAttack,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.ExtraShrineItem,
					new TrackedDef(TrackedDef.Chance)
				},
				{
					Items.IncreasePrimaryDamage,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Items.MeteorAttackOnHighDamage,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.KnockBackHitEnemies,
					new TrackedDef(TrackedDef.Chance)
				},
				{
					Items.StunAndPierce,
					new TrackedDef(TrackedDef.DamageChance)
				},
				{
					Items.LowerPricedChests,
					new TrackedDef(TrackedDef.Count)
				},
				{
					Items.LowerPricedChestsConsumed,
					new TrackedDef(TrackedDef.Count)
				},
				{
					Items.ResetChests,
					new TrackedDef(TrackedDef.Chance)
				},
				{
					Items.GoldOnStageStart,
					new TrackedDef(TrackedDef.Gold)
				},
				{
					Items.TeleportOnLowHealth,
					new TrackedDef(TrackedDef.Count)
				},
				{
					Equipment.Saw,
					new TrackedDef(TrackedDef.Damage, TrackedDef.portionTooltip)
				},
				{
					Equipment.GoldGat,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.BFG,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.PassiveHealing,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Equipment.CommandMissile,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.Fruit,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Equipment.DroneBackup,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.Lightning,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.Recycle,
					new TrackedDef(TrackedDef.Count, TrackedDef.recycledTooltip)
				},
				{
					Equipment.LifestealOnHit,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Equipment.Molotov,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.VendingMachine,
					new TrackedDef(TrackedDef.Heal)
				},
				{
					Equipment.GummyClone,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.MultiShopCard,
					new TrackedDef(TrackedDef.Gold)
				},
				{
					Equipment.GainArmor,
					new TrackedDef(TrackedDef.Armor)
				},
				{
					Equipment.Meteor,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.BurnNearby,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.AffixRed,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.AffixBlue,
					new TrackedDef(TrackedDef.Damage)
				},
				{
					Equipment.AffixWhite,
					new TrackedDef(TrackedDef.Damage)
				}
			};
			crocoDiseaseProjectileIndex = ProjectileCatalog.FindProjectileIndex("CrocoDiseaseProjectile");
			falseSonCharacterBodyIndex = BodyCatalog.FindBodyIndex("FalseSonBody");
			ModifyPrefabs();
			onCatalogLoaded?.Invoke();
		}

		private static void ModifyPrefabs()
		{
			AddProcComponent("RoR2/Base/StickyBomb/StickyBomb.prefab", Items.StickyBomb);
			AddProcComponent("RoR2/Base/ElementalRings/FireTornado.prefab", Items.FireRing);
			AddProcComponent("RoR2/DLC1/ElementalRingVoid/ElementalRingVoidBlackHole.prefab", Items.ElementalRingVoid);
			AddProcComponent("RoR2/Base/FireballsOnHit/FireMeatBall.prefab", Items.FireballsOnHit);
			AddProcComponent("RoR2/DLC1/PrimarySkillShuriken/ShurikenProjectile.prefab", Items.PrimarySkillShuriken);
			AddProcComponent("RoR2/Base/LaserTurbine/LaserTurbineController.prefab", Items.LaserTurbine);
			AddProcComponent("RoR2/Base/LaserTurbine/LaserTurbineBomb.prefab", Items.LaserTurbine);
			AddProcComponent("RoR2/Base/Icicle/IcicleAura.prefab", Items.Icicle);
			AddProcComponent("RoR2/Base/NovaOnLowHealth/VagrantNovaItemBodyAttachment.prefab", Items.NovaOnLowHealth);
			AddProcComponent("RoR2/Base/Firework/FireworkProjectile.prefab", Items.Firework);
			AddProcComponent("RoR2/DLC1/LunarSun/LunarSunProjectile.prefab", Items.LunarSun);
			AddProcComponent("RoR2/DLC2/Items/StunAndPierce/StunAndPierceBoomerang.prefab", Items.StunAndPierce);
			CommonAssets.daggerPrefab.AddComponent<ProcComponent>().index = Items.Dagger;
			CommonAssets.bleedOnHitAndExplodeBlastEffect.AddComponent<ProcComponent>().index = Items.BleedOnHitAndExplode;
			AddProcComponent("RoR2/Base/Mushroom/MushroomWard.prefab", Items.Mushroom);
			AddProcComponent("RoR2/Base/Plant/DeskplantWard.prefab", Items.Plant);
			AddMinionComponent("RoR2/Base/RoboBallBuddy/RoboBallGreenBuddyBody.prefab", Items.RoboBallBuddy);
			AddMinionComponent("RoR2/Base/RoboBallBuddy/RoboBallRedBuddyBody.prefab", Items.RoboBallBuddy);
			AddMinionComponent("RoR2/DLC1/VoidJailer/VoidJailerAllyBody.prefab", Items.VoidMegaCrabItem);
			AddMinionComponent("RoR2/Base/Nullifier/NullifierAllyBody.prefab", Items.VoidMegaCrabItem);
			AddMinionComponent("RoR2/DLC1/VoidMegaCrab/VoidMegaCrabAllyBody.prefab", Items.VoidMegaCrabItem);
			AddMinionComponent("RoR2/Base/BeetleGland/BeetleGuardAllyBody.prefab", Items.BeetleGland);
			AddMinionComponent("RoR2/Base/Squid/SquidTurretBody.prefab", Items.Squid);
			AddMinionComponent("RoR2/DLC1/MajorAndMinorConstruct/MinorConstructOnKillBody.prefab", Items.MinorConstructOnKill);
			AddMinionComponent("RoR2/Base/Titan/TitanGoldBody.prefab", Items.TitanGoldDuringTP);
			AddMinionComponent("RoR2/Base/Drones/BackupDroneBody.prefab", Equipment.DroneBackup);
			Utilities.AddressableAddComp<ProjectileBehaviour>("RoR2/Base/Nullifier/NullifierDeathBombProjectile.prefab", (Action<ProjectileBehaviour>)delegate(ProjectileBehaviour a)
			{
				a.projectile = ProjectileBehaviour.Projectile.Zoea;
			});
			Utilities.AddressableAddComp<ProjectileBehaviour>("RoR2/DLC1/VoidJailer/VoidJailerDeathBombProjectile.prefab", (Action<ProjectileBehaviour>)delegate(ProjectileBehaviour a)
			{
				a.projectile = ProjectileBehaviour.Projectile.Zoea;
			});
			Utilities.AddressableAddComp<ProjectileBehaviour>("RoR2/DLC1/VoidMegaCrab/VoidMegaCrabDeathBombProjectile.prefab", (Action<ProjectileBehaviour>)delegate(ProjectileBehaviour a)
			{
				a.projectile = ProjectileBehaviour.Projectile.ZoeaDeathBomblet;
			});
			Utilities.AddressableAddComp<ProjectileBehaviour>("RoR2/DLC1/VoidMegaCrab/VoidMegaCrabDeathBombletsProjectile.prefab", (Action<ProjectileBehaviour>)delegate(ProjectileBehaviour a)
			{
				a.projectile = ProjectileBehaviour.Projectile.Zoea;
			});
			AddProcComponent("RoR2/Base/Saw/Sawmerang.prefab", Equipment.Saw);
			AddProcComponent("RoR2/Base/GoldGat/GoldGatController.prefab", Equipment.GoldGat);
			AddProcComponent("RoR2/Base/BFG/BeamSphere.prefab", Equipment.BFG);
			AddProcComponent("RoR2/DLC1/Molotov/MolotovClusterProjectile.prefab", Equipment.Molotov);
			AddProcComponent("RoR2/DLC1/Molotov/MolotovSingleProjectile.prefab", Equipment.Molotov);
			AddProcComponent("RoR2/DLC1/Molotov/MolotovProjectileDotZone.prefab", Equipment.Molotov);
			AddProcComponent("RoR2/Base/Mage/MageFireboltBasic.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/Base/Mage/MageLightningboltBasic.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/Base/Mage/MageIceBombProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Mage/MageLightningBombProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Mage/MageIcewallPillarProjectile.prefab", (SkillSlot)2);
			AddProcComponent("RoR2/Base/Merc/EvisProjectile.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Merc/EvisOverlapProjectile.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Commando/FMJRamping.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Commando/CommandoGrenadeProjectile.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Captain/CaptainAirstrikeProjectile1.prefab", (SkillSlot)2);
			AddProcComponent("RoR2/Base/Captain/CaptainAirstrikeAltProjectile.prefab", (SkillSlot)2);
			AddProcComponent("RoR2/Base/Captain/CaptainSupplyDrop, Base.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Captain/CaptainSupplyDrop, EquipmentRestock.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Captain/CaptainSupplyDrop, Hacking.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Captain/CaptainSupplyDrop, Healing.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Captain/CaptainSupplyDrop, Shocking.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Captain/CaptainTazer.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Huntress/HuntressArrowRain.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Loader/LoaderYankHook.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Loader/LoaderZapCone.prefab", (SkillSlot)2);
			AddProcComponent("RoR2/Base/Loader/LoaderPylon.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Engi/EngiGrenadeProjectile.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/Base/Engi/EngiHarpoon.prefab", (SkillSlot)2);
			AddMinionComponent("RoR2/Base/Engi/EngiTurretBody.prefab", (SkillSlot)3);
			AddMinionComponent("RoR2/Base/Engi/EngiWalkerTurretBody.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Croco/CrocoSpit.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Croco/CrocoLeapAcid.prefab", (SkillSlot)2);
			AddProcComponent("RoR2/Base/Croco/CrocoDiseaseProjectile.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Toolbot/ToolbotGrenadeLauncherProjectile.prefab", (SkillSlot)0);
			Utilities.GetAddressable("RoR2/Base/Toolbot/ToolbotGrenadeLauncherProjectile.prefab", delegate(GameObject a)
			{
				a.AddComponent<ProjectileBehaviour>().projectile = ProjectileBehaviour.Projectile.ScrapLauncher;
			});
			AddProcComponent("RoR2/Base/Toolbot/CryoCanisterProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Toolbot/CryoCanisterBombletsProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Bandit2/Bandit2ShivProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/DLC1/Railgunner/RailgunnerPistolProjectile.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/Base/Treebot/SyringeProjectile.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/Base/Treebot/SyringeProjectileHealing.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/Base/Treebot/TreebotMortar2.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Treebot/TreebotMortarRain.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/Treebot/TreebotFlowerSeed.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/Base/Treebot/TreebotFruitSeedProjectile.prefab", (SkillSlot)3);
			Utilities.GetAddressable<GameObject>("RoR2/Base/Treebot/TreebotFruitPack.prefab", (Action<GameObject>)delegate(GameObject a)
			{
				((Component)a.GetComponentInChildren<HealthPickup>()).gameObject.AddComponent<ProcComponent>().index = (SkillSlot)3;
			});
			AddProcComponent("RoR2/DLC1/VoidSurvivor/VoidSurvivorMegaBlasterSmallProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/DLC1/VoidSurvivor/VoidSurvivorMegaBlasterBigProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/DLC1/VoidSurvivor/VoidSurvivorMegaBlasterBigProjectileCorrupted.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/Base/LunarSkillReplacements/LunarNeedleProjectile.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/Base/LunarSkillReplacements/LunarSecondaryProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/DLC2/Seeker/SpiritPunchProjectile.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/DLC2/Seeker/SpiritPunchFinisherProjectile.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/DLC2/Seeker/SoulSpiralProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/DLC2/Seeker/UnseenHandMovingProjectile.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/DLC2/Seeker/SojournVehicle/SojournVehicle.prefab", (SkillSlot)2);
			AddProcComponent("RoR2/DLC2/FalseSon/LunarSpike.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/DLC2/Chef/ChefCleaver.prefab", (SkillSlot)0);
			AddProcComponent("RoR2/DLC2/Chef/ChefDiceEnhanced.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC2/Chef/BoostedSearFireballProjectile.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC2/Chef/BoostedRolyPolyProjectile.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC2/Chef/ChefGlazeProjectile.prefab", (SkillSlot)3);
			missileLauncher = Utilities.CreatePrefab(CommonAssets.missilePrefab);
			missileLauncher.AddComponent<ProcComponent>().index = Equipment.CommandMissile;
			((Object)missileLauncher).name = "MissileLauncherProjectile";
			CommonAssets.missilePrefab = Utilities.CreatePrefab(CommonAssets.missilePrefab);
			CommonAssets.missilePrefab.AddComponent<ProcComponent>().index = Items.Missile;
			Utilities.GetAddressable("RoR2/Base/EliteLightning/LightningStake.prefab", delegate(GameObject blueorb)
			{
				overloadingHeadhunter = Utilities.CreatePrefab(blueorb);
				overloadingHeadhunter.AddComponent<ProcComponent>().index = Items.HeadHunter;
				blueorb.AddComponent<ProcComponent>().index = Equipment.AffixBlue;
			});
			AddProcComponent("RoR2/Base/Common/FireTrail.prefab", Equipment.AffixRed);
		}

		private static void AddProcComponent(string addressable, Index index)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable);
			val.Completed += delegate(AsyncOperationHandle<GameObject> a)
			{
				a.Result.AddComponent<ProcComponent>().index = index;
			};
		}

		private static void AddMinionComponent(string addressable, Index index)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable);
			val.Completed += delegate(AsyncOperationHandle<GameObject> a)
			{
				a.Result.AddComponent<MinionComponent>().index = index;
			};
		}
	}
	internal static class Mods
	{
		internal const string magriderGuid = "dolso.magrdier";

		internal static void DoMods()
		{
			TryMod(LoadMagrider, "dolso.magrdier");
		}

		private static void TryMod(Action DoMod, string modGuid)
		{
			if (Chainloader.PluginInfos.ContainsKey(modGuid))
			{
				try
				{
					DoMod();
				}
				catch (Exception arg)
				{
					log.error($"Failed to load mod {modGuid}\n{arg}");
				}
			}
		}

		private static void LoadMagrider()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			Blaster.projectilePrefab.AddComponent<ProcComponent>().index = (SkillSlot)0;
			Cannon.projectilePrefab.AddComponent<ProcComponent>().index = (SkillSlot)0;
			HookManager.Hook(typeof(MagriderCollision), "ApplyHit", new Manipulator(IL_MagriderCollision_ApplyHit_Inflictor));
		}

		private static void IL_MagriderCollision_ApplyHit_Inflictor(ILContext context)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ILCursor val = new ILCursor(context);
			val.AddInflictorToAttack<DamageInfo>((SkillSlot)2);
			if (val.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(BlastAttack), "ClientReportDamage")
			}))
			{
				val.EmitDelegate<Action>((Action)delegate
				{
					NetworkHooks.inflictorIndex = (SkillSlot)2;
				});
				int index = val.Index;
				val.Index = index + 1;
				val.EmitClearNetworkParameters();
			}
		}
	}
	public class ReverseTree
	{
		public Index value;

		public ReverseTree parent;

		public ReverseTree(Index value, ReverseTree parent)
		{
			this.value = value;
			this.parent = parent;
		}

		public override string ToString()
		{
			string text = value.ToString();
			for (ReverseTree reverseTree = parent; reverseTree != null; reverseTree = reverseTree.parent)
			{
				text += $" -> {reverseTree.value}";
			}
			return text;
		}
	}
	[Serializable]
	public struct Totals
	{
		public static float allDamageDealt;

		public float damageDealt;

		public float minionDamageDealt;

		public float damageTaken;

		public float healed;

		public uint goldEarned;
	}
	public struct TrackedDef
	{
		public const string tooltipPrefix = "ITEMSTATISTICS_TOOLTIPS_";

		public static readonly string damageTooltip = "ITEMSTATISTICS_TOOLTIPS_DAMAGE";

		public static readonly string chanceTooltip = "ITEMSTATISTICS_TOOLTIPS_CHANCE";

		public static readonly string countTooltip = "ITEMSTATISTICS_TOOLTIPS_COUNT";

		public static readonly string healTooltip = "ITEMSTATISTICS_TOOLTIPS_HEAL";

		public static readonly string goldTooltip = "ITEMSTATISTICS_TOOLTIPS_GOLD";

		public static readonly string reductionTooltip = "ITEMSTATISTICS_TOOLTIPS_REDUCTION";

		public static readonly string recycledTooltip = "ITEMSTATISTICS_TOOLTIPS_RECYCLED";

		public static readonly string portionTooltip = "ITEMSTATISTICS_TOOLTIPS_DAMAGEPORTION";

		public static readonly string count_chanceTooltip = "ITEMSTATISTICS_TOOLTIPS_COUNT_CHANCE";

		public static readonly string chance_damageTooltip = "ITEMSTATISTICS_TOOLTIPS_CHANCE_DAMAGE";

		public static readonly string reduction_countTooltip = "ITEMSTATISTICS_TOOLTIPS_REDUCTION_COUNT";

		public static readonly string hit_damageTooltip = "ITEMSTATISTICS_TOOLTIPS_HIT_DAMAGE";

		public static readonly string heal_countTooltip = "ITEMSTATISTICS_TOOLTIPS_HEAL_COUNT";

		public static readonly string portion_healTooltip = "ITEMSTATISTICS_TOOLTIPS_PORTION_HEAL";

		public static readonly string minion_portionTooltip = "ITEMSTATISTICS_TOOLTIPS_MINION_PORTION";

		public static readonly Type ArmorCount = typeof(ArmorCountTracker);

		public static readonly Type Armor = typeof(ArmorTracker);

		public static readonly Type Chance = typeof(ChanceTracker);

		public static readonly Type Count = typeof(CountTracker);

		public static readonly Type DamageChance = typeof(DamageChanceTracker);

		public static readonly Type Watch = typeof(WatchTracker);

		public static readonly Type Skill = typeof(SkillTracker);

		public static readonly Type Damage = typeof(DamageTracker);

		public static readonly Type Gold = typeof(GoldTracker);

		public static readonly Type Heal = typeof(HealTracker);

		public Type trackedType;

		public string tooltipTokenOverride;

		public TrackedDef(Type trackedType)
		{
			tooltipTokenOverride = null;
			this.trackedType = trackedType;
		}

		public TrackedDef(Type trackedType, string tooltipTokenOverride)
		{
			this.tooltipTokenOverride = null;
			this.tooltipTokenOverride = tooltipTokenOverride;
			this.trackedType = trackedType;
		}

		public string GetTooltip(IItemTracker tracker, in Totals totals)
		{
			string[] tooltipArgs = tracker.GetTooltipArgs(in totals);
			if (tooltipTokenOverride != null)
			{
				string text = tooltipTokenOverride;
				object[] array = tooltipArgs;
				return Language.GetStringFormatted(text, array);
			}
			if (!(tracker is SkillTracker))
			{
				if (!(tracker is WatchTracker))
				{
					object[] array;
					if (!(tracker is DamageTracker))
					{
						if (!(tracker is ArmorCountTracker))
						{
							if (!(tracker is ArmorTracker))
							{
								if (!(tracker is ChanceTracker))
								{
									if (!(tracker is CountTracker))
									{
										if (!(tracker is DamageChanceTracker))
										{
											if (!(tracker is GoldTracker))
											{
												if (tracker is HealTracker)
												{
													string text2 = healTooltip;
													array = tooltipArgs;
													return Language.GetStringFormatted(text2, array);
												}
												return (tooltipArgs == null) ? "" : string.Concat(tooltipArgs);
											}
											string text3 = goldTooltip;
											array = tooltipArgs;
											return Language.GetStringFormatted(text3, array);
										}
										string text4 = chance_damageTooltip;
										array = tooltipArgs;
										return Language.GetStringFormatted(text4, array);
									}
									string text5 = countTooltip;
									array = tooltipArgs;
									return Language.GetStringFormatted(text5, array);
								}
								string text6 = count_chanceTooltip;
								array = tooltipArgs;
								return Language.GetStringFormatted(text6, array);
							}
							string text7 = reductionTooltip;
							array = tooltipArgs;
							return Language.GetStringFormatted(text7, array);
						}
						string text8 = reduction_countTooltip;
						array = tooltipArgs;
						return Language.GetStringFormatted(text8, array);
					}
					string text9 = damageTooltip;
					array = tooltipArgs;
					return Language.GetStringFormatted(text9, array);
				}
				object result;
				if (tooltipArgs != null)
				{
					string text10 = damageTooltip;
					object[] array = tooltipArgs;
					result = Language.GetStringFormatted(text10, array);
				}
				else
				{
					result = "";
				}
				return (string)result;
			}
			object result2;
			if (tooltipArgs != null)
			{
				string token = SkillTracker.GetToken(tooltipArgs);
				object[] array = tooltipArgs;
				result2 = Language.GetStringFormatted(token, array);
			}
			else
			{
				result2 = "";
			}
			return (string)result2;
		}

		internal IItemTracker CreateTracker()
		{
			return (IItemTracker)Activator.CreateInstance(trackedType);
		}

		[SystemInitializer(new Type[] { })]
		private static void Init()
		{
			Language.english.SetStringsByTokens((IEnumerable<KeyValuePair<string, string>>)new KeyValuePair<string, string>[15]
			{
				new KeyValuePair<string, string>(damageTooltip, "Average damage increase: <style=cIsDamage>{0}</style>"),
				new KeyValuePair<string, string>(chanceTooltip, "Success rate: <style=cIsDamage>{0}</style>"),
				new KeyValuePair<string, string>(countTooltip, "Success count: <style=cIsDamage>{0}</style>"),
				new KeyValuePair<string, string>(healTooltip, "Heal portion: <style=cIsHealing>{0}</style>"),
				new KeyValuePair<string, string>(goldTooltip, "Average gold increase: <style=cIsDamage>{0}</style>"),
				new KeyValuePair<string, string>(reductionTooltip, "Average reduction: <style=cIsHealing>{0}</style>"),
				new KeyValuePair<string, string>(recycledTooltip, "Recycled: <style=cIsDamage>{0}</style>"),
				new KeyValuePair<string, string>(portionTooltip, "Damage portion: <style=cIsHealing>{1}</style>"),
				new KeyValuePair<string, string>(count_chanceTooltip, "Success count: <style=cIsDamage>{0}</style>\nSuccess rate: <style=cIsDamage>{1}</style>"),
				new KeyValuePair<string, string>(chance_damageTooltip, "Success rate: <style=cIsDamage>{0}</style>\nAverage damage increase: <style=cIsDamage>{1}</style>"),
				new KeyValuePair<string, string>(reduction_countTooltip, "Average reduction: <style=cIsHealing>{0}</style>\nSuccess count: <style=cIsDamage>{1}</style>"),
				new KeyValuePair<string, string>(hit_damageTooltip, "Hit rate: <style=cIsDamage>{0}</style>\nAverage damage increase: <style=cIsDamage>{1}</style>"),
				new KeyValuePair<string, string>(heal_countTooltip, "Heal portion: <style=cIsHealing>{0}</style>\nTotal healing: <style=cIsUtility>{1}</style>"),
				new KeyValuePair<string, string>(portion_healTooltip, "Damage portion: <style=cIsUtility>{1}</style>\nHeal portion: <style=cIsHealing>{0}</style>"),
				new KeyValuePair<string, string>(minion_portionTooltip, "Local minion portion: <style=cIsDamage>{0}</style>\nGlobal damage portion: <style=cIsHealing>{1}</style>")
			});
		}
	}
}
namespace ItemStatistics.Trackers
{
	public class ArmorCountTracker : IItemTracker, IReductionTracker, IChanceTracker
	{
		private float globalDamageTakenWhenSet;

		private float damageBlocked;

		private uint attempted;

		private uint succedded;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void Attempted()
		{
			log.warning("Called Attempted on ArmorChanceTracker");
		}

		public void Succedded()
		{
			succedded++;
			dirtyBit = true;
		}

		public void AddBlockedDamage(float blocked)
		{
			damageBlocked += blocked;
			dirtyBit = true;
		}

		public string[] GetTooltipArgs(in Totals totals)
		{
			return new string[2]
			{
				TrackerStatics.ReductionToString(damageBlocked, totals.damageTaken - globalDamageTakenWhenSet),
				succedded.ToString()
			};
		}

		public void Reset(in Totals totals)
		{
			attempted = 0u;
			succedded = 0u;
			damageBlocked = 0f;
			globalDamageTakenWhenSet = totals.damageTaken;
		}

		public void Serialize(out uint[] ints, out float[] floats)
		{
			ints = new uint[2] { attempted, succedded };
			floats = new float[1] { damageBlocked };
		}

		public void Deserialize(uint[] ints, float[] floats)
		{
			damageBlocked = floats[0];
			attempted = ints[0];
			succedded = ints[1];
		}

		string[] IItemTracker.GetTooltipArgs(in Totals totals)
		{
			return GetTooltipArgs(in totals);
		}

		void IItemTracker.Reset(in Totals totals)
		{
			Reset(in totals);
		}
	}
	public class ArmorTracker : IItemTracker, IReductionTracker
	{
		private float globalDamageTakenWhenSet;

		private float damageBlocked;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void AddBlockedDamage(float blocked)
		{
			damageBlocked += blocked;
			dirtyBit = true;
		}

		public string[] GetTooltipArgs(in Totals totals)
		{
			return new string[1] { TrackerStatics.ReductionToString(damageBlocked, totals.damageTaken - globalDamageTakenWhenSet) };
		}

		public void Reset(in Totals totals)
		{
			damageBlocked = 0f;
			globalDamageTakenWhenSet = totals.damageTaken;
		}

		public void Serialize(out uint[] ints, out float[] floats)
		{
			ints = null;
			floats = new float[1] { damageBlocked };
		}

		public void Deserialize(uint[] ints, float[] floats)
		{
			damageBlocked = floats[0];
		}

		string[] IItemTracker.GetTooltipArgs(in Totals totals)
		{
			return GetTooltipArgs(in totals);
		}

		void IItemTracker.Reset(in Totals totals)
		{
			Reset(in totals);
		}
	}
	public class ChanceTracker : IItemTracker, IChanceTracker
	{
		private uint attempted;

		private uint succedded;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void Attempted()
		{
			attempted++;
			dirtyBit = true;
		}

		public void Succedded()
		{
			succedded++;
			dirtyBit = true;
		}

		public string[] GetTooltipArgs(in Totals totals)
		{
			return new string[2]
			{
				succedded.ToString(),
				TrackerStatics.ChanceToString(attempted, succedded)
			};
		}

		public void Reset(in Totals totals)
		{
			attempted = 0u;
			succedded = 0u;
		}

		public void Serialize(out uint[] ints, out float[] floats)
		{
			ints = new uint[2] { attempted, succedded };
			floats = null;
		}

		public void Deserialize(uint[] ints, float[] floats)
		{
			attempted = ints[0];
			succedded = ints[1];
		}

		string[] IItemTracker.GetTooltipArgs(in Totals totals)
		{
			return GetTooltipArgs(in totals);
		}

		void IItemTracker.Reset(in Totals totals)
		{
			Reset(in totals);
		}
	}
	public class CountTracker : IItemTracker, IChanceTracker
	{
		private uint succedded;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void Attempted()
		{
			log.error("Called Attempted on CountTracker");
		}

		public void Succedded()
		{
			succedded++;
			dirtyBit = true;
		}

		public string[] GetTooltipArgs(in Totals totals)
		{
			return new string[1] { succedded.ToString() };
		}

		public void Reset(in Totals totals)
		{
			succedded = 0u;
		}

		public void Serialize(out uint[] ints, out float[] floats)
		{
			ints = new uint[1] { succedded };
			floats = null;
		}

		public void Deserialize(uint[] ints, float[] floats)
		{
			succedded = ints[0];
		}

		string[] IItemTracker.GetTooltipArgs(in Totals totals)
		{
			return GetTooltipArgs(in totals);
		}

		void IItemTracker.Reset(in Totals totals)
		{
			Reset(in totals);
		}
	}
	public class DamageChanceTracker : IItemTracker, IChanceTracker, IDamageTracker
	{
		private float globalDamageWhenSet;

		private float itemDamage;

		private uint attempted;

		private uint succedded;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void Attempted()
		{
			attempted++;
			dirtyBit = true;
		}

		public void Succedded()
		{
			succedded++;
			dirtyBit = true;
		}

		public void AddItemDamage(float damage)
		{
			itemDamage += damage;
			dirtyBit = true;
		}

		public string[] GetTooltipArgs(in Totals totals)
		{
			return new string[2]
			{
				TrackerStatics.ChanceToString(attempted, succedded),
				TrackerStatics.IncreaseToString(itemDamage, totals.damageDealt - globalDamageWhenSet)
			};
		}

		public void Reset(in Totals totals)
		{
			attempted = 0u;
			succedded = 0u;
			itemDamage = 0f;
			globalDamageWhenSet = totals.damageDealt;
		}

		public void Serialize(out uint[] ints, out float[] floats)
		{
			ints = new uint[2] { attempted, succedded };
			floats = new float[1] { itemDamage };
		}

		public void Deserialize(uint[] ints, float[] floats)
		{
			itemDamage = floats[0];
			attempted = ints[0];
			succedded = ints[1];
		}

		string[] IItemTracker.GetTooltipArgs(in Totals totals)
		{
			return GetTooltipArgs(in totals);
		}

		void IItemTracker.Reset(in Totals totals)
		{
			Reset(in totals);
		}
	}
	public class DamageTracker : IItemTracker, IDamageTracker
	{
		internal float globalDamageWhenSet;

		internal float itemDamage;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void AddItemDamage(float damage)
		{
			itemDamage += damage;
			dirtyBit = true;
		}

		public virtual string[] GetTooltipArgs(in Totals totals)
		{
			return new string[2]
			{
				TrackerStatics.IncreaseToString(itemDamage, totals.damageDealt - globalDamageWhenSet),
				TrackerStatics.PortionToString(itemDamage, totals.damageDealt - globalDamageWhenSet)
			};
		}

		public virtual void Reset(in Totals totals)
		{
			itemDamage = 0f;
			globalDamageWhenSet = totals.damageDealt;
		}

		public virtual void Serialize(out uint[] ints, out float[] floats)
		{
			ints = null;
			floats = new float[1] { itemDamage };
		}

		public virtual void Deserialize(uint[] ints, float[] floats)
		{
			itemDamage = floats[0];
		}
	}
	public class GoldTracker : IItemTracker
	{
		private float globalEarnedWhenSet;

		private float itemEarned;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void AddGold(float gold)
		{
			itemEarned += gold;
			dirtyBit = true;
		}

		public string[] GetTooltipArgs(in Totals totals)
		{
			return new string[1] { TrackerStatics.IncreaseToString(itemEarned, (float)totals.goldEarned - globalEarnedWhenSet) };
		}

		public void Reset(in Totals totals)
		{
			itemEarned = 0f;
			globalEarnedWhenSet = totals.goldEarned;
		}

		public void Serialize(out uint[] ints, out float[] floats)
		{
			ints = null;
			floats = new float[1] { itemEarned };
		}

		public void Deserialize(uint[] ints, float[] floats)
		{
			itemEarned = floats[0];
		}

		string[] IItemTracker.GetTooltipArgs(in Totals totals)
		{
			return GetTooltipArgs(in totals);
		}

		void IItemTracker.Reset(in Totals totals)
		{
			Reset(in totals);
		}
	}
	public class HealTracker : IItemTracker, IHealTracker
	{
		private float itemHealed;

		private float globalHealedWhenSet;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void AddHealing(float heal)
		{
			itemHealed += heal;
			dirtyBit = true;
		}

		public string[] GetTooltipArgs(in Totals totals)
		{
			return new string[2]
			{
				TrackerStatics.PortionToString(itemHealed, totals.healed - globalHealedWhenSet),
				itemHealed.ToString("0")
			};
		}

		public void Reset(in Totals totals)
		{
			itemHealed = 0f;
			globalHealedWhenSet = totals.healed;
		}

		public void Serialize(out uint[] ints, out float[] floats)
		{
			ints = null;
			floats = new float[1] { itemHealed };
		}

		public void Deserialize(uint[] ints, float[] floats)
		{
			itemHealed = floats[0];
		}

		string[] IItemTracker.GetTooltipArgs(in Totals totals)
		{
			return GetTooltipArgs(in totals);
		}

		void IItemTracker.Reset(in Totals totals)
		{
			Reset(in totals);
		}
	}
	public interface IItemTracker
	{
		int itemCount { get; set; }

		bool dirtyBit { get; set; }

		string[] GetTooltipArgs(in Totals totals);

		void Reset(in Totals totals);

		void Serialize(out uint[] ints, out float[] floats);

		void Deserialize(uint[] ints, float[] floats);
	}
	public interface IChanceTracker
	{
		void Attempted();

		void Succedded();
	}
	public interface IDamageTracker
	{
		void AddItemDamage(float damage);
	}
	public interface IHealTracker
	{
		void AddHealing(float heal);
	}
	public interface IReductionTracker
	{
		void AddBlockedDamage(float blocked);
	}
	public class SkillTracker : IItemTracker, IDamageTracker, IHealTracker
	{
		private float itemDamage;

		private float itemHealed;

		private float globalDamageWhenSet;

		private float globalHealedWhenSet;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

		public void AddItemDamage(float damage)
		{
			itemDamage += damage;
			dirtyBit = true;
		}

		public void AddHealing(float heal)
		{
			itemHealed += heal;
			dirtyBit = true;
		}

		public string[] GetTooltipArgs(in Totals totals)
		{
			bool flag = itemDamage != 0f;
			bool flag2 = itemHealed != 0f;
			if (flag && flag2)
			{
				return new string[2]
				{
					TrackerStatics.PortionToString(itemHealed, totals.healed - globalHealedWhenSet),
					TrackerStatics.PortionToString(itemDamage, totals.damageDealt - globalDamageWhenSet)
				};
			}
			if (flag)
			{
				return new string[2]
				{
					null,
					TrackerStatics.PortionToString(itemDamage, totals.damageDealt - globalDamageWhenSet)
				};
			}
			if (flag2)
			{
				return new string[2]
				{
					TrackerStatics.PortionToString(itemHealed, totals.healed - globalHealedWhenSet),
					null
				};
			}
			return null;
		}

		public static string GetToken(string[] args)
		{
			bool flag = args[0] != null;
			bool flag2 = args[1] != null;
			if (flag2 && flag)
			{
				return TrackedDef.portion_healTooltip;
			}
			if (flag2)
			{
				return TrackedDef.portionTooltip;
			}
			if (flag)
			{
				return TrackedDef.healTooltip;
			}
			log.error("Null args for SkillTracker");
			return TrackedDef.portion_healTooltip;
		}

		public void Reset(in Totals totals)
		{
			itemDamage = 0f;
			itemHealed = 0f;
			globalDamageWhenSet = totals.damageDealt;
			globalHealedWhenSet = totals.healed;
		}

		public virtual void Serialize(out uint[] ints, out float[] floats)
		{
			ints = null;
			floats = new float[2] { itemDamage, itemHealed };
		}

		public virtual void Deserialize(uint[] ints, float[] floats)
		{
			itemDamage = floats[0];
			itemHealed = floats[1];
		}

		string[] IItemTracker.GetTooltipArgs(in Totals totals)
		{
			return GetTooltipArgs(in totals);
		}

		void IItemTracker.Reset(in Totals totals)
		{
			Reset(in totals);
		}
	}
	public static class TrackerStatics
	{
		public static string IncreaseToString(float localNum, float totalNum)
		{
			if (totalNum == 0f)
			{
				return "NaN";
			}
			if (localNum >= 0.999999f * totalNum)
			{
				return "Max";
			}
			if (localNum < 0f)
			{
				return $"{100f * localNum / totalNum:f0}%";
			}
			return $"{100f / (1f - localNum / totalNum) - 100f:f0}%";
		}

		public static string ChanceToString(uint attempted, uint succedded)
		{
			if (attempted == 0)
			{
				return "NaN";
			}
			float num = 100f * (float)succedded / (float)attempted;
			return num.ToString((num < 10f) ? "f1" : "f0") + "%";
		}

		public static string ReductionToString(float localNum, float totalNum)
		{
			if (totalNum == 0f)
			{
				if (!(localNum > 0f))
				{
					return "NaN";
				}
				return "100%";
			}
			if (localNum <= -0.999999f * totalNum)
			{
				return "Min";
			}
			return $"{100f - 100f / (1f + localNum / totalNum):f0}%";
		}

		public static string PortionToString(float localNum, float totalNum)
		{
			if (totalNum == 0f)
			{
				return "NaN";
			}
			return $"{100f * localNum / totalNum:f0}%";
		}
	}
	public class WatchTracker : DamageTracker
	{
		private bool globalset;

		public void AddBrokenDamage(DamageTracker cleanWatchTracker)
		{
			AddItemDamage(cleanWatchTracker.itemDamage);
			if (!globalset)
			{
				globalDamageWhenSet = cleanWatchTracker.globalDamageWhenSet;
				globalset = true;
			}
		}

		public override void Reset(in Totals totals)
		{
			base.Reset(in totals);
			globalset = false;
		}

		public override void Serialize(out uint[] ints, out float[] floats)
		{
			ints = null;
			floats = new float[2] { itemDamage, globalDamageWhenSet };
		}

		public override void Deserialize(uint[] ints, float[] floats)
		{
			itemDamage = floats[0];
			globalDamageWhenSet = floats[1];
		}
	}
}
namespace ItemStatistics.Networking
{
	[Serializable]
	public struct DamageMessage
	{
		public Index inflictorIndex;

		public NetworkInstanceId victimId;

		public float damage;

		public bool crit;

		public GameObject attacker;

		public Vector3 position;

		public Vector3 force;

		public bool rejected;

		public uint procChainMask;

		public float procCoefficient;

		public ulong damageType;

		public DamageColorIndex damageColorIndex;

		public DotIndex dotIndex;

		public bool canRejectForce;

		public ProcChainMask GetProcChainMask()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			ProcChainMask result = default(ProcChainMask);
			result.mask = procChainMask;
			return result;
		}

		public static explicit operator DamageInfo(DamageMessage message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			return new DamageInfo
			{
				damage = message.damage,
				crit = message.crit,
				inflictor = ProcComponent.CreateInflictor(message.inflictorIndex, null),
				attacker = message.attacker,
				position = message.position,
				force = message.force,
				rejected = message.rejected,
				procChainMask = message.GetProcChainMask(),
				procCoefficient = message.procCoefficient,
				damageType = DamageTypeCombo.op_Implicit(message.damageType),
				damageColorIndex = message.damageColorIndex,
				dotIndex = message.dotIndex,
				canRejectForce = message.canRejectForce
			};
		}

		public DamageMessage(DamageInfo damageInfo, Index inflictorIndex, HealthComponent victim)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			this.inflictorIndex = inflictorIndex;
			if (Object.op_Implicit((Object)(object)victim))
			{
				victimId = ((NetworkBehaviour)victim).netId;
			}
			else
			{
				victimId = new NetworkInstanceId(0u);
			}
			damage = damageInfo.damage;
			crit = damageInfo.crit;
			attacker = damageInfo.attacker;
			position = damageInfo.position;
			force = damageInfo.force;
			rejected = damageInfo.rejected;
			procChainMask = damageInfo.procChainMask.mask;
			procCoefficient = damageInfo.procCoefficient;
			damageType = DamageTypeCombo.op_Implicit(damageInfo.damageType);
			damageColorIndex = damageInfo.damageColorIndex;
			dotIndex = damageInfo.dotIndex;
			canRejectForce = damageInfo.canRejectForce;
		}

		public DamageMessage(in BlastAttackDamageInfo blastAttack, Index inflictorIndex)
		{
			//IL_0029: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0050: Unknown result type (might be due to invalid IL or missing references)
			this.inflictorIndex = inflictorIndex;
			if (Object.op_Implicit((Object)(object)blastAttack.hitHealthComponent))
			{
				victimId = ((NetworkBehaviour)blastAttack.hitHealthComponent).netId;
			}
			else
			{
				victimId = new NetworkInstanceId(0u);
			}
			DamageTypeCombo val = blastAttack.damageType;
			if ((int)blastAttack.damageModifier == 2)
			{
				val |= DamageTypeCombo.op_Implicit((DamageType)16);
			}
			damage = blastAttack.damage;
			crit = blastAttack.crit;
			attacker = blastAttack.attacker;
			position = blastAttack.position;
			force = blastAttack.force;
			rejected = false;
			procChainMask = blastAttack.procChainMask.mask;
			procCoefficient = blastAttack.procCoefficient;
			damageType = DamageTypeCombo.op_Implicit(val);
			damageColorIndex = blastAttack.damageColorIndex;
			dotIndex = (DotIndex)(-1);
			canRejectForce = blastAttack.canRejectForce;
		}

		public DamageMessage(OverlapAttack overlapAttack, Index inflictorIndex)
		{
			//IL_000d: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			this.inflictorIndex = inflictorIndex;
			victimId = default(NetworkInstanceId);
			damage = overlapAttack.damage;
			crit = overlapAttack.isCrit;
			attacker = overlapAttack.attacker;
			position = default(Vector3);
			force = overlapAttack.forceVector;
			rejected = false;
			procChainMask = overlapAttack.procChainMask.mask;
			procCoefficient = overlapAttack.procCoefficient;
			damageType = DamageTypeCombo.op_Implicit(overlapAttack.damageType);
			damageColorIndex = overlapAttack.damageColorIndex;
			dotIndex = (DotIndex)(-1);
			canRejectForce = true;
		}
	}
	public static class NetworkHooks
	{
		private delegate void BlastAttack_ClientReportDamage(in BlastAttackDamageInfo blastAttack);

		public static Index inflictorIndex;

		public static bool shouldClientSendMessage
		{
			get
			{
				if (TrackModdedUsers.isModdedServer)
				{
					return inflictorIndex.type != IndexType.None;
				}
				return false;
			}
		}

		internal static void Hook()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			HookManager.Hook(typeof(BlastAttack), "ClientReportDamage", (Delegate)new <>A{00000018}<BlastAttack_ClientReportDamage, BlastAttackDamageInfo>(On_BlastAttack_ClientReportDamage_NetworkMessage));
			HookManager.Hook(typeof(BlastAttack), "HandleHits", new Manipulator(IL_BlastAttack_HandleHits_Inflictor));
			HookManager.Hook(typeof(BulletAttack), "DefaultHitCallbackImplementation", new Manipulator(IL_BulletAttack_DefaultHitCallbackImplementation_NetworkMessage));
			HookManager.Hook(typeof(OverlapAttack), "ProcessHits", new Manipulator(IL_OverlapAttack_ProcessHits_Inflictor));
			HookManager.Hook(typeof(BasicMeleeAttack), "AuthorityFixedUpdate", (Delegate)new Action<Action<BaseState>, BaseState>(On_BasicMeleeAttack_AuthorityFixedUpdate_ClearModded));
		}

		private static void On_BlastAttack_ClientReportDamage_NetworkMessage(BlastAttack_ClientReportDamage orig, in BlastAttackDamageInfo blastAttack)
		{
			if (!shouldClientSendMessage)
			{
				orig(in blastAttack);
			}
			else if (Object.op_Implicit((Object)(object)blastAttack.hitHealthComponent))
			{
				TrackModdedUsers.localUser.CallCmdBlastAttack(new DamageMessage(in blastAttack, inflictorIndex));
			}
		}

		private static void IL_BlastAttack_HandleHits_Inflictor(ILContext context)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ILCursor val = new ILCursor(context);
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchLdfld(a, typeof(BlastAttack), "inflictor")
			}))
			{
				val.EmitReplaceInflictor();
			}
			else
			{
				val.LogErrorCaller("failed find", "IL_BlastAttack_HandleHits_Inflictor");
			}
		}

		private static void IL_BulletAttack_DefaultHitCallbackImplementation_NetworkMessage(ILContext context)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(context);
			int shouldHitIndex = 9;
			ILLabel val2 = default(ILLabel);
			int num = default(int);
			if (!val.TryGotoNext(new Func<Instruction, bool>[4]
			{
				(Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(FriendlyFireManager), "ShouldDirectHitProceed"),
				(Instruction a) => ILPatternMatchingExt.MatchBr(a, ref val2),
				(Instruction a) => ILPatternMatchingExt.MatchLdcI4(a, ref num),
				(Instruction a) => ILPatternMatchingExt.MatchStloc(a, ref shouldHitIndex)
			}))
			{
				log.error($"Failed to find shouldHitIndex\n{val}");
			}
			int damageInfoIndex = 6;
			if (!val.TryGotoNext(new Func<Instruction, bool>[2]
			{
				(Instruction a) => ILPatternMatchingExt.MatchLdloc(a, ref damageInfoIndex),
				(Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(HealthComponent), "TakeDamage")
			}))
			{
				log.error($"Failed to find damageInfoIndex\n{val}");
			}
			else
			{
				int index = val.Index;
				val.Index = index + 1;
				val.Emit(OpCodes.Dup);
				val.EmitDelegate<Action<DamageInfo>>((Action<DamageInfo>)delegate(DamageInfo damageInfo)
				{
					if (inflictorIndex.type != 0)
					{
						damageInfo.inflictor = ProcComponent.CreateInflictor(inflictorIndex, null);
					}
				});
			}
			ILLabel branchSkip = null;
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
			{
				(Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(ClientScene), "get_ready"),
				(Instruction a) => ILPatternMatchingExt.MatchBrfalse(a, ref branchSkip)
			}))
			{
				Instruction next = val.Next;
				val.Emit(OpCodes.Call, (MethodBase)typeof(NetworkHooks).GetMethod("get_shouldClientSendMessage"));
				val.Emit(OpCodes.Brfalse, next);
				val.Emit(OpCodes.Ldarg, 1);
				val.Emit(OpCodes.Ldloc, damageInfoIndex);
				val.