Decompiled source of ItemStatistics v1.1.15

patchers/ItemStatisticsPatcher.dll

Decompiled 2 weeks 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;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("1.1.15.0")]
public static class ItemStatisticsPatcher
{
	private static ManualLogSource _log;

	private static ManualLogSource log
	{
		get
		{
			if (_log == null)
			{
				_log = Logger.CreateLogSource("ItemStatisticsPatcher");
			}
			return _log;
		}
	}

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

	public static void Patch(AssemblyDefinition assembly)
	{
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Expected O, but got Unknown
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: 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 fieldType = mainModule.ImportReference((TypeReference)(object)val.MainModule.GetType("ItemStatistics.Components.TrackedInventory"));
		TypeReference val2 = mainModule.ImportReference((TypeReference)(object)val.MainModule.GetType("ItemStatistics.ProcChain"));
		GenericInstanceType val3 = new GenericInstanceType(mainModule.ImportReference(typeof(List<>)));
		val3.GenericArguments.Add(val2);
		TypeReference fieldType2 = mainModule.ImportReference((TypeReference)(object)val.MainModule.GetType("ItemStatistics.Index"));
		ModuleDefinition mainModule2 = AssemblyDefinition.ReadAssembly(Path.Combine(Paths.ManagedPath, "UnityEngine.CoreModule.dll")).MainModule;
		TypeReference fieldType3 = mainModule.ImportReference((TypeReference)(object)mainModule2.GetType("UnityEngine.GameObject"));
		TypeReference val4 = mainModule.ImportReference((TypeReference)(object)mainModule2.GetType("UnityEngine.SerializeField"));
		AddField(mainModule.GetType("RoR2.CharacterMaster"), fieldType, "trackedInventory");
		AddField(mainModule.GetType("RoR2.DotController/DotStack"), val2, "dotStackChain");
		AddField(mainModule.GetType("RoR2.DotController/PendingDamage"), (TypeReference)(object)val3, "pendingDotChainList");
		AddField(mainModule.GetType("RoR2.Orbs.GenericDamageOrb"), fieldType3, "inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.DevilOrb"), fieldType3, "inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.BounceOrb"), fieldType3, "inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.LunarDetonatorOrb"), fieldType3, "inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.HealOrb"), fieldType2, "inflictor");
		AddField(mainModule.GetType("EntityStates.FrozenState"), fieldType2, "freezeInflictor");
		AddField(mainModule.GetType("EntityStates.FrozenState"), (TypeReference)(object)mainModule.GetType("RoR2.CharacterMaster"), "freezeInflictorMaster");
		FieldDefinition obj = AddField(mainModule.GetType("EntityStates.BasicMeleeAttack"), fieldType2, "meleeInflictorIndex");
		CustomAttribute val5 = new CustomAttribute(mainModule.ImportReference((MethodReference)(object)((IEnumerable<MethodDefinition>)val4.Resolve().Methods).First((MethodDefinition a) => a.IsConstructor && !a.IsStatic)));
		obj.CustomAttributes.Add(val5);
	}

	private static FieldDefinition AddField(TypeDefinition target, TypeReference fieldType, string fieldName)
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		if (target == null || fieldType == null)
		{
			log.LogError((object)("Null types in AddField: " + fieldName));
			return null;
		}
		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 null;
		}
		FieldDefinition val = new FieldDefinition(fieldName, (FieldAttributes)6, fieldType);
		target.Fields.Add(val);
		return val;
	}
}

plugins/ItemStatistics.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
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 System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dolso;
using Dolso.RiskofOptions;
using EntityStates;
using EntityStates.CaptainDefenseMatrixItem;
using EntityStates.Chef;
using EntityStates.Croco;
using EntityStates.FalseSon;
using EntityStates.GlobalSkills.LunarDetonator;
using EntityStates.GummyClone;
using EntityStates.Headstompers;
using EntityStates.Loader;
using EntityStates.Mage;
using EntityStates.Mage.Weapon;
using EntityStates.Railgunner.Weapon;
using EntityStates.Seeker;
using EntityStates.Toolbot;
using HG;
using HG.GeneralSerializer;
using HG.Reflection;
using ItemStatistics;
using ItemStatistics.Components;
using ItemStatistics.Hooks;
using ItemStatistics.Networking;
using ItemStatistics.Trackers;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
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+da3480dcae20f922586d0a62c3e4331984fc2069")]
[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 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)
		{
			logger.LogError((object)string.Format($"ILCursor failure in {new StackFrame(1).GetMethod().Name}, skipping: {data}\n{c}"));
		}
	}
	internal static class HookManager
	{
		internal delegate bool ConfigEnabled<T>(ConfigEntry<T> configEntry);

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

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

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

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

		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(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(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 Hook: {methodFrom.DeclaringType}::{methodFrom.Name} - {onHook.Name}\n{ex}");
			}
		}

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

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

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

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

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

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

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

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

		private static void HookConfigInternal<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase methodFrom, Delegate hook)
		{
			try
			{
				IDetour detour = ManualDetour(methodFrom, hook);
				configEntry.SettingChanged += delegate(object sender, EventArgs _)
				{
					UpdateHook(detour, enabled(sender as ConfigEntry<T>));
				};
				if (enabled(configEntry))
				{
					detour.Apply();
				}
			}
			catch (Exception ex)
			{
				log.error($"Failed to do config hook {methodFrom.DeclaringType}::{methodFrom.Name} - {hook.Method.Name}\n{ex}");
			}
		}

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

		internal static IDetour ManualDetour(Type typeFrom, string methodFrom, Delegate hook)
		{
			return ManualDetour(GetMethod(typeFrom, methodFrom), hook);
		}

		internal static IDetour ManualDetour(MethodBase methodFrom, Delegate hook)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			if (methodFrom == null)
			{
				log.error("null methodFrom for detour: " + hook.Method.Name);
			}
			else
			{
				try
				{
					Manipulator val = (Manipulator)(object)((hook is Manipulator) ? hook : null);
					if (val != null)
					{
						return (IDetour)new ILHook(methodFrom, val, ref ilHookConfig);
					}
					return (IDetour)new Hook(methodFrom, hook, ref onHookConfig);
				}
				catch (Exception ex)
				{
					log.error($"Failed to create detour {methodFrom.DeclaringType}::{methodFrom} - {hook.Method.Name}\n{ex}");
				}
			}
			return null;
		}

		internal static MethodInfo GetMethod(Type typeFrom, string methodName)
		{
			if (typeFrom == null || methodName == null)
			{
				log.error($"Null argument in GetMethod: type={typeFrom}, name={methodName}");
				return null;
			}
			MethodInfo[] array = (from predicate in typeFrom.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where predicate.Name == methodName
				select predicate).ToArray();
			switch (array.Length)
			{
			case 1:
				return array[0];
			case 0:
				log.error($"Failed to find method: {typeFrom}::{methodName}");
				return null;
			default:
			{
				log.error($"{array.Length} ambiguous matches found for: {typeFrom}::{methodName}");
				MethodInfo[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					log.error(array2[i]);
				}
				return null;
			}
			}
		}

		internal static MethodInfo GetMethod(Type typeFrom, string methodName, params Type[] parameters)
		{
			if (typeFrom == null || methodName == null)
			{
				log.error($"Null argument in GetMethod: type={typeFrom}, name={methodName}");
				return null;
			}
			MethodInfo? method = typeFrom.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameters, null);
			if (method == null)
			{
				log.error($"Failed to find method: {typeFrom}::{methodName}_{parameters.Length}");
			}
			return method;
		}

		internal static void SetPriority(string[] before = null, string[] after = null)
		{
			ilHookConfig.Before = before;
			onHookConfig.Before = before;
			ilHookConfig.After = after;
			onHookConfig.After = after;
		}

		internal static void CreateWrapper(MethodInfo targetMethod, Action prefix, Action suffix)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (targetMethod == null || targetMethod.IsGenericMethodDefinition || targetMethod.GetMethodBody()?.GetILAsByteArray() == null)
				{
					log.error("invalid target method " + targetMethod);
					return;
				}
				Type[] onHookParameters;
				Type type = CreateDelegateType(targetMethod, out onHookParameters);
				DynamicMethodDefinition val = new DynamicMethodDefinition("wrapper_" + targetMethod.DeclaringType.Name + "_" + targetMethod.Name, targetMethod.ReturnType ?? typeof(void), onHookParameters);
				ILProcessor iLProcessor = val.GetILProcessor();
				if (prefix != null)
				{
					if (prefix.Target != null)
					{
						DynamicMethodHelper.EmitReference<object>(iLProcessor, prefix.Target);
					}
					Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)prefix.Method);
				}
				for (int i = 0; i < onHookParameters.Length; i++)
				{
					iLProcessor.Emit(OpCodes.Ldarg, i);
				}
				Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)type.GetMethod("Invoke"));
				if (suffix != null)
				{
					if (suffix.Target != null)
					{
						DynamicMethodHelper.EmitReference<object>(iLProcessor, suffix.Target);
					}
					Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)suffix.Method);
				}
				iLProcessor.Emit(OpCodes.Ret);
				MethodInfo methodInfo = DetourHelper.Pin<MethodInfo>(val.Generate());
				new Hook((MethodBase)targetMethod, methodInfo, (object)null, ref onHookConfig).Apply();
			}
			catch (Exception arg)
			{
				log.error($"Failed to create wrapper for {targetMethod}\n{arg}");
			}
		}

		private static Type CreateDelegateType(MethodInfo method, out Type[] onHookParameters)
		{
			ModuleBuilder moduleBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName($"DDTASM<{method.DeclaringType}{method.Name}>?{method.MethodHandle.Value}".Replace(".", "_")), AssemblyBuilderAccess.Run).DefineDynamicModule("DynamicDelegateModule");
			ParameterInfo[] parameters = method.GetParameters();
			Type[] array;
			if (!method.IsStatic)
			{
				array = new Type[parameters.Length + 1];
				array[0] = Extensions.GetThisParamType((MethodBase)method);
				for (int i = 0; i < parameters.Length; i++)
				{
					array[i + 1] = parameters[i].ParameterType;
				}
			}
			else
			{
				array = new Type[parameters.Length];
				for (int j = 0; j < parameters.Length; j++)
				{
					array[j] = parameters[j].ParameterType;
				}
			}
			TypeBuilder typeBuilder = moduleBuilder.DefineType($"<{method.DeclaringType.Name}{method.Name}>?{method.MethodHandle.Value}".Replace(".", "_"), TypeAttributes.Public | TypeAttributes.Sealed, typeof(MulticastDelegate));
			typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[2]
			{
				typeof(object),
				typeof(IntPtr)
			}).SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
			typeBuilder.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, method.ReturnType ?? typeof(void), array).SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
			Type type = typeBuilder.CreateType();
			onHookParameters = new Type[array.Length + 1];
			onHookParameters[0] = type;
			for (int k = 0; k < array.Length; k++)
			{
				onHookParameters[k + 1] = array[k];
			}
			return type;
		}
	}
	internal static class Utilities
	{
		private static GameObject _prefabParent;

		internal static GameObject CreatePrefab(GameObject gameObject, string name = null)
		{
			//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 val = Object.Instantiate<GameObject>(gameObject, _prefabParent.transform);
			if (name != null)
			{
				((Object)val).name = name;
			}
			return val;
		}

		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 Task<Obj> GetAddressableAsync<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).Task;
		}

		internal static Task<GameObject> GetAddressableAsync(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).Task;
		}

		internal static void DoAddressable<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 DoAddressable(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 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 void ModifyStateConfig(string stateConfigAddress, string fieldName, object newValue)
		{
			Utilities.DoAddressable<EntityStateConfiguration>(stateConfigAddress, (Action<EntityStateConfiguration>)delegate(EntityStateConfiguration a)
			{
				a.ModifyStateConfig(fieldName, newValue);
			});
		}

		internal static void ModifyStateConfig(this EntityStateConfiguration stateConfig, string fieldName, object newValue)
		{
			SerializedField[] serializedFields = stateConfig.serializedFieldsCollection.serializedFields;
			for (int i = 0; i < serializedFields.Length; i++)
			{
				if (serializedFields[i].fieldName == fieldName)
				{
					Object val = (Object)((newValue is Object) ? newValue : null);
					if (val != null)
					{
						serializedFields[i].fieldValue.objectValue = val;
					}
					else if (newValue is string stringValue)
					{
						serializedFields[i].fieldValue.stringValue = stringValue;
					}
					else
					{
						log.error("Invalid value for SerializedField: " + 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;
		}
	}
}
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 AddOption(ConfigEntry<bool> entry)
		{
			AddOption(entry, "", "");
		}

		internal static void AddOption(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 AddOption<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 AddOption(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 AddOption(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 AddOption(ConfigEntry<float> entry, float min, float max, string format = "{0:f2}")
		{
			AddFloatSlider(entry, min, max, format);
		}

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

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

		internal static void AddString(ConfigEntry<string> entry, bool restartRequired = false, 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_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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(entry, new InputFieldConfig
			{
				submitOn = (SubmitEnum)6,
				lineType = (LineType)0,
				category = categoryName,
				description = ((ConfigEntryBase)(object)entry).DescWithDefault(),
				restartRequired = restartRequired
			}));
		}

		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_001b: Expected O, but got Unknown
			//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
			FloatFieldConfig val = new FloatFieldConfig();
			((NumericFieldConfig<float>)val).Min = min;
			((NumericFieldConfig<float>)val).Max = max;
			((NumericFieldConfig<float>)val).FormatString = format;
			((BaseOptionConfig)val).description = ((ConfigEntryBase)(object)entry).DescWithDefault(format);
			ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(entry, val));
		}

		internal static void AddFloatSlider(ConfigEntry<float> entry, float min, float max, string format = "{0:f2}", 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_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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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 AddIntField(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, 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_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()
			}));
		}

		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 : IEquatable<Index>
	{
		[SerializeField]
		private int _value;

		public readonly IndexType type => (IndexType)(_value >> 16);

		public readonly int index => (short)_value;

		public readonly bool isNotNone => _value != 0;

		public Index(ItemIndex index)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected I4, but got Unknown
			_value = (index & 0xFFFF) + 65536;
		}

		public Index(EquipmentIndex index)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected I4, but got Unknown
			_value = (index & 0xFFFF) + 131072;
		}

		public Index(SkillSlot index)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected I4, but got Unknown
			_value = (index & 0xFFFF) + 196608;
		}

		public Index(BodyIndexType index)
		{
			_value = (int)((index & (BodyIndexType)65535) + 262144);
		}

		public Index(short type, short index)
		{
			_value = (type << 16) + (index & 0xFFFF);
		}

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

		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 index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return new Index(index);
		}

		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 index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return new Index(index);
		}

		public static implicit operator Index(BodyIndexType index)
		{
			return new Index(index);
		}

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

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

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

		public static explicit operator BodyIndexType(Index index)
		{
			if (index.type != IndexType.Body)
			{
				throw new InvalidCastException("Index type is not Body");
			}
			return (BodyIndexType)index.index;
		}

		public static bool operator ==(Index a, Index b)
		{
			return a._value == b._value;
		}

		public static bool operator !=(Index a, Index b)
		{
			return a._value != b._value;
		}

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

		public bool Equals(Index index)
		{
			return _value == index._value;
		}

		public override int GetHashCode()
		{
			return _value;
		}

		public override string ToString()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			switch (type)
			{
			case IndexType.None:
				return "None" + ((index == 0) ? "" : (", " + index));
			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 "Skill, " + ((object)(SkillSlot)(ref val)).ToString();
			}
			case IndexType.Body:
				return "Body, " + (BodyIndexType)index;
			default:
				return $"Unknown Index {type}, {index}";
			}
		}

		internal static void Serialize(NetworkWriter writer, Index value)
		{
			writer.WritePackedUInt32((uint)value._value);
		}

		internal static Index Deserialize(NetworkReader reader)
		{
			Index result = default(Index);
			result._value = (int)reader.ReadPackedUInt32();
			return result;
		}

		private static string SerializeToString(object obj)
		{
			Index index = (Index)obj;
			return $"{((int)index.type).ToString()} {index.index.ToString(CultureInfo.InvariantCulture)}";
		}

		private static object DeserializeFromString(string str)
		{
			string[] array = StringSerializer.SplitToComponents(str, typeof(Index), 2);
			return new Index(short.Parse(array[0], CultureInfo.InvariantCulture), short.Parse(array[1], CultureInfo.InvariantCulture));
		}

		static Index()
		{
			//IL_0011: 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_002a: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			StringSerializer.serializationHandlers[typeof(Index)] = new SerializationHandler
			{
				serializer = new SerializerDelegate(SerializeToString),
				deserializer = new DeserializerDelegate(DeserializeFromString)
			};
		}
	}
	public enum IndexType
	{
		None,
		Item,
		Equip,
		SkillSlot,
		Body
	}
	public enum BodyIndexType
	{
		Ignore,
		Regen,
		Barrier,
		MinionDamage
	}
	public static class ItemStatisticsAPI
	{
		public static void AddTrackerToPrefab(GameObject prefab, Index indexToCredit)
		{
			prefab.AddComponent<ProcComponent>().index = indexToCredit;
		}

		public static void AddMinionTrackerToPrefab(GameObject prefab, Index indexToCredit)
		{
			prefab.AddComponent<MinionComponent>().index = indexToCredit;
		}

		public static void AddTrackedIndex(Index indexToAdd, TrackedDef trackerType)
		{
			if (trackerType != null)
			{
				ItemStatisticsPlugin.indexToDef.Add(indexToAdd, trackerType);
				return;
			}
			Index index = indexToAdd;
			log.error(index.ToString() + " has a null tracker type");
		}

		public static void WrapAttackWithIndex(MethodInfo yourAttackMethod, Index indexToCredit)
		{
			HookManager.CreateWrapper(yourAttackMethod, delegate
			{
				NetworkHooks.inflictorIndex = indexToCredit;
			}, AttackSuffix);
		}

		public static TrackedInventory GetTrackedInventory(CharacterMaster master, bool includeFromMinion)
		{
			return TrackedInventory.GetTrackedInventory(master, includeFromMinion);
		}

		public static bool TryGetTrackedInventory(CharacterMaster master, bool includeFromMinion, out TrackedInventory trackedInventory)
		{
			return TrackedInventory.TryGetTrackedInventory(master, includeFromMinion, out trackedInventory);
		}

		public static GameObject CreateNewInflictor(Index index, GameObject parentInflictor = null)
		{
			return ProcComponent.CreateInflictor(index, parentInflictor);
		}

		public static void AddChainToNextProjectileFromInflictor(GameObject parentInflictor)
		{
			ILExtensions.parentInflictorParameter = parentInflictor;
		}

		public static void TrackNextDot(GameObject parentInflictor)
		{
			DotTracking.dotChainParameter = ProcComponent.GetChainFromInflictor(parentInflictor);
		}

		public static void TrackNextDot(Index dotApplier, GameObject parentInflictor)
		{
			DotTracking.dotChainParameter = new ProcChain(dotApplier, ProcComponent.GetChainFromInflictor(parentInflictor));
		}

		public static void CreditNextHeal(Index indexToCredit)
		{
			HCHeal.healIndex = indexToCredit;
		}

		public static void CreditDamage(TrackedInventory trackedInventory, Index index, float damage)
		{
			trackedInventory.AddDamage(index, damage);
		}

		public static void CreditGold(TrackedInventory trackedInventory, Index index, float gold)
		{
			trackedInventory.AddGold(index, gold);
		}

		public static void CreditProcAttempt(TrackedInventory trackedInventory, Index index)
		{
			trackedInventory.ProcAttempt(index);
		}

		public static void CreditProcSuccess(TrackedInventory trackedInventory, Index index)
		{
			trackedInventory.ProcSuccess(index);
		}

		private static void AttackSuffix()
		{
			NetworkHooks.inflictorIndex = default(Index);
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("dolso.ItemStatistics", "ItemStatistics", "1.1.15")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ItemStatisticsPlugin : BaseUnityPlugin
	{
		public const string Version = "1.1.15";

		public const string ModGuid = "dolso.ItemStatistics";

		internal static readonly Dictionary<Index, TrackedDef> indexToDef = new Dictionary<Index, TrackedDef>();

		internal static GameObject missileLauncher;

		internal static GameObject overloadingHeadhunter;

		internal static GameObject fireTrailHeadhunter;

		internal static int crocoDiseaseProjectileIndex;

		internal static BodyIndex falseSonCharacterBodyIndex;

		private void Awake()
		{
			log.start(((BaseUnityPlugin)this).Logger);
			Config.DoConfig(((BaseUnityPlugin)this).Config);
			try
			{
				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.DoAddressable("RoR2/Base/Core/PlayerMaster.prefab", delegate(GameObject a)
				{
					a.GetComponent<CharacterMaster>().trackedInventory = a.AddComponent<TrackedInventory>();
				});
				Utilities.DoAddressable("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.DoAddressable("RoR2/Base/UI/ScoreboardStrip.prefab", delegate(GameObject scoreboardStrip)
				{
					((Component)scoreboardStrip.GetComponentInChildren<EquipmentIcon>()).gameObject.AddComponent<IconBehaviour>().type = IndexType.Equip;
					PlayerTooltip.CreateTooltipPrefab(scoreboardStrip);
				});
				ToolbotStance.DoSetup();
			}
			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();
			Language.collectLanguageRootFolders += CollectLanguageRootFolders;
			log.info($"Hooks completed in {stopwatch.Elapsed.TotalSeconds:f2}s");
		}

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

		private static void ModifyPrefabs()
		{
			//IL_078c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0791: Unknown result type (might be due to invalid IL or missing references)
			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);
			AddProcComponent("RoR2/Base/Dagger/DaggerProjectile.prefab", Items.Dagger);
			AddProcComponent("RoR2/Base/BleedOnHitAndExplode/BleedOnHitAndExplodeDelay.prefab", 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.DoAddressable("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.DoAddressable<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);
			Utilities.DoAddressable("RoR2/Base/Common/MissileProjectile.prefab", DoMissilePrefab);
			Utilities.DoAddressable("RoR2/Base/EliteLightning/LightningStake.prefab", DoOverloadingPrefab);
			Utilities.DoAddressable("RoR2/Base/Common/FireTrail.prefab", DoBlazingTrailPrefab);
			AddMeleeConfigIndexies(Addressables.LoadAssetsAsync<EntityStateConfiguration>((IEnumerable)new string[11]
			{
				"RoR2/Base/Bandit2/EntityStates.Bandit2.Weapon.SlashBlade.asset", "RoR2/Base/Croco/EntityStates.Croco.Bite.asset", "RoR2/Base/Croco/EntityStates.Croco.Slash.asset", "RoR2/DLC2/FalseSon/EntityStates.FalseSon.ClubSwing.asset", "RoR2/DLC2/FalseSon/EntityStates.FalseSon.ClubSwing2.asset", "RoR2/DLC2/FalseSon/EntityStates.FalseSon.OverheadClubSwing.asset", "RoR2/Base/Loader/EntityStates.Loader.SwingChargedFist.asset", "RoR2/Base/Loader/EntityStates.Loader.SwingComboFist.asset", "RoR2/Base/Loader/EntityStates.Loader.SwingZapFist.asset", "RoR2/Base/Merc/EntityStates.Merc.Assaulter2.asset",
				"RoR2/Base/Merc/EntityStates.Merc.Weapon.GroundLight2.asset"
			}, (Action<EntityStateConfiguration>)null, (MergeMode)1, false).WaitForCompletion());
		}

		private static void AddMeleeConfigIndexies(IList<EntityStateConfiguration> list)
		{
			FieldInfo field = typeof(BasicMeleeAttack).GetField("meleeInflictorIndex");
			foreach (EntityStateConfiguration item in list)
			{
				Index index = ((Object)item).name switch
				{
					"EntityStates.Bandit2.Weapon.SlashBlade" => (SkillSlot)1, 
					"EntityStates.Croco.Bite" => (SkillSlot)1, 
					"EntityStates.Croco.Slash" => (SkillSlot)0, 
					"EntityStates.FalseSon.ClubSwing" => (SkillSlot)0, 
					"EntityStates.FalseSon.ClubSwing2" => (SkillSlot)0, 
					"EntityStates.FalseSon.OverheadClubSwing" => (SkillSlot)0, 
					"EntityStates.Loader.SwingChargedFist" => (SkillSlot)2, 
					"EntityStates.Loader.SwingComboFist" => (SkillSlot)0, 
					"EntityStates.Loader.SwingZapFist" => (SkillSlot)2, 
					"EntityStates.Merc.Assaulter2" => (SkillSlot)2, 
					"EntityStates.Merc.Weapon.GroundLight2" => (SkillSlot)0, 
					_ => default(Index), 
				};
				if (index.isNotNone)
				{
					((SerializedValue)(ref ((SerializedFieldCollection)(ref item.serializedFieldsCollection)).GetOrCreateField("meleeInflictorIndex").fieldValue)).SetValue(field, (object)index);
				}
				else
				{
					log.error("Failed to add melee index to " + ((Object)item).name);
				}
			}
		}

		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;
			};
		}

		private static void DoMissilePrefab(GameObject missilePrefab)
		{
			missileLauncher = Utilities.CreatePrefab(missilePrefab, "DisposableMissileProjectile");
			missileLauncher.AddComponent<ProcComponent>().index = Equipment.CommandMissile;
			CommonAssets.missilePrefab = Utilities.CreatePrefab(missilePrefab, "ATGMissileProjectile");
			CommonAssets.missilePrefab.AddComponent<ProcComponent>().index = Items.Missile;
		}

		private static void DoOverloadingPrefab(GameObject orbPrefab)
		{
			overloadingHeadhunter = Utilities.CreatePrefab(orbPrefab);
			overloadingHeadhunter.AddComponent<ProcComponent>().index = Items.HeadHunter;
			orbPrefab.AddComponent<ProcComponent>().index = Equipment.AffixBlue;
		}

		private static void DoBlazingTrailPrefab(GameObject trailPrefab)
		{
			fireTrailHeadhunter = Utilities.CreatePrefab(trailPrefab);
			fireTrailHeadhunter.AddComponent<ProcComponent>().index = Items.HeadHunter;
			trailPrefab.AddComponent<ProcComponent>().index = Equipment.AffixRed;
		}

		private void CollectLanguageRootFolders(List<string> list)
		{
			list.Add(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Language"));
		}
	}
	public class ProcChain
	{
		public Index value;

		public ProcChain parent;

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

		public override string ToString()
		{
			string text = value.ToString();
			for (ProcChain procChain = parent; procChain != null; procChain = procChain.parent)
			{
				string text2 = text;
				Index index = procChain.value;
				text = text2 + " -> " + index.ToString();
			}
			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 class 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 portionTooltip = "ITEMSTATISTICS_TOOLTIPS_DAMAGEPORTION";

		public static readonly string recycledTooltip = "ITEMSTATISTICS_TOOLTIPS_RECYCLED";

		public static readonly string barrierGainedTooltip = "ITEMSTATISTICS_TOOLTIPS_BARRIERGAINED";

		public static readonly string globalPortionTooltip = "ITEMSTATISTICS_TOOLTIPS_GLOBALPORTION";

		public static readonly string minionPortionTooltip = "ITEMSTATISTICS_TOOLTIPS_MINIONPORTION";

		public static readonly string regenPortionTooltip = "ITEMSTATISTICS_TOOLTIPS_REGENPORTION";

		public static readonly string barrierBlockedTooltip = "ITEMSTATISTICS_TOOLTIPS_BARRIERBLOCKED";

		public static readonly string chance_barrierTooltip = "ITEMSTATISTICS_TOOLTIPS_CHANCE_BARRIER";

		public static readonly string chance_healedTooltip = "ITEMSTATISTICS_TOOLTIPS_CHANCE_HEALED";

		public static readonly string chance_damageTooltip = "ITEMSTATISTICS_TOOLTIPS_CHANCE_DAMAGE";

		public static readonly string hit_damageTooltip = "ITEMSTATISTICS_TOOLTIPS_HIT_DAMAGE";

		public static readonly string count_chanceTooltip = "ITEMSTATISTICS_TOOLTIPS_COUNT_CHANCE";

		public static readonly string reduction_countTooltip = "ITEMSTATISTICS_TOOLTIPS_REDUCTION_COUNT";

		public static readonly TrackedDef ArmorCount = new TrackedDef(typeof(ArmorCountTracker), reduction_countTooltip);

		public static readonly TrackedDef Armor = new TrackedDef(typeof(ArmorTracker), reductionTooltip);

		public static readonly TrackedDef Chance = new TrackedDef(typeof(ChanceTracker), count_chanceTooltip);

		public static readonly TrackedDef Count = new TrackedDef(typeof(CountTracker), countTooltip);

		public static readonly TrackedDef DamageChance = new TrackedDef(typeof(DamageChanceTracker), chance_damageTooltip);

		public static readonly TrackedDef DamagePortion = new TrackedDef(typeof(DamageTracker), portionTooltip);

		public static readonly TrackedDef Damage = new TrackedDef(typeof(DamageTracker), damageTooltip);

		public static readonly TrackedDef Gold = new TrackedDef(typeof(GoldTracker), goldTooltip);

		public static readonly TrackedDef Heal = new TrackedDef(typeof(HealTracker), healTooltip);

		public static readonly TrackedDef Watch = new TrackedDef(typeof(WatchTracker), damageTooltip);

		public static readonly TrackedDef Skill = new TrackedDef(typeof(SkillTracker), null);

		private readonly Type trackerType;

		private readonly string tooltipToken;

		public TrackedDef(Type trackerType, string tooltipToken)
		{
			if (typeof(ITracker).IsAssignableFrom(trackerType))
			{
				this.trackerType = trackerType;
				this.tooltipToken = tooltipToken;
			}
			else
			{
				log.error(trackerType?.ToString() + " is not a valid tracker type");
			}
		}

		public string GetTooltip(ITracker tracker, in Totals totals)
		{
			string[] tooltipArgs = tracker.GetTooltipArgs(in totals);
			if (tooltipArgs == null)
			{
				return "";
			}
			if (tooltipToken == null)
			{
				return string.Concat(tooltipArgs);
			}
			string text = tooltipToken;
			object[] array = tooltipArgs;
			return Language.GetStringFormatted(text, array);
		}

		internal ITracker CreateTracker()
		{
			return (ITracker)Activator.CreateInstance(trackerType);
		}
	}
}
namespace ItemStatistics.Trackers
{
	public class ArmorCountTracker : ITracker, 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;
		}

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

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

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(attempted);
			data.Add(succedded);
			data.Add(damageBlocked);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			attempted = data.nextInt;
			succedded = data.nextInt;
			damageBlocked = data.nextFloat;
		}
	}
	public class ArmorTracker : ITracker, 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;
		}

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

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

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(damageBlocked);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			damageBlocked = data.nextFloat;
		}
	}
	public class ChanceTracker : ITracker, 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;
		}

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

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

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(attempted);
			data.Add(succedded);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			attempted = data.nextInt;
			succedded = data.nextInt;
		}
	}
	public class CountTracker : ITracker, IChanceTracker
	{
		private uint succedded;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

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

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

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

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

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(succedded);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			succedded = data.nextInt;
		}
	}
	public class DamageChanceTracker : ITracker, IChanceTracker, IDamageTracker
	{
		private uint attempted;

		private uint succedded;

		private float globalDamageWhenSet;

		private float itemDamage;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

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

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

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

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

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

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(attempted);
			data.Add(succedded);
			data.Add(itemDamage);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			attempted = data.nextInt;
			succedded = data.nextInt;
			itemDamage = data.nextFloat;
		}
	}
	public class DamageTracker : ITracker, IDamageTracker
	{
		internal float globalDamageWhenSet;

		internal float itemDamage;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

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

		string[] ITracker.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(SerializationBuffer data)
		{
			data.Add(itemDamage);
		}

		public virtual void Deserialize(SerializationBuffer data)
		{
			itemDamage = data.nextFloat;
		}
	}
	public class GoldTracker : ITracker
	{
		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;
		}

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

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

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(itemEarned);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			itemEarned = data.nextFloat;
		}
	}
	public class HealChanceTracker : ITracker, IChanceTracker, IHealTracker
	{
		private uint attempted;

		private uint succedded;

		private float itemHealed;

		private float globalHealedWhenSet;

		public int itemCount { get; set; }

		public bool dirtyBit { get; set; }

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

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

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

		string[] ITracker.GetTooltipArgs(in Totals totals)
		{
			return new string[3]
			{
				TrackerStatics.ChanceToString(attempted, succedded),
				TrackerStatics.PortionToString(itemHealed, totals.healed - globalHealedWhenSet),
				itemHealed.ToString("0")
			};
		}

		void ITracker.Reset(in Totals totals)
		{
			attempted = 0u;
			succedded = 0u;
			itemHealed = 0f;
			globalHealedWhenSet = totals.healed;
		}

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(attempted);
			data.Add(succedded);
			data.Add(itemHealed);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			attempted = data.nextInt;
			succedded = data.nextInt;
			itemHealed = data.nextFloat;
		}
	}
	public class HealTracker : ITracker, 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;
		}

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

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

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(itemHealed);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			itemHealed = data.nextFloat;
		}
	}
	public interface IChanceTracker
	{
		void Attempted();

		void Succedded();
	}
	public interface IDamageTracker
	{
		void AddDamage(float damage);
	}
	public interface IHealTracker
	{
		void AddHealing(float heal);
	}
	public interface IReductionTracker
	{
		void AddBlockedDamage(float blocked);
	}
	public interface ITracker
	{
		int itemCount { get; set; }

		bool dirtyBit { get; set; }

		string[] GetTooltipArgs(in Totals totals);

		void Reset(in Totals totals);

		void Serialize(SerializationBuffer data);

		void Deserialize(SerializationBuffer data);
	}
	public class SkillTracker : ITracker, 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 AddDamage(float damage)
		{
			itemDamage += damage;
			dirtyBit = true;
		}

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

		string[] ITracker.GetTooltipArgs(in Totals totals)
		{
			bool flag = itemDamage != 0f;
			bool flag2 = itemHealed != 0f;
			string text = null;
			if (flag)
			{
				text = Language.GetStringFormatted(TrackedDef.portionTooltip, new object[2]
				{
					null,
					TrackerStatics.PortionToString(itemDamage, totals.damageDealt - globalDamageWhenSet)
				});
			}
			if (flag2)
			{
				if (flag)
				{
					text += "\n";
				}
				text += Language.GetStringFormatted(TrackedDef.healTooltip, new object[2]
				{
					TrackerStatics.PortionToString(itemHealed, totals.healed - globalHealedWhenSet),
					null
				});
			}
			if (text != null)
			{
				return new string[1] { text };
			}
			return null;
		}

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

		void ITracker.Serialize(SerializationBuffer data)
		{
			data.Add(itemDamage);
			data.Add(itemHealed);
		}

		void ITracker.Deserialize(SerializationBuffer data)
		{
			itemDamage = data.nextFloat;
			itemHealed = data.nextFloat;
		}
	}
	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).ToString("f0") + "%";
			}
			return (100f / (1f - localNum / totalNum) - 100f).ToString("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)).ToString("f0") + "%";
		}

		public static string PortionToString(float localNum, float totalNum)
		{
			if (totalNum == 0f)
			{
				return "NaN";
			}
			return (100f * localNum / totalNum).ToString("f0") + "%";
		}

		internal static void LogInvalid(Index index, ITracker tracker, string requiredTracker, [CallerMemberName] string caller = "")
		{
			log.error($"Invalid call '{caller}' on {index} ({tracker}). Has to be a {requiredTracker} tracker");
		}
	}
	public class WatchTracker : DamageTracker
	{
		private bool globalset;

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

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

		public override void Serialize(SerializationBuffer data)
		{
			base.Serialize(data);
			data.Add(globalDamageWhenSet);
		}

		public override void Deserialize(SerializationBuffer data)
		{
			base.Deserialize(data);
			globalDamageWhenSet = data.nextFloat;
		}
	}
}
namespace ItemStatistics.Networking
{
	public struct DamageMessage
	{
		private Index inflictorIndex;

		internal DamageInfo damageInfo;

		public DamageMessage(DamageInfo damageInfo, Index inflictorIndex)
		{
			this.inflictorIndex = inflictorIndex;
			this.damageInfo = damageInfo;
		}

		public DamageMessage(in BlastAttackDamageInfo blastAttack, Index inflictorIndex)
		{
			//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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			this.inflictorIndex = inflictorIndex;
			damageInfo = new DamageInfo
			{
				attacker = blastAttack.attacker,
				inflictor = blastAttack.inflictor,
				damage = blastAttack.damage,
				crit = blastAttack.crit,
				force = blastAttack.force,
				procChainMask = blastAttack.procChainMask,
				procCoefficient = blastAttack.procCoefficient,
				damageType = blastAttack.damageType,
				damageColorIndex = blastAttack.damageColorIndex,
				position = blastAttack.position,
				canRejectForce = blastAttack.canRejectForce
			};
			damageInfo.ModifyDamageInfo(blastAttack.damageModifier);
		}

		internal static void Serialize(NetworkWriter writer, DamageMessage value)
		{
			Index.Serialize(writer, value.inflictorIndex);
			NetworkExtensions.Write(writer, value.damageInfo);
		}

		internal static DamageMessage Deserialize(NetworkReader reader)
		{
			DamageMessage result = default(DamageMessage);
			result.inflictorIndex = Index.Deserialize(reader);
			result.damageInfo = NetworkExtensions.ReadDamageInfo(reader);
			result.damageInfo.inflictor = ProcComponent.CreateInflictor(result.inflictorIndex, null);
			return result;
		}
	}
	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.isNotNone;
				}
				return false;
			}
		}

		internal static void Hook()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			HookManager.Hook(MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/), (Delegate)new <>A{00000018}<BlastAttack_ClientReportDamage, BlastAttackDamageInfo>(NetworkMessage_On_BlastAttack_ClientReportDamage));
			HookManager.Hook(MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/), new Manipulator(Inflictor_IL_BlastAttack_HandleHits));
			HookManager.Hook(MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/), new Manipulator(NetworkMessage_IL_BulletAttack_DefaultHitCallbackImplementation));
			HookManager.Hook(MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/), new Manipulator(Inflictor_IL_OverlapAttack_ProcessHits));
			HookManager.Hook(MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/), new Manipulator(SetInflictor_On_BasicMeleeAttack_AuthorityFireAttack));
		}

		private static void NetworkMessage_On_BlastAttack_ClientReportDamage(BlastAttack_ClientReportDamage orig, in BlastAttackDamageInfo blastAttack)
		{
			if (!shouldClientSendMessage)
			{
				orig(in blastAttack);
			}
			else if (Object.op_Implicit((Object)(object)blastAttack.hitHealthComponent))
			{
				TrackModdedUsers.localUser.CallCmdAttack(new DamageMessage(in blastAttack, inflictorIndex), ((Component)blastAttack.hitHealthComponent).gameObject, shouldHitProceed: true);
			}
		}

		private static void Inflictor_IL_BlastAttack_HandleHits(ILContext context)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(context);
			if (val.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(BlastAttack), "PerformDamageServer")
			}))
			{
				val.Emit(OpCodes.Dup);
				val.Emit(OpCodes.Dup);
				val.Emit<BlastAttackDamageInfo>(OpCodes.Ldfld, "inflictor");
				val.Emit(OpCodes.Call, (MethodBase)new Func<GameObject, GameObject>(ReplaceInflictor).Method);
				val.Emit<BlastAttackDamageInfo>(OpCodes.Stfld, "inflictor");
			}
			else
			{
				val.LogErrorCaller("failed find");
			}
		}

		private static void NetworkMessage_IL_BulletAttack_DefaultHitCallbackImplementation(ILContext context)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(context);
			int shouldHitIndex = 9;
			if (!val.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(FriendlyFireManager), "ShouldDirectHitProceed")
			}) || !val.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchStloc(a, ref shouldHitIndex)
			}))
			{
				val.LogErrorCaller("shouldHitIndex");
				return;
			}
			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")
			}))
			{
				val.LogErrorCaller("damageInfoIndex");
			}
			else
			{
				int index = val.Index;
				val.Index = index + 1;
				val.Emit(OpCodes.Dup);
				val.EmitDelegate<Action<DamageInfo>>((Action<DamageInfo>)delegate(DamageInfo damageInfo)
				{
					if (inflictorIndex.isNotNone)
					{
						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.Emit(OpCodes.Ldloc, shouldHitIndex);
				val.EmitDelegate<<>A{00000001}<BulletHit, DamageInfo, bool>>((<>A{00000001}<BulletHit, DamageInfo, bool>)delegate(ref BulletHit hitInfo, DamageInfo damageInfo, bool shouldHit)
				{
					TrackModdedUsers.localUser.CallCmdAttack(new DamageMessage(damageInfo, inflictorIndex), Object.op_Implicit((Object)(object)hitInfo.hitHurtBox) ? ((Component)hitInfo.hitHurtBox.healthComponent).gameObject : null, shouldHit);
				});
				val.Emit(OpCodes.Br, (object)branchSkip);
			}
			else
			{
				val.LogErrorCaller("Failed client IL");
			}
		}

		private static void Inflictor_IL_OverlapAttack_ProcessHits(ILContext context)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(context);
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchLdfld(a, typeof(OverlapAttack), "inflictor")
			}))
			{
				val.Emit(OpCodes.Call, (MethodBase)new Func<GameObject, GameObject>(ReplaceInflictor).Method);
			}
			else
			{
				val.LogErrorCaller("inflictor");
			}
			if (val.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchLdsfld(a, typeof(PlatformSystems), "networkManager")
			}))
			{
				val.Emit(OpCodes.Call, (MethodBase)typeof(NetworkHooks).GetMethod("get_shouldClientSendMessage"));
				val.Emit(OpCodes.Brfalse, val.Next);
				val.EmitDelegate<Action>((Action)delegate
				{
					TrackModdedUsers.localUser.CallCmdOverlapAttack(new OverlapMessage(OverlapAttack.outgoingMessage, inflictorIndex));
				});
				val.Emit(OpCodes.Ret);
			}
			else
			{
				val.LogErrorCaller("Failed client IL");
			}
		}

		private static void SetInflictor_On_BasicMeleeAttack_AuthorityFireAttack(ILContext context)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_003b: 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_0058: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(context);
			if (val.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(OverlapAttack), "Fire")
			}))
			{
				val.Emit(OpCodes.Ldarg_0);
				val.Emit<BasicMeleeAttack>(OpCodes.Ldfld, "meleeInflictorIndex");
				val.Emit(OpCodes.Stsfld, typeof(NetworkHooks).GetField("inflictorIndex"));
				int index = val.Index;
				val.Index = index + 1;
				val.Emit(OpCodes.Ldsflda, typeof(NetworkHooks).GetField("inflictorIndex"));
				val.Emit(OpCodes.Initobj, typeof(Index));
			}
			else
			{
				val.LogErrorCaller("inflictor");
			}
		}

		private static GameObject ReplaceInflictor(GameObject inflictor)
		{
			if (inflictorIndex.isNotNone && (!Object.op_Implicit((Object)(object)inflictor) || !ProcComponent.inflictorToProc.ContainsKey(inflictor)))
			{
				return ProcComponent.CreateInflictor(inflictorIndex, null);
			}
			return inflictor;
		}
	}
	public struct OverlapMessage
	{
		private Index inflictorIndex;

		internal OverlapAttackMessage overlapAttack;

		public OverlapMessage(OverlapAttackMessage overlapAttack, Index inflictorIndex)
		{
			this.inflictorIndex = inflictorIndex;
			this.overlapAttack = overlapAttack;
		}

		internal static void Serialize(NetworkWriter writer, OverlapMessage value)
		{
			Index.Serialize(writer, value.inflictorIndex);
			((MessageBase)value.overlapAttack).Serialize(writer);
		}

		internal static OverlapMessage Deserialize(NetworkReader reader)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			OverlapMessage result = default(OverlapMessage);
			result.inflictorIndex = Index.Deserialize(reader);
			result.overlapAttack = new OverlapAttackMessage();
			((MessageBase)result.overlapAttack).Deserialize(reader);
			result.overlapAttack.inflictor = ProcComponent.CreateInflictor(result.inflictorIndex, null);
			return result;
		}
	}
	public class SerializationBuffer : IEnumerable<Index>, IEnumerable
	{
		[StructLayout(LayoutKind.Explicit)]
		private struct IntFloat
		{
			[FieldOffset(0)]
			private float floatValue;

			[FieldOffset(0)]
			private uint intValue;

			internal static float IntToFloat(uint value)
			{
				IntFloat intFloat = default(IntFloat);
				intFloat.intValue = value;
				return intFloat.floatValue;
			}

			internal static uint FloatToInt(float value)
			{
				IntFloat intFloat = default(IntFloat);
				intFloat.floatValue = value;
				return intFloat.intValue;
			}
		}

		private static readonly SerializationBuffer staticBuffer = new SerializationBuffer(4u, 4u);

		private Index[] indexes;

		private uint[] bits;

		private uint indexSize;

		private uint bitsSize;

		private uint bitPos;

		public uint nextInt => bits[bitPos++];

		public float nextFloat => IntFloat.IntToFloat(nextInt);

		public bool hasSomething => indexSize != 0;

		publ