Decompiled source of ItemStatistics v1.2.11

plugins/ItemStatistics.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 EntityStates;
using EntityStates.CaptainDefenseMatrixItem;
using EntityStates.Chef;
using EntityStates.Drone.Command;
using EntityStates.Drone.DroneCopycat;
using EntityStates.DroneWeaponsChainGun;
using EntityStates.FriendUnit;
using EntityStates.GummyClone;
using EntityStates.Headstompers;
using EntityStates.Toolbot;
using EntityStates.Treebot.TreebotFlower;
using EntityStates.Treebot.Weapon;
using EntityStates.VoidSurvivor.Weapon;
using HG;
using HG.GeneralSerializer;
using HG.Reflection;
using ItemStatistics;
using ItemStatistics.Components;
using ItemStatistics.Hooks;
using ItemStatistics.Networking;
using JetBrains.Annotations;
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: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: OptIn]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.11.0")]
[module: UnverifiableCode]
namespace Dolso
{
	internal static class log
	{
		private static readonly ManualLogSource logger = Logger.CreateLogSource(Assembly.GetExecutingAssembly().GetName().Name);

		[Conditional("DEBUG")]
		internal static void debug(object data)
		{
			logger.LogDebug(data);
		}

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

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

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

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

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

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

		internal static void LogErrorCaller(this ILCursor c, object data)
		{
			logger.LogError((object)$"ILCursor failed in {new StackFrame(1).GetMethod().Name}, skipping: {data}\n{c}");
		}
	}
	internal static class HookManager
	{
		internal delegate bool ConfigEnabled<T>(T configValue);

		private class HookedConfig<T>
		{
			private readonly ConfigEnabled<T> enabled;

			private readonly IDetour detour;

			internal HookedConfig(ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, IDetour detour)
			{
				this.enabled = enabled;
				this.detour = detour;
				if (configEntry != null)
				{
					configEntry.SettingChanged += ConfigChanged;
					ConfigChanged(configEntry, null);
				}
				else
				{
					detour.Apply();
				}
			}

			private void ConfigChanged(object sender, EventArgs args)
			{
				if (enabled(((ConfigEntry<T>)sender).Value))
				{
					if (!detour.IsApplied)
					{
						detour.Apply();
					}
				}
				else if (detour.IsApplied)
				{
					detour.Undo();
				}
			}
		}

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

		private static readonly ConfigEnabled<bool> boolConfigEnabled = BoolEnabled;

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

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

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

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

		internal static void Hook(MethodBase fromMethod, Manipulator ilHook)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				new ILHook(fromMethod, ilHook, ref ilHookConfig).Apply();
			}
			catch (Exception e)
			{
				e.LogHookError(fromMethod, ((Delegate)(object)ilHook).Method);
			}
		}

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

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

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

		internal static void Hook(MethodBase fromMethod, MethodInfo onHook, object target = null)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				new Hook(fromMethod, onHook, target, ref onHookConfig).Apply();
			}
			catch (Exception e)
			{
				e.LogHookError(fromMethod, onHook);
			}
		}

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

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

		internal static void HookConfig(this ConfigEntry<bool> configEntry, MethodBase fromMethod, MethodInfo hook)
		{
			configEntry.HookConfig(boolConfigEnabled, fromMethod, hook);
		}

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

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

		internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase fromMethod, MethodInfo hook, object target = null)
		{
			try
			{
				new HookedConfig<T>(configEntry, enabled, ManualDetour(fromMethod, hook, target));
			}
			catch (Exception e)
			{
				e.LogHookError(fromMethod, hook);
			}
		}

		internal static IDetour ManualDetour(Type typeFrom, string fromMethod, Delegate hook)
		{
			return ManualDetour(GetMethod(typeFrom, fromMethod), hook.Method, hook.Target);
		}

		internal static IDetour ManualDetour(MethodBase fromMethod, Delegate hook)
		{
			return ManualDetour(fromMethod, hook.Method, hook.Target);
		}

		internal static IDetour ManualDetour(MethodBase fromMethod, MethodInfo hook, object target = null)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			try
			{
				ParameterInfo[] parameters = hook.GetParameters();
				if (parameters.Length == 1 && parameters[0].ParameterType == typeof(ILContext))
				{
					return (IDetour)new ILHook(fromMethod, (Manipulator)hook.CreateDelegate(typeof(Manipulator)), ref ilHookConfig);
				}
				return (IDetour)new Hook(fromMethod, hook, target, ref onHookConfig);
			}
			catch (Exception e)
			{
				e.LogHookError(fromMethod, hook);
				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 a in typeFrom.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where a.Name == methodName
				select a).ToArray();
			switch (array.Length)
			{
			case 1:
				return array[0];
			case 0:
				log.error($"Failed to find method: {typeFrom}::{methodName}");
				return null;
			default:
			{
				string text = $"{array.Length} ambiguous matches found for: {typeFrom}::{methodName}, may be incorrect";
				MethodInfo[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					text = text + "\n" + array2[i];
				}
				log.warning(text);
				return array[0];
			}
			}
		}

		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_il = null, string[] before_on = null, string[] after_il = null, string[] after_on = null)
		{
			ilHookConfig.Before = before_il;
			onHookConfig.Before = before_on;
			ilHookConfig.After = after_il;
			onHookConfig.After = after_on;
		}

		internal static void LogHookError(this Exception e, MethodBase fromMethod, MethodInfo hook)
		{
			log.error((fromMethod == null) ? $"null from-method for hook: {hook.Name}\n{e}" : $"Failed to hook: {fromMethod.DeclaringType}::{fromMethod.Name} - {hook.Name}\n{e}");
		}

		private static bool BoolEnabled(bool configValue)
		{
			return configValue;
		}
	}
	internal static class Utilities
	{
		internal struct AsyncHandle<T> : IDisposable
		{
			private AsyncOperationHandle<T> handle;

			public T result => handle.Result;

			public Task<T> task => handle.Task;

			internal AsyncHandle(AsyncOperationHandle<T> handle)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				this.handle = handle;
			}

			public TaskAwaiter<T> GetAwaiter()
			{
				return handle.Task.GetAwaiter();
			}

			public void Dispose()
			{
				handle.Release();
			}

			public static implicit operator AsyncOperationHandle<T>(AsyncHandle<T> handle)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return handle.handle;
			}
		}

		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 AsyncHandle<T> GetAddressableAsync<T>(string addressable) where T : Object
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return new AsyncHandle<T>(Addressables.LoadAssetAsync<T>((object)addressable));
		}

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

		internal static void DoAddressable<T>(string addressable, Action<T> callback, bool release = false) where T : Object
		{
			//IL_0016: 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)
			AsyncOperationHandle<T> handle = Addressables.LoadAssetAsync<T>((object)addressable);
			handle.Completed += delegate(AsyncOperationHandle<T> a)
			{
				callback(a.Result);
				if (release)
				{
					handle.Release();
				}
			};
		}

		internal static void DoAddressable(string addressable, Action<GameObject> callback, bool release = false)
		{
			//IL_0016: 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)
			AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>((object)addressable);
			handle.Completed += delegate(AsyncOperationHandle<GameObject> a)
			{
				callback(a.Result);
				if (release)
				{
					handle.Release();
				}
			};
		}

		internal static void AddressableAddComp<TComp>(string addressable, Action<TComp> callback = null) where TComp : 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)
			{
				TComp obj = a.Result.AddComponent<TComp>();
				callback?.Invoke(obj);
			};
		}

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

		internal static void 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 != null && StringSerializer.CanSerializeType(newValue.GetType()))
					{
						serializedFields[i].fieldValue.stringValue = StringSerializer.Serialize(newValue.GetType(), newValue);
					}
					else
					{
						log.error("Invalid value for SerializedField: " + newValue);
					}
					return;
				}
			}
			log.error("Failed to find " + fieldName + " for " + ((Object)stateConfig).name);
		}

		internal static bool IsKeyDown(this KeyboardShortcut key, bool onlyJustPressed)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (onlyJustPressed)
			{
				if (!Input.GetKeyDown(((KeyboardShortcut)(ref key)).MainKey))
				{
					return false;
				}
			}
			else if (!Input.GetKey(((KeyboardShortcut)(ref key)).MainKey))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref key)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			return true;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
	[MeansImplicitUse]
	internal class HookAttribute : Attribute
	{
		private readonly Type typeFrom;

		private readonly string methodFrom;

		private readonly Type[] parameters;

		protected MethodInfo from
		{
			get
			{
				if ((object)typeFrom != null)
				{
					if (parameters != null)
					{
						return HookManager.GetMethod(typeFrom, methodFrom, parameters);
					}
					return HookManager.GetMethod(typeFrom, methodFrom);
				}
				return null;
			}
		}

		internal HookAttribute(Type typeFrom, string methodFrom)
		{
			this.typeFrom = typeFrom;
			this.methodFrom = methodFrom;
		}

		internal HookAttribute(Type typeFrom, string methodFrom, params Type[] parameters)
		{
			this.typeFrom = typeFrom;
			this.methodFrom = methodFrom;
			this.parameters = parameters;
		}

		internal HookAttribute()
		{
		}

		internal static void ScanAndApply()
		{
			ScanAndApply((from a in Assembly.GetExecutingAssembly().GetTypes()
				where a.GetCustomAttribute<HookAttribute>() != null
				select a).ToArray());
		}

		internal static void ScanAndApply(params Type[] types)
		{
			for (int i = 0; i < types.Length; i++)
			{
				MethodInfo[] methods = types[i].GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					foreach (HookAttribute customAttribute in methodInfo.GetCustomAttributes<HookAttribute>(inherit: false))
					{
						MethodInfo methodInfo2 = null;
						try
						{
							methodInfo2 = customAttribute.from;
							if (methodInfo2 == null && methodInfo.GetParameters().Length == 0)
							{
								methodInfo.Invoke(null, null);
							}
							else
							{
								customAttribute.Hook(methodInfo2, methodInfo);
							}
						}
						catch (Exception e)
						{
							e.LogHookError(methodInfo2, methodInfo);
						}
					}
				}
			}
		}

		protected virtual void Hook(MethodInfo from, MethodInfo member)
		{
			IDetour obj = HookManager.ManualDetour(from, member);
			if (obj != null)
			{
				obj.Apply();
			}
		}
	}
	internal static class RiskofOptions
	{
		internal const string RooGuid = "com.rune580.riskofoptions";

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

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void SetSprite(Sprite sprite)
		{
			ModSettingsManager.SetModIcon(sprite);
		}

		internal static void SetSpriteDefaultIcon()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string fullName = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)).FullName;
				Texture2D val = new Texture2D(256, 256);
				if (ImageConversion.LoadImage(val, File.ReadAllBytes(Path.Combine(fullName, "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(ConfigEntryBase entry)
		{
			AddOption(entry, string.Empty, string.Empty);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void AddOption(ConfigEntryBase entry, string categoryName = "", string name = "", bool restartRequired = false)
		{
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Expected O, but got Unknown
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			Type settingType = entry.SettingType;
			object obj;
			if (!(settingType == typeof(float)))
			{
				obj = ((!(settingType == typeof(string))) ? ((!(settingType == typeof(bool))) ? ((!(settingType == typeof(int))) ? ((!(settingType == typeof(Color))) ? ((!(settingType == typeof(KeyboardShortcut))) ? ((object)((!settingType.IsEnum) ? ((ChoiceOption)null) : new ChoiceOption(entry, new ChoiceConfig()))) : ((object)new KeyBindOption((ConfigEntry<KeyboardShortcut>)(object)entry, new KeyBindConfig()))) : ((object)new ColorOption((ConfigEntry<Color>)(object)entry, new ColorOptionConfig()))) : ((object)new IntFieldOption((ConfigEntry<int>)(object)entry, new IntFieldConfig()))) : ((object)new CheckBoxOption((ConfigEntry<bool>)(object)entry, new CheckBoxConfig()))) : ((object)new StringInputFieldOption((ConfigEntry<string>)(object)entry, new InputFieldConfig
				{
					submitOn = (SubmitEnum)6,
					lineType = (LineType)0
				})));
			}
			else if (entry.Description.AcceptableValues is AcceptableValueRange<float>)
			{
				obj = (object)new SliderOption((ConfigEntry<float>)(object)entry, new SliderConfig
				{
					min = ((AcceptableValueRange<float>)(object)entry.Description.AcceptableValues).MinValue,
					max = ((AcceptableValueRange<float>)(object)entry.Description.AcceptableValues).MaxValue,
					FormatString = "{0:f2}",
					description = entry.DescWithDefault("{0:f2}")
				});
			}
			else
			{
				ConfigEntry<float> obj2 = (ConfigEntry<float>)(object)entry;
				FloatFieldConfig val = new FloatFieldConfig();
				((NumericFieldConfig<float>)val).FormatString = "{0:f2}";
				((BaseOptionConfig)val).description = entry.DescWithDefault("{0:f2}");
				obj = (object)new FloatFieldOption(obj2, val);
			}
			BaseOption val2 = (BaseOption)obj;
			if (val2 == null)
			{
				return;
			}
			BaseOptionConfig config = val2.GetConfig();
			config.category = categoryName;
			config.name = name;
			config.restartRequired = restartRequired;
			if (config.description == "")
			{
				config.description = entry.DescWithDefault();
			}
			try
			{
				ModSettingsManager.AddOption(val2);
			}
			catch (Exception arg)
			{
				log.error($"AddOption {entry.Definition} failed\n{arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void AddOption(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)
			}));
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		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_0031: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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, string format = "{0}")
		{
			return string.Format("{1}\n[Default: " + format + "]", entry.DefaultValue, entry.Description.Description);
		}
	}
}
namespace ItemStatistics
{
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public readonly struct ChainContext : IDisposable
	{
		private static readonly List<ProcChain> chains;

		internal static ConstructorInfo constructor0 => typeof(ChainContext).GetConstructor(Type.EmptyTypes);

		internal static ConstructorInfo constructor1 => typeof(ChainContext).GetConstructor(new Type[1] { typeof(ProcChain) });

		public ChainContext(ProcChain procChain)
		{
			chains.Add(CurrentContext.proc_chain = procChain);
		}

		public ChainContext()
			: this(default(ProcChain))
		{
		}

		public void Dispose()
		{
			chains.RemoveAt(chains.Count - 1);
			ProcChain proc_chain;
			if (chains.Count <= 0)
			{
				proc_chain = default(ProcChain);
			}
			else
			{
				List<ProcChain> list = chains;
				proc_chain = list[list.Count - 1];
			}
			CurrentContext.proc_chain = proc_chain;
		}

		static ChainContext()
		{
			chains = new List<ProcChain>();
			Stage.onStageStartGlobal += SafetyCheck;
		}

		private static void SafetyCheck(Stage stage)
		{
			if (chains.Count != 0 || CurrentContext.proc_chain.isNotEmpty)
			{
				log.error("ChainContext has leaked chains: " + string.Join(", ", chains));
				chains.Clear();
			}
		}

		public override string ToString()
		{
			return "current_static_chain: " + CurrentContext.proc_chain;
		}
	}
	internal static class Config
	{
		internal enum ResetMode
		{
			Never,
			WhenNotInInventory
		}

		private static ConfigFile configFile;

		internal static ConfigEntry<ResetMode> resetOnStackChanged;

		internal static ConfigEntry<KeyboardShortcut> resetSpamKey;

		internal static ConfigEntry<KeyboardShortcut> resetAllKey;

		internal static void DoConfig(ConfigFile bepConfigFile)
		{
			//IL_003e: 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)
			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");
			resetAllKey = configFile.Bind<KeyboardShortcut>(string.Empty, "Reset All Key", new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Press this key to reset all trackers in your inventory");
			if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
			{
				DoRiskOfOptions();
			}
		}

		internal static void DoRiskOfOptions()
		{
			RiskofOptions.SetSpriteDefaultIcon();
			RiskofOptions.AddOption((ConfigEntryBase)(object)resetOnStackChanged);
			RiskofOptions.AddOption((ConfigEntryBase)(object)resetSpamKey);
			RiskofOptions.AddOption((ConfigEntryBase)(object)resetAllKey);
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		private static void ReloadConfig(ConCommandArgs args)
		{
			configFile.Reload();
			Debug.Log((object)"ItemStatistics config reloaded");
		}
	}
	public static class CurrentContext
	{
		public readonly struct ContextData
		{
			public readonly TrackedInventory tracked_inventory;

			public readonly Inventory inventory;

			public readonly bool has_tracked_inv;

			public readonly bool is_owner;

			internal ContextData(TrackedInventory tracked, Inventory inventory)
			{
				tracked_inventory = tracked;
				this.inventory = inventory;
				has_tracked_inv = Object.op_Implicit((Object)(object)tracked);
				is_owner = has_tracked_inv && (Object)(object)tracked.inventory == (Object)(object)inventory;
			}
		}

		public static ProcChain proc_chain;

		public static ContextData attacker;

		public static ContextData victim;

		private static DamageInfo cached_info;

		private static ProcChain cached_chain;

		internal static ProcChain FindProcChain(DamageInfo damageInfo)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (damageInfo == cached_info)
			{
				return cached_chain;
			}
			cached_info = damageInfo;
			if (damageInfo.source_inflictor != null)
			{
				return cached_chain = damageInfo.source_inflictor.source_chain;
			}
			ProcComponent procComponent = default(ProcComponent);
			if (Object.op_Implicit((Object)(object)damageInfo.inflictor) && damageInfo.inflictor.TryGetComponent<ProcComponent>(ref procComponent))
			{
				return cached_chain = procComponent.procChain;
			}
			if (((DamageTypeCombo)(ref damageInfo.damageType)).IsDamageSourceSkillBased)
			{
				if (Object.op_Implicit((Object)(object)damageInfo.attacker))
				{
					CharacterBody component = damageInfo.attacker.GetComponent<CharacterBody>();
					object obj;
					if (component == null)
					{
						obj = null;
					}
					else
					{
						CharacterMaster master = component.master;
						if (master == null)
						{
							obj = null;
						}
						else
						{
							MinionOwnership minionOwnership = master.minionOwnership;
							obj = ((minionOwnership != null) ? minionOwnership.ownerMaster : null);
						}
					}
					if (!((Object)obj == (Object)null))
					{
						goto IL_00da;
					}
				}
				Index index = damageInfo.damageType.damageSource;
				return cached_chain = (index.isNotNone ? new ProcChain(index) : default(ProcChain));
			}
			goto IL_00da;
			IL_00da:
			return cached_chain = default(ProcChain);
		}
	}
	internal readonly struct HcContext : IDisposable
	{
		internal readonly struct IndexMultPair
		{
			internal readonly Index index;

			internal readonly float mult;

			internal IndexMultPair(Index index, float mult)
			{
				this.index = index;
				this.mult = mult;
			}
		}

		private static readonly List<HcContext> contexts = new List<HcContext>();

		private static int depth;

		private readonly List<IndexMultPair> value;

		internal static List<IndexMultPair> current
		{
			get
			{
				if (depth <= 0)
				{
					return null;
				}
				return contexts[depth - 1].value;
			}
		}

		public HcContext()
		{
			depth++;
			if (depth > contexts.Count)
			{
				value = new List<IndexMultPair>();
				contexts.Add(this);
			}
			else
			{
				this = contexts[depth - 1];
			}
		}

		public void Dispose()
		{
			value.Clear();
			depth--;
		}
	}
	public readonly struct HitContext : IDisposable
	{
		private readonly ChainContext chain_context;

		private readonly TrackedInventory attackerTrackedInventory;

		private readonly Inventory attackerInventory;

		private readonly TrackedInventory victimTrackedInventory;

		private readonly Inventory victimInventory;

		private static readonly List<HitContext> hits;

		public HitContext(ProcChain procChain, TrackedInventory attackerTrackedInventory, Inventory attackerInventory, TrackedInventory victimTrackedInventory, Inventory victimInventory)
		{
			chain_context = new ChainContext(procChain);
			this.attackerTrackedInventory = attackerTrackedInventory;
			this.attackerInventory = attackerInventory;
			this.victimTrackedInventory = victimTrackedInventory;
			this.victimInventory = victimInventory;
			CurrentContext.attacker = new CurrentContext.ContextData(attackerTrackedInventory, attackerInventory);
			CurrentContext.victim = new CurrentContext.ContextData(victimTrackedInventory, victimInventory);
			hits.Add(this);
		}

		public HitContext()
			: this(default(ProcChain), null, null, null, null)
		{
		}

		public void Dispose()
		{
			chain_context.Dispose();
			hits.RemoveAt(hits.Count - 1);
			HitContext obj;
			if (hits.Count <= 0)
			{
				obj = default(HitContext);
			}
			else
			{
				List<HitContext> list = hits;
				obj = list[list.Count - 1];
			}
			HitContext hitContext = obj;
			CurrentContext.attacker = new CurrentContext.ContextData(hitContext.attackerTrackedInventory, hitContext.attackerInventory);
			CurrentContext.victim = new CurrentContext.ContextData(hitContext.victimTrackedInventory, hitContext.victimInventory);
		}

		static HitContext()
		{
			hits = new List<HitContext>();
			Stage.onStageStartGlobal += SafetyCheck;
		}

		private static void SafetyCheck(Stage stage)
		{
			if (hits.Count != 0 || CurrentContext.attacker.has_tracked_inv)
			{
				log.error("HitContext has leaked hits: " + string.Join(",\n", hits));
				hits.Clear();
			}
		}

		public override string ToString()
		{
			return string.Join(", ", chain_context, attackerTrackedInventory, attackerInventory, victimTrackedInventory, victimInventory);
		}
	}
	[Serializable]
	public struct Index : IEquatable<Index>
	{
		[SerializeField]
		private short _index;

		[SerializeField]
		private IndexType _type;

		public readonly short index => _index;

		public readonly IndexType type => _type;

		public readonly bool isNone => _type == IndexType.None;

		public readonly bool isNotNone => _type != IndexType.None;

		public Index(ItemIndex x)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			_index = (short)x;
			_type = IndexType.Item;
		}

		public Index(EquipmentIndex x)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			_index = (short)x;
			_type = IndexType.Equip;
		}

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

		public Index(MiscIndex x)
		{
			_index = (short)x;
			_type = IndexType.Misc;
		}

		public Index(BodyIndex x)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			_index = (short)x;
			_type = IndexType.Body;
		}

		public Index(short index, IndexType type)
		{
			_index = index;
			_type = type;
		}

		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(MiscIndex index)
		{
			return new Index(index);
		}

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

		public static implicit operator Index(DamageSource damageSource)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected I4, but got Unknown
			switch (damageSource - 1)
			{
			case 0:
				return new Index((SkillSlot)0);
			case 1:
			case 2:
				return new Index((SkillSlot)1);
			case 3:
			case 4:
				return new Index((SkillSlot)2);
			case 7:
			case 8:
			case 9:
			case 11:
				return new Index((SkillSlot)3);
			default:
				return new Index(0, IndexType.None);
			}
		}

		public static bool operator ==(Index a, Index b)
		{
			if (a._index == b._index)
			{
				return a._type == b._type;
			}
			return false;
		}

		public static bool operator !=(Index a, Index b)
		{
			if (a._index == b._index)
			{
				return a._type != b._type;
			}
			return true;
		}

		public readonly bool Equals(Index index)
		{
			if (_index == index._index)
			{
				return _type == index._type;
			}
			return false;
		}

		public override readonly bool Equals(object obj)
		{
			if (obj is Index)
			{
				return Equals((Index)obj);
			}
			return false;
		}

		public override readonly int GetHashCode()
		{
			return (_index & 0xFFFF) + ((int)_type << 16);
		}

		public override readonly string ToString()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			switch (_type)
			{
			case IndexType.None:
				if (_index == 0)
				{
					return "None";
				}
				return "None." + _index;
			case IndexType.Item:
				return ((ItemIndex)_index).Name();
			case IndexType.Equip:
				return ((EquipmentIndex)_index).Name();
			case IndexType.SkillSlot:
			{
				SkillSlot val = (SkillSlot)(sbyte)_index;
				return "Skill." + ((object)(SkillSlot)(ref val)).ToString();
			}
			case IndexType.Misc:
				return "Misc." + (MiscIndex)_index;
			case IndexType.Body:
				return ((BodyIndex)_index).Name();
			default:
				return $"Unknown Index {{t:{_type}, i:{_index}}}";
			}
		}

		internal static void Serialize(NetworkWriter writer, Index value)
		{
			writer.Write(value._index);
			writer.Write((short)value._type);
		}

		internal static Index Deserialize(NetworkReader reader)
		{
			return new Index(reader.ReadInt16(), (IndexType)reader.ReadInt16());
		}
	}
	public enum IndexType : short
	{
		None,
		Item,
		Equip,
		SkillSlot,
		Misc,
		Body
	}
	public enum MiscIndex
	{
		NeverInInventory = -1,
		Ignore = 0,
		Regen = 1,
		Barrier = 2,
		MinionDamage = 3,
		Shield = 4,
		FreezeCreditMinionBody = -2
	}
	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 trackedDef)
		{
			if (trackedDef.flags != 0)
			{
				ItemStatisticsPlugin.indexToDef.Add(indexToAdd, trackedDef);
			}
			else
			{
				log.error($"Attempted to give {indexToAdd} an undefined tracker def");
			}
		}

		public static void AddCombatStackTracker(Index index, BuffIndex buffIndex)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			ItemStatisticsPlugin.combatBuffsTrackers.Add((index, buffIndex));
		}

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

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

		public static GameObject CreateNewInflictor(Index index, ProcChain parentChain = default(ProcChain))
		{
			return ProcComponent.CreateInflictor(index, parentChain);
		}

		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.AddAttempt(index);
		}

		public static void CreditProcSuccess(TrackedInventory trackedInventory, Index index)
		{
			trackedInventory.AddSuccess(index);
		}
	}
	[BepInPlugin("dolso.ItemStatistics", "ItemStatistics", "1.2.11")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ItemStatisticsPlugin : BaseUnityPlugin
	{
		public const string ModGuid = "dolso.ItemStatistics";

		public const string Version = "1.2.11";

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

		internal static readonly List<(Index index, BuffIndex buffIndex)> combatBuffsTrackers = new List<(Index, BuffIndex)>();

		internal static GameObject missileLauncher;

		internal static GameObject hhOverloading;

		internal static GameObject hhFireTrail;

		internal static GameObject hhGoldOuter;

		internal static GameObject hhGoldInner;

		internal static GameObject hhBead;

		internal static int crocoDiseaseProjectileIndex;

		internal static BodyIndex falseSonCharacterBodyIndex;

		private void Awake()
		{
			Config.DoConfig(((BaseUnityPlugin)this).Config);
			ModifyAddressablesAsync();
			Stopwatch stopwatch = Stopwatch.StartNew();
			Language.collectLanguageRootFolders += CollectLanguageRootFolders;
			HookAttribute.ScanAndApply();
			log.info($"Hooks completed in {stopwatch.Elapsed.TotalSeconds:f2}s");
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Config.resetAllKey.Value.IsKeyDown(onlyJustPressed: true))
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				if (firstLocalUser != null)
				{
					firstLocalUser.cachedMaster?.trackedInventory.CallCmdResetAllTrackers();
				}
			}
		}

		private static void ModifyAddressablesAsync()
		{
			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.AddressableAddComp<TrackedInventory>("RoR2/Base/Core/PlayerMaster.prefab", (Action<TrackedInventory>)null);
				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();
				Utilities.AddressableAddComp<SharedSufferingAddOn>("RoR2/DLC3/DLC3RunBehavior.prefab", (Action<SharedSufferingAddOn>)null);
			}
			catch (Exception ex)
			{
				log.error("Failed to do addressables\n" + ex);
			}
		}

		[InitDuringStartupPhase(/*Could not decode attribute arguments.*/)]
		private static void Init()
		{
			//IL_0d5e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d7d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d9c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dbb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dda: Unknown result type (might be due to invalid IL or missing references)
			//IL_0df9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e18: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e37: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e55: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e7d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e82: 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(MiscIndex.Regen, new TrackedDef(TrackerFlags.Heal, TrackedDef.regen_portion_tooltip));
			dictionary.Add(MiscIndex.Barrier, new TrackedDef(TrackerFlags.Block, TrackedDef.barrier_blocked_tooltip));
			dictionary.Add(MiscIndex.MinionDamage, new TrackedDef(TrackerFlags.Damage, TrackedDef.minion_portion_tooltip));
			dictionary.Add(MiscIndex.Shield, new TrackedDef(TrackerFlags.Block, TrackedDef.shield_blocked_tooltip));
			dictionary.Add(Items.Bear, TrackedDef.ArmorCountChance);
			dictionary.Add(Items.BearVoid, TrackedDef.ArmorCountChance);
			dictionary.Add(Items.Crowbar, TrackedDef.Damage);
			dictionary.Add(Items.ExplodeOnDeathVoid, TrackedDef.DamagePortion);
			dictionary.Add(Items.NearbyDamageBonus, TrackedDef.Damage);
			dictionary.Add(Items.FragileDamageBonus, TrackedDef.Damage);
			dictionary.Add(Items.FragileDamageBonusConsumed, new TrackedDef(TrackerFlags.Damage, TrackedDef.damage_tooltip));
			dictionary.Add(Items.BossDamageBonus, TrackedDef.Damage);
			dictionary.Add(Items.CritGlasses, new TrackedDef(TrackerFlags.Damage, TrackedDef.total_crit_tooltip));
			dictionary.Add(Items.CritDamage, TrackedDef.Damage);
			dictionary.Add(Items.DeathMark, TrackedDef.Damage);
			dictionary.Add(Items.CritGlassesVoid, TrackedDef.DamageChance);
			dictionary.Add(Items.ExecuteLowHealthElite, TrackedDef.DamagePortion);
			dictionary.Add(Items.OutOfCombatArmor, TrackedDef.ArmorCountChance);
			dictionary.Add(Items.SprintArmor, TrackedDef.ArmorChance);
			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.DamagePortion);
			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.DamagePortionChance);
			dictionary.Add(Items.ExplodeOnDeath, TrackedDef.DamagePortionChance);
			dictionary.Add(Items.Dagger, TrackedDef.DamagePortion);
			dictionary.Add(Items.Tooth, TrackedDef.Heal);
			dictionary.Add(Items.Bandolier, TrackedDef.Chance);
			dictionary.Add(Items.BonusGoldPackOnKill, TrackedDef.Gold);
			dictionary.Add(Items.BleedOnHitAndExplode, new TrackedDef(TrackerFlags.Damage | TrackerFlags.Attempt, TrackedDef.hit_tooltip, TrackedDef.portion_tooltip));
			dictionary.Add(Items.BarrierOnKill, new TrackedDef(TrackerFlags.Heal, TrackedDef.barrier_gained_tooltip));
			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(TrackerFlags.Heal, TrackedDef.barrier_gained_tooltip));
			dictionary.Add(Items.ShockNearby, TrackedDef.DamagePortion);
			dictionary.Add(Items.PrimarySkillShuriken, new TrackedDef(TrackerFlags.Damage | TrackerFlags.Attempt, TrackedDef.hit_tooltip, TrackedDef.portion_tooltip));
			dictionary.Add(Items.StrengthenBurn, TrackedDef.Damage);
			dictionary.Add(Items.LaserTurbine, TrackedDef.DamagePortion);
			dictionary.Add(Items.CaptainDefenseMatrix, TrackedDef.Count);
			dictionary.Add(Items.Icicle, TrackedDef.DamagePortion);
			dictionary.Add(Items.NovaOnLowHealth, TrackedDef.DamagePortion);
			dictionary.Add(Items.ImmuneToDebuff, new TrackedDef(TrackerFlags.Heal | TrackerFlags.Success, TrackedDef.chance_tooltip, TrackedDef.barrier_gained_tooltip));
			dictionary.Add(Items.NovaOnHeal, TrackedDef.DamagePortion);
			dictionary.Add(Items.SprintWisp, TrackedDef.DamagePortion);
			dictionary.Add(Items.RandomlyLunar, TrackedDef.Chance);
			dictionary.Add(Items.Firework, TrackedDef.DamagePortion);
			dictionary.Add(Items.Phasing, TrackedDef.Count);
			dictionary.Add(Items.FallBoots, TrackedDef.DamagePortion);
			dictionary.Add(Items.SiphonOnLowHealth, new TrackedDef(TrackerFlags.Damage | TrackerFlags.Heal, TrackedDef.portion_tooltip, TrackedDef.heal_tooltip));
			dictionary.Add(Items.LunarSun, TrackedDef.DamagePortion);
			dictionary.Add(Items.Infusion, TrackedDef.Count);
			dictionary.Add(Items.HeadHunter, TrackedDef.Damage);
			dictionary.Add(Items.RoboBallBuddy, TrackedDef.DamagePortion);
			dictionary.Add(Items.VoidMegaCrabItem, TrackedDef.DamagePortion);
			dictionary.Add(Items.BeetleGland, TrackedDef.DamagePortion);
			dictionary.Add(Items.DroneWeapons, TrackedDef.DamagePortion);
			dictionary.Add(Items.GhostOnKill, TrackedDef.DamagePortion);
			dictionary.Add(Items.MinorConstructOnKill, TrackedDef.DamagePortion);
			dictionary.Add(Items.Squid, TrackedDef.DamagePortion);
			dictionary.Add(Items.TitanGoldDuringTP, TrackedDef.DamagePortion);
			dictionary.Add(Items.ExtraShrineItem, TrackedDef.Chance);
			dictionary.Add(Items.IncreasePrimaryDamage, TrackedDef.DamagePortion);
			dictionary.Add(Items.MeteorAttackOnHighDamage, TrackedDef.DamageChance);
			dictionary.Add(Items.KnockBackHitEnemies, TrackedDef.Damage);
			dictionary.Add(Items.StunAndPierce, TrackedDef.DamageChance);
			dictionary.Add(Items.LowerPricedChests, TrackedDef.Count);
			dictionary.Add(Items.LowerPricedChestsConsumed, TrackedDef.Count);
			dictionary.Add(Items.ItemDropChanceOnKill, TrackedDef.Chance);
			dictionary.Add(Items.BarrageOnBoss, TrackedDef.DamagePortion);
			dictionary.Add(Items.TeleportOnLowHealth, new TrackedDef(TrackerFlags.Damage | TrackerFlags.Success, TrackedDef.count_tooltip, TrackedDef.portion_tooltip));
			dictionary.Add(Items.TriggerEnemyDebuffs, TrackedDef.Damage);
			dictionary.Add(Items.WardOnLevel, TrackedDef.StackCombat);
			dictionary.Add(Items.WarCryOnMultiKill, TrackedDef.StackCombat);
			dictionary.Add(Items.EnergizedOnEquipmentUse, TrackedDef.StackCombat);
			dictionary.Add(Items.KillEliteFrenzy, TrackedDef.StackCombat);
			dictionary.Add(Items.MoveSpeedOnKill, TrackedDef.StackCombat);
			dictionary.Add(Items.SpeedBoostPickup, TrackedDef.StackCombat);
			dictionary.Add(Items.BoostAllStats, TrackedDef.StackCombat);
			dictionary.Add(Items.SprintBonus, TrackedDef.StackCombat);
			dictionary.Add(Items.SprintOutOfCombat, TrackedDef.Stack);
			dictionary.Add(Items.ArmorReductionOnHit, TrackedDef.StackHit);
			dictionary.Add(Items.PermanentDebuffOnHit, TrackedDef.StackHit);
			dictionary.Add(Items.RandomDamageZone, TrackedDef.StackHit);
			dictionary.Add(Items.IncreaseDamageOnMultiKill, TrackedDef.StackHit);
			dictionary.Add(Items.AttackSpeedPerNearbyAllyOrEnemy, TrackedDef.StackHitSkill);
			dictionary.Add(Items.AttackSpeedOnCrit, TrackedDef.StackHitSkill);
			dictionary.Add(Items.DronesDropDynamite, TrackedDef.DamagePortion);
			dictionary.Add(Items.PowerCube, TrackedDef.Armor);
			dictionary.Add(Items.JumpDamageStrike, new TrackedDef(TrackerFlags.Damage | TrackerFlags.Attempt, TrackedDef.stack_combat_tooltip, TrackedDef.portion_tooltip));
			dictionary.Add(Items.ShieldBooster, new TrackedDef(TrackerFlags.Block | TrackerFlags.Damage, TrackedDef.reduction_tooltip, TrackedDef.portion_tooltip));
			dictionary.Add(Items.SpeedOnPickup, TrackedDef.StackCombat);
			dictionary.Add(Items.BarrierOnCooldown, new TrackedDef(TrackerFlags.Heal, TrackedDef.barrier_gained_tooltip));
			dictionary.Add(Items.SharedSuffering, new TrackedDef(TrackerFlags.Damage, TrackedDef.sharedsuffering_tooltip));
			dictionary.Add(Items.PhysicsProjectile, new TrackedDef(TrackerFlags.Damage | TrackerFlags.Success, TrackedDef.count_tooltip, TrackedDef.portion_tooltip));
			dictionary.Add(Items.Duplicator, TrackedDef.Count);
			dictionary.Add(Items.CritAtLowerElevation, TrackedDef.StackHit);
			dictionary.Add(Items.WyrmOnHit, TrackedDef.DamageChance);
			dictionary.Add(Equipment.Saw, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.GoldGat, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.BFG, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.PassiveHealing, TrackedDef.Heal);
			dictionary.Add(Equipment.CommandMissile, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.Fruit, TrackedDef.Heal);
			dictionary.Add(Equipment.DroneBackup, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.Lightning, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.Recycle, new TrackedDef(TrackerFlags.Success, TrackedDef.recycled_tooltip));
			dictionary.Add(Equipment.LifestealOnHit, TrackedDef.Heal);
			dictionary.Add(Equipment.Molotov, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.VendingMachine, TrackedDef.Heal);
			dictionary.Add(Equipment.GummyClone, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.MultiShopCard, TrackedDef.Gold);
			dictionary.Add(Equipment.GainArmor, TrackedDef.Armor);
			dictionary.Add(Equipment.Meteor, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.BurnNearby, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.AffixRed, TrackedDef.Damage);
			dictionary.Add(Equipment.AffixBlue, TrackedDef.Damage);
			dictionary.Add(Equipment.AffixWhite, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.EliteAurelioniteEquipment, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.EliteBeadEquipment, TrackedDef.DamagePortion);
			dictionary.Add(Equipment.Parry, TrackedDef.Chance);
			List<(Index index, BuffIndex buffIndex)> list = combatBuffsTrackers;
			list.Add((Items.WardOnLevel, Buffs.Warbanner.buffIndex));
			list.Add((Items.WarCryOnMultiKill, Buffs.WarCryBuff.buffIndex));
			list.Add((Items.EnergizedOnEquipmentUse, Buffs.Energized.buffIndex));
			list.Add((Items.KillEliteFrenzy, Buffs.NoCooldowns.buffIndex));
			list.Add((Items.MoveSpeedOnKill, Buffs.KillMoveSpeed.buffIndex));
			list.Add((Items.SpeedBoostPickup, Buffs.ElusiveAntlersBuff.buffIndex));
			list.Add((Items.BoostAllStats, Buffs.BoostAllStatsBuff.buffIndex));
			list.Add((Items.JumpDamageStrike, Buffs.JumpDamageStrikeCharge.buffIndex));
			list.Add((Items.SpeedOnPickup, Buffs.SpeedOnPickup.buffIndex));
			ModifyPrefabs();
			crocoDiseaseProjectileIndex = ProjectileCatalog.FindProjectileIndex("CrocoDiseaseProjectile");
			falseSonCharacterBodyIndex = BodyCatalog.FindBodyIndex("FalseSonBody");
		}

		private static void ModifyPrefabs()
		{
			AddProcComponent("RoR2/Base/StickyBomb/StickyBomb.prefab", Items.StickyBomb);
			AddProcComponent("RoR2/Base/ElementalRings/FireTornado.prefab", Items.FireRing);
			AddProcComponent("RoR2/DLC1/ElementalRingVoid/ElementalRingVoidBlackHole.prefab", Items.ElementalRingVoid);
			AddProcComponent("RoR2/Base/FireballsOnHit/FireMeatBall.prefab", Items.FireballsOnHit);
			AddProcComponent("RoR2/DLC1/PrimarySkillShuriken/ShurikenProjectile.prefab", Items.PrimarySkillShuriken);
			AddProcComponent("RoR2/Base/LaserTurbine/LaserTurbineController.prefab", Items.LaserTurbine);
			AddProcComponent("RoR2/Base/LaserTurbine/LaserTurbineBomb.prefab", Items.LaserTurbine);
			AddProcComponent("RoR2/Base/Icicle/IcicleAura.prefab", Items.Icicle);
			AddProcComponent("RoR2/Base/NovaOnLowHealth/VagrantNovaItemBodyAttachment.prefab", Items.NovaOnLowHealth);
			AddProcComponent("RoR2/Base/Firework/FireworkProjectile.prefab", Items.Firework);
			AddProcComponent("RoR2/DLC1/LunarSun/LunarSunProjectile.prefab", Items.LunarSun);
			AddProcComponent("RoR2/Base/Dagger/DaggerProjectile.prefab", Items.Dagger);
			AddProcComponent("RoR2/Base/BleedOnHitAndExplode/BleedOnHitAndExplodeDelay.prefab", Items.BleedOnHitAndExplode);
			AddProcComponent("RoR2/DLC2/Items/StunAndPierce/StunAndPierceBoomerang.prefab", Items.StunAndPierce);
			AddProcComponent("RoR2/DLC2/Items/BarrageOnBoss/BossMissileProjectile.prefab", Items.BarrageOnBoss);
			Utilities.DoAddressable<GameObject>("RoR2/Base/BonusGoldPackOnKill/BonusMoneyPack.prefab", (Action<GameObject>)delegate(GameObject a)
			{
				((Component)a.GetComponentInChildren<MoneyPickup>()).gameObject.AddComponent<ProcComponent>().index = Items.BonusGoldPackOnKill;
			}, release: false);
			AddProcComponent("RoR2/DLC3/Items/DronesDropDynamite/DynamiteProjectile.prefab", Items.DronesDropDynamite);
			AddProcComponent("RoR2/DLC3/Items/WyrmOnHit/WyrmProjectile.prefab", Items.WyrmOnHit);
			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);
			AddMinionComponent("RoR2/DLC3/FriendUnit/FriendUnitBody.prefab", Items.PhysicsProjectile);
			Utilities.AddressableAddComp<ProjectileBehaviour>("RoR2/Base/Nullifier/NullifierDeathBombProjectile.prefab", (Action<ProjectileBehaviour>)delegate(ProjectileBehaviour a)
			{
				a.projectile = ProjectileBehaviour.Projectile.ZoeaDeath;
			});
			Utilities.AddressableAddComp<ProjectileBehaviour>("RoR2/DLC1/VoidJailer/VoidJailerDeathBombProjectile.prefab", (Action<ProjectileBehaviour>)delegate(ProjectileBehaviour a)
			{
				a.projectile = ProjectileBehaviour.Projectile.ZoeaDeath;
			});
			Utilities.AddressableAddComp<ProjectileBehaviour>("RoR2/DLC1/VoidMegaCrab/VoidMegaCrabDeathBombProjectile.prefab", (Action<ProjectileBehaviour>)delegate(ProjectileBehaviour a)
			{
				a.projectile = ProjectileBehaviour.Projectile.ZoeaDeathChilder;
			});
			Utilities.AddressableAddComp<ProjectileBehaviour>("RoR2/DLC1/VoidMegaCrab/VoidMegaCrabDeathBombletsProjectile.prefab", (Action<ProjectileBehaviour>)delegate(ProjectileBehaviour a)
			{
				a.projectile = ProjectileBehaviour.Projectile.ZoeaDeath;
			});
			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/Base/Meteor/MeteorStorm.prefab", Equipment.Meteor);
			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/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;
			}, release: false);
			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/BoostedIceBoxIceCubeProjectile.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC2/Chef/ChefGlazeProjectile.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC2/Chef/ChefGlazeProjectileUtility.prefab", (SkillSlot)2);
			AddProcComponent("RoR2/DLC2/Chef/ChefGlazeProjectileUtilityIgnited.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC2/Chef/ChefGlazeProjectileUtilityFrozen.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC2/Chef/ChefImpactOilBoosted.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC2/Chef/ChefImpactOilBoostedFrozen.prefab", (SkillSlot)3);
			AddProcComponent("RoR2/DLC3/Drone Tech/CommandJailerDroneCage.prefab", (SkillSlot)1);
			AddProcComponent("RoR2/DLC3/Drone Tech/HaulerThrowProjectile.prefab", (SkillSlot)1);
			Utilities.DoAddressable("RoR2/Base/Common/MissileProjectile.prefab", DoMissilePrefab);
			DoElites();
		}

		private static void AddProcComponent(string addressable, Index index)
		{
			Utilities.AddressableAddComp<ProcComponent>(addressable, (Action<ProcComponent>)delegate(ProcComponent a)
			{
				a.index = index;
			});
		}

		private static void AddMinionComponent(string addressable, Index index)
		{
			Utilities.AddressableAddComp<MinionComponent>(addressable, (Action<MinionComponent>)delegate(MinionComponent a)
			{
				a.index = index;
			});
		}

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

		private static async void DoElites()
		{
			try
			{
				AsyncOperationHandle<GameObject>[] tasks = new AsyncOperationHandle<GameObject>[5]
				{
					Utilities.GetAddressableAsync("RoR2/Base/EliteLightning/LightningStake.prefab"),
					Utilities.GetAddressableAsync("RoR2/Base/Common/FireTrail.prefab"),
					Utilities.GetAddressableAsync("RoR2/DLC2/Elites/EliteBead/BeadProjectileTrackingBomb.prefab"),
					Utilities.GetAddressableAsync("RoR2/DLC2/Elites/EliteAurelionite/AffixAurelionitePreStrikeProjectile.prefab"),
					Utilities.GetAddressableAsync("RoR2/DLC2/Elites/EliteAurelionite/AffixAurelioniteCenterProjectile.prefab")
				};
				await Task.WhenAll(tasks.Select((AsyncOperationHandle<GameObject> a) => a.Task));
				DoDualElitePrefab(tasks[0].Result, Equipment.AffixBlue.equipmentIndex, out hhOverloading);
				DoDualElitePrefab(tasks[1].Result, Equipment.AffixRed.equipmentIndex, out hhFireTrail);
				DoDualElitePrefab(tasks[2].Result, Equipment.EliteBeadEquipment.equipmentIndex, out hhBead);
				DoDualElitePrefab(tasks[3].Result, Equipment.EliteAurelioniteEquipment.equipmentIndex, out hhGoldOuter);
				DoDualElitePrefab(tasks[4].Result, Equipment.EliteAurelioniteEquipment.equipmentIndex, out hhGoldInner);
			}
			catch (Exception data)
			{
				log.error(data);
			}
		}

		private static void DoDualElitePrefab(GameObject prefab, EquipmentIndex eliteIndex, out GameObject hhPrefab)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			prefab.AddComponent<ProcComponent>().index = eliteIndex;
			hhPrefab = Utilities.CreatePrefab(prefab);
			hhPrefab.GetComponent<ProcComponent>().index = Items.HeadHunter;
		}

		private void CollectLanguageRootFolders(List<string> list)
		{
			list.Add(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Language"));
		}
	}
	public readonly struct ProcChain : IEnumerable<Index>, IEnumerable
	{
		private readonly Index[] indexes;

		public Index source_index
		{
			get
			{
				Index[] array = indexes;
				if (array == null)
				{
					return default(Index);
				}
				return array[0];
			}
		}

		public bool isEmpty => indexes == null;

		public bool isNotEmpty => indexes != null;

		public ProcChain(Index index)
		{
			indexes = new Index[1] { index };
		}

		public ProcChain(Index index, ProcChain parent)
		{
			if (parent.indexes != null)
			{
				indexes = new Index[1 + parent.indexes.Length];
				for (int i = 0; i < parent.indexes.Length; i++)
				{
					indexes[1 + i] = parent.indexes[i];
				}
			}
			else
			{
				indexes = new Index[1];
			}
			indexes[0] = index;
		}

		public override string ToString()
		{
			if (indexes == null)
			{
				return string.Empty;
			}
			string text = indexes[0].ToString();
			for (int i = 1; i < indexes.Length; i++)
			{
				text = indexes[i].ToString() + " -> " + text;
			}
			return text;
		}

		public IEnumerator<Index> GetEnumerator()
		{
			return ((IEnumerable<Index>)(indexes ?? Array.Empty<Index>())).GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return (indexes ?? Array.Empty<Index>()).GetEnumerator();
		}
	}
	public class SourceInflictor
	{
		public readonly ProcChain source_chain;

		private bool hasHit;

		public SourceInflictor(Index index)
		{
			source_chain = new ProcChain(index);
		}

		public SourceInflictor(Index index, ProcChain parent_chain)
		{
			source_chain = new ProcChain(index, parent_chain);
		}

		internal void OnDamageInflictedServer(DamageReport damageReport)
		{
			if (!hasHit)
			{
				hasHit = true;
				if (source_chain.isNotEmpty && damageReport.attackerMaster.TryGetTrackedInventory(source_chain.source_index.type != IndexType.SkillSlot, out var trackedInventory))
				{
					trackedInventory.TryAddSuccess(source_chain.source_index);
				}
			}
		}

		public override string ToString()
		{
			return source_chain.ToString();
		}
	}
	public struct Tracker
	{
		private static class TooltipParser
		{
			private static readonly Regex tooltip_regex = new Regex("{([A-Z]+)\\(([A-Z]*)(\\?)?\\)}");

			private unsafe static Tracker* tracker;

			private unsafe static Totals* totals;

			private static bool ignore;

			internal unsafe static string Parse(in Tracker tracker, in Totals totals, string[] tooltips_unformatted)
			{
				fixed (Tracker* ptr = &tracker)
				{
					fixed (Totals* ptr2 = &totals)
					{
						TooltipParser.tracker = ptr;
						TooltipParser.totals = ptr2;
						ignore = false;
						string text = string.Empty;
						foreach (string input in tooltips_unformatted)
						{
							string text2 = tooltip_regex.Replace(input, Evaluator);
							if (!ignore)
							{
								text = ((text.Length <= 0) ? (text + text2) : (text + "\n" + text2));
							}
							else
							{
								ignore = false;
							}
						}
						return text;
					}
				}
			}

			private unsafe static string Evaluator(Match match)
			{
				var (trackedValue, num) = match.Groups[2].Value switch
				{
					"BLOCK" => ((tracker->flags & TrackerFlags.Damage) == 0) ? (tracker->v1, totals->damageTaken) : (tracker->v2, totals->damageTaken), 
					"DAMAGE" => (tracker->v1, totals->damageDealt), 
					"HEAL" => ((tracker->flags & TrackerFlags.Damage) == 0) ? (tracker->v1, totals->healed) : (tracker->v2, totals->healed), 
					"GOLD" => (tracker->v1, totals->goldEarned), 
					"COUNT" => (tracker->v2, 0f), 
					_ => (tracker->v2, 0f), 
				};
				if (match.Groups[3].Success && trackedValue.value.i == 0)
				{
					ignore = true;
					return string.Empty;
				}
				return match.Groups[1].Value switch
				{
					"INCREASE" => TrackerStatics.IncreaseToString(trackedValue.value.f, num - trackedValue.total_when_set.f), 
					"REDUCTION" => TrackerStatics.ReductionToString(trackedValue.value.f, num - trackedValue.total_when_set.f), 
					"PORTION" => TrackerStatics.PortionToString(trackedValue.value.f, num - trackedValue.total_when_set.f), 
					"CHANCE" => TrackerStatics.ChanceToString(trackedValue.total_when_set.i, trackedValue.value.i), 
					"RATE" => TrackerStatics.RateToString(trackedValue.total_when_set.i, trackedValue.value.i), 
					"COUNT" => trackedValue.value.i.ToString("n0"), 
					"VALUE" => trackedValue.value.f.ToString("n0"), 
					_ => "UNDEFINED:" + match.Value, 
				};
			}
		}

		private struct TrackedValue
		{
			internal num32 value;

			internal num32 total_when_set;
		}

		[StructLayout(LayoutKind.Explicit)]
		private struct num32
		{
			[FieldOffset(0)]
			internal uint i;

			[FieldOffset(0)]
			internal float f;

			public static implicit operator num32(uint i)
			{
				num32 result = default(num32);
				result.i = i;
				return result;
			}

			public static implicit operator num32(float f)
			{
				num32 result = default(num32);
				result.f = f;
				return result;
			}

			public static num32 operator +(num32 num, uint i)
			{
				num32 result = default(num32);
				result.i = num.i + i;
				return result;
			}

			public static num32 operator +(num32 num, float f)
			{
				num32 result = default(num32);
				result.f = num.f + f;
				return result;
			}
		}

		private TrackedValue v1;

		private TrackedValue v2;

		public TrackerFlags flags;

		public void AddDamage(float damage)
		{
			v1.value += damage;
			SetDirty();
		}

		public void AddHealing(float heal)
		{
			if ((flags & TrackerFlags.Damage) != 0)
			{
				v2.value += heal;
			}
			else
			{
				v1.value += heal;
			}
			SetDirty();
		}

		public void AddBlocked(float blocked)
		{
			if ((flags & TrackerFlags.Damage) != 0)
			{
				v2.value += blocked;
			}
			else
			{
				v1.value += blocked;
			}
			SetDirty();
		}

		public void AddGold(float gold)
		{
			v1.value += gold;
			SetDirty();
		}

		public void AddAttempt()
		{
			v2.total_when_set += 1u;
			SetDirty();
		}

		public void AddSuccess()
		{
			v2.value += 1u;
			SetDirty();
		}

		public void AddSuccess(uint count)
		{
			v2.value += count;
			SetDirty();
		}

		internal readonly string GetTooltip(in Totals totals, string[] tooltips_unformatted)
		{
			return TooltipParser.Parse(in this, in totals, tooltips_unformatted);
		}

		internal void Reset(in Totals totals)
		{
			v1.value = 0u;
			v2.value = 0u;
			if ((flags & TrackerFlags.Damage) != 0)
			{
				v1.total_when_set = totals.damageDealt;
			}
			else if ((flags & TrackerFlags.Gold) != 0)
			{
				v1.total_when_set = totals.goldEarned;
			}
			else if ((flags & (TrackerFlags.Block | TrackerFlags.Damage)) == TrackerFlags.Block)
			{
				v1.total_when_set = totals.damageTaken;
			}
			else if ((flags & (TrackerFlags.Damage | TrackerFlags.Heal)) == TrackerFlags.Heal)
			{
				v1.total_when_set = totals.healed;
			}
			else
			{
				v1.total_when_set = 0u;
			}
			if ((flags & (TrackerFlags.Block | TrackerFlags.Damage)) == (TrackerFlags.Block | TrackerFlags.Damage))
			{
				v2.total_when_set = totals.damageTaken;
			}
			else if ((flags & (TrackerFlags.Damage | TrackerFlags.Heal)) == (TrackerFlags.Damage | TrackerFlags.Heal))
			{
				v2.total_when_set = totals.healed;
			}
			else
			{
				v2.total_when_set = 0u;
			}
			if ((flags & TrackerFlags.Watch) != 0)
			{
				flags &= ~TrackerFlags.Watch;
			}
		}

		internal readonly void Serialize(SerializationBuffer data)
		{
			if ((flags & (TrackerFlags.Block | TrackerFlags.Damage | TrackerFlags.Gold | TrackerFlags.Heal)) != 0)
			{
				data.Add(v1.value.i);
			}
			if ((flags & (TrackerFlags.Attempt | TrackerFlags.Success)) != 0)
			{
				data.Add(v2.value.i);
				data.Add(v2.total_when_set.i);
			}
			else if ((int)(flags & (TrackerFlags.Block | TrackerFlags.Damage | TrackerFlags.Heal)) > 4)
			{
				data.Add(v2.value.i);
			}
		}

		internal void Deserialize(SerializationBuffer data)
		{
			if ((flags & (TrackerFlags.Block | TrackerFlags.Damage | TrackerFlags.Gold | TrackerFlags.Heal)) != 0)
			{
				v1.value = data.nextInt;
			}
			if ((flags & (TrackerFlags.Attempt | TrackerFlags.Success)) != 0)
			{
				v2.value = data.nextInt;
				v2.total_when_set = data.nextInt;
			}
			else if ((int)(flags & (TrackerFlags.Block | TrackerFlags.Damage | TrackerFlags.Heal)) > 4)
			{
				v2.value = data.nextInt;
			}
		}

		internal void HandleBrokenWatch(in Tracker former_watch)
		{
			AddDamage(former_watch.v1.value.f);
			if ((flags & TrackerFlags.Watch) == 0)
			{
				v1.total_when_set = former_watch.v1.total_when_set;
				flags |= TrackerFlags.Watch;
			}
		}

		private void SetDirty()
		{
			flags |= TrackerFlags.Dirty;
		}

		internal void UnDirty()
		{
			flags &= ~TrackerFlags.Dirty;
		}

		internal readonly bool IsDirty()
		{
			return (flags & TrackerFlags.Dirty) != 0;
		}

		internal static int CompareDamage(in Tracker a, in Tracker b, in Totals totals)
		{
			float num = a.v1.value.f / (totals.damageDealt - a.v1.total_when_set.f);
			float value = b.v1.value.f / (totals.damageDealt - b.v1.total_when_set.f);
			return num.CompareTo(value);
		}
	}
	[Serializable]
	public struct Totals
	{
		public static float allDamageDealt;

		public float damageDealt;

		public float damageTaken;

		public float healed;

		public uint goldEarned;

		static Totals()
		{
			Run.onRunStartGlobal += ResetGlobalDamage;
		}

		private static void ResetGlobalDamage(Run run)
		{
			allDamageDealt = 0f;
		}
	}
	public sealed class TrackedDef
	{
		private static readonly string tooltip_prefix = "ITEMSTATISTICS_TOOLTIPS_";

		public static readonly string damage_tooltip = tooltip_prefix + "DAMAGE";

		public static readonly string chance_tooltip = tooltip_prefix + "CHANCE";

		public static readonly string count_tooltip = tooltip_prefix + "COUNT";

		public static readonly string hit_tooltip = tooltip_prefix + "HIT";

		public static readonly string heal_tooltip = tooltip_prefix + "HEAL";

		public static readonly string heal_optional_tooltip = tooltip_prefix + "HEAL_OPTIONAL";

		public static readonly string gold_tooltip = tooltip_prefix + "GOLD";

		public static readonly string reduction_tooltip = tooltip_prefix + "REDUCTION";

		public static readonly string portion_tooltip = tooltip_prefix + "DAMAGEPORTION";

		public static readonly string portion_optional_tooltip = tooltip_prefix + "DAMAGEPORTION_OPTIONAL";

		public static readonly string recycled_tooltip = tooltip_prefix + "RECYCLED";

		public static readonly string barrier_gained_tooltip = tooltip_prefix + "BARRIERGAINED";

		public static readonly string total_crit_tooltip = tooltip_prefix + "CRITDAMAGE";

		public static readonly string stack_tooltip = tooltip_prefix + "STACK";

		public static readonly string stack_combat_tooltip = tooltip_prefix + "STACKCOMBAT";

		public static readonly string stack_hit_tooltip = tooltip_prefix + "STACKHIT";

		public static readonly string stack_hit_skill_tooltip = tooltip_prefix + "STACKHITSKILL";

		public static readonly string global_portion_tooltip = tooltip_prefix + "GLOBALPORTION";

		public static readonly string minion_portion_tooltip = tooltip_prefix + "MINIONPORTION";

		public static readonly string regen_portion_tooltip = tooltip_prefix + "REGENPORTION";

		public static readonly string barrier_blocked_tooltip = tooltip_prefix + "BARRIERBLOCKED";

		public static readonly string shield_blocked_tooltip = tooltip_prefix + "SHIELDBLOCKED";

		public static readonly string minion_body_portion_tooltip = tooltip_prefix + "MINIONBODYPORTION";

		public static readonly string sharedsuffering_tooltip = tooltip_prefix + "SHAREDSUFFERING";

		public static readonly TrackedDef ArmorCount = new TrackedDef(TrackerFlags.Block | TrackerFlags.Success, count_tooltip, reduction_tooltip);

		public static readonly TrackedDef ArmorCountChance = new TrackedDef(TrackerFlags.Block | TrackerFlags.Attempt, count_tooltip, chance_tooltip, reduction_tooltip);

		public static readonly TrackedDef ArmorChance = new TrackedDef(TrackerFlags.Block | TrackerFlags.Attempt, chance_tooltip, reduction_tooltip);

		public static readonly TrackedDef Armor = new TrackedDef(TrackerFlags.Block, reduction_tooltip);

		public static readonly TrackedDef Chance = new TrackedDef(TrackerFlags.Attempt, count_tooltip, chance_tooltip);

		public static readonly TrackedDef Count = new TrackedDef(TrackerFlags.Success, count_tooltip);

		public static readonly TrackedDef DamageChance = new TrackedDef(TrackerFlags.Damage | TrackerFlags.Attempt, chance_tooltip, damage_tooltip);

		public static readonly TrackedDef DamagePortionChance = new TrackedDef(TrackerFlags.Damage | TrackerFlags.Attempt, chance_tooltip, portion_tooltip);

		public static readonly TrackedDef DamagePortion = new TrackedDef(TrackerFlags.Damage, portion_tooltip);

		public static readonly TrackedDef Damage = new TrackedDef(TrackerFlags.Damage, damage_tooltip);

		public static readonly TrackedDef Gold = new TrackedDef(TrackerFlags.Gold, gold_tooltip);

		public static readonly TrackedDef Heal = new TrackedDef(TrackerFlags.Heal, heal_tooltip);

		public static readonly TrackedDef Skill = new TrackedDef(TrackerFlags.Damage | TrackerFlags.Heal, portion_optional_tooltip, heal_optional_tooltip);

		public static readonly TrackedDef Stack = new TrackedDef(TrackerFlags.Attempt, stack_tooltip);

		public static readonly TrackedDef StackCombat = new TrackedDef(TrackerFlags.Attempt, stack_combat_tooltip);

		public static readonly TrackedDef StackHit = new TrackedDef(TrackerFlags.Attempt, stack_hit_tooltip);

		public static readonly TrackedDef StackHitSkill = new TrackedDef(TrackerFlags.Attempt, stack_hit_skill_tooltip);

		internal static readonly TrackedDef MinionBody = new TrackedDef(TrackerFlags.Damage, minion_body_portion_tooltip);

		internal readonly TrackerFlags flags;

		private readonly string[] tooltip_tokens;

		public TrackedDef(TrackerFlags flags, params string[] tooltip_tokens)
		{
			if (flags == TrackerFlags.Undefined)
			{
				throw new ArgumentException("flags must be non-zero");
			}
			this.flags = flags;
			this.tooltip_tokens = tooltip_tokens ?? throw new ArgumentNullException("tooltip_tokens");
		}

		internal string[] GetTooltipsLanguaged()
		{
			string[] array = new string[tooltip_tokens.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = Language.GetString(tooltip_tokens[i]);
			}
			return array;
		}
	}
	[Flags]
	public enum TrackerFlags : byte
	{
		Undefined = 0,
		Block = 2,
		Damage = 4,
		Gold = 8,
		Heal = 0x10,
		Attempt = 0x20,
		Success = 0x40,
		Watch = 0x80,
		Dirty = 1
	}
	internal static class TrackerStatics
	{
		internal static string IncreaseToString(float value, float total)
		{
			if (total == 0f)
			{
				return "NaN";
			}
			if (value >= 0.999999f * total)
			{
				return "Max";
			}
			float num = ((!(value < 0f)) ? (100f / (1f - value / total) - 100f) : (100f * value / total));
			return num.ToString((num < 3f) ? "f1" : "f0") + "%";
		}

		internal static string ReductionToString(float value, float total)
		{
			if (total == 0f)
			{
				if (!(value > 0f))
				{
					return "NaN";
				}
				return "100%";
			}
			if (value <= -0.999999f * total)
			{
				return "Min";
			}
			float num = 100f - 100f / (1f + value / total);
			return num.ToString((num < 3f) ? "f1" : "f0") + "%";
		}

		internal static string PortionToString(float value, float total)
		{
			if (total == 0f)
			{
				return "NaN";
			}
			float num = 100f * value / total;
			return num.ToString((num < 3f) ? "f1" : "f0") + "%";
		}

		internal 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") + "%";
		}

		internal static string RateToString(uint attempted, uint succedded)
		{
			if (attempted == 0)
			{
				return "NaN";
			}
			float num = (float)succedded / (float)attempted;
			return num.ToString((num <= 1f) ? "f2" : ((num < 10f) ? "f1" : "f0"));
		}
	}
	public static class Utils
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static TrackedInventory GetTrackedInventory(this CharacterMaster master, bool includeFromMinion)
		{
			if (master == null)
			{
				return null;
			}
			if (includeFromMinion)
			{
				MinionOwnership minionOwnership = master.minionOwnership;
				if (((minionOwnership != null) ? minionOwnership.ownerMaster : null) != null)
				{
					return master.minionOwnership.ownerMaster.trackedInventory;
				}
			}
			return master.trackedInventory;
		}

		public static bool TryGetTrackedInventory(this CharacterMaster master, bool includeFromMinion, out TrackedInventory trackedInventory)
		{
			trackedInventory = master.GetTrackedInventory(includeFromMinion);
			return Object.op_Implicit((Object)(object)trackedInventory);
		}

		public static bool HasIndex(this Inventory inventory, Index index)
		{
			switch (index.type)
			{
			case IndexType.Item:
				return inventory.GetItemCountEffective((ItemIndex)index.index) > 0;
			case IndexType.Equip:
				return HasEquipment(inventory, (EquipmentIndex)index.index);
			case IndexType.SkillSlot:
				return true;
			case IndexType.Misc:
				return index.index > 0;
			case IndexType.Body:
				return true;
			default:
				log.warning($"Unknown index type {index.type} for HasIndex");
				return false;
			}
		}

		public static bool HasEquipment(Inventory inventory, EquipmentIndex index)
		{
			//IL_0016: 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)
			for (int i = 0; i < inventory._equipmentStateSlots.Length; i++)
			{
				for (int j = 0; j < inventory._equipmentStateSlots[i].Length; j++)
				{
					if (inventory._equipmentStateSlots[i][j].equipmentIndex == index)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static int GetIndexItemCount(this Inventory inventory, Index index)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			switch (index.type)
			{
			case IndexType.Item:
				return inventory.GetItemCountEffective((ItemIndex)index.index);
			case IndexType.Equip:
			{
				int num = 0;
				for (int i = 0; i < inventory._equipmentStateSlots.Length; i++)
				{
					for (int j = 0; j < inventory._equipmentStateSlots[i].Length; j++)
					{
						if ((int)inventory._equipmentStateSlots[i][j].equipmentIndex == index.index)
						{
							num++;
						}
					}
				}
				return num;
			}
			case IndexType.SkillSlot:
				return 1;
			case IndexType.Misc:
				return (index.index > 0) ? 1 : 0;
			case IndexType.Body:
				return 1;
			default:
				log.warning($"Unknown index type {index.type} for GetIndexItemCount");
				return 0;
			}
		}

		internal static float ArmorToDamage(CharacterBody body, float damage, float subtractArmor = 0f)
		{
			if (!Object.op_Implicit((Object)(object)body))
			{
				return 0f;
			}
			float num = body.armor + body.healthComponent.adaptiveArmorValue - subtractArmor;
			float num2 = ((num >= 0f) ? (1f - num / (num + 100f)) : (2f - 100f / (100f - num)));
			return Mathf.Max(1f, damage * num2 - (float)(5 * body.healthComponent.itemCounts.armorPlate));
		}

		internal static float GetDamageNoOverkill(this DamageReport damageReport)
		{
			return Mathf.Min(damageReport.damageDealt, damageReport.combinedHealthBeforeDamage);
		}

		internal static string Name(this ItemIndex index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			ItemDef itemDef = ItemCatalog.GetItemDef(index);
			if (itemDef != null)
			{
				return Language.GetString(itemDef.nameToken);
			}
			return "Item.null";
		}

		internal static string Name(this EquipmentIndex index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(index);
			if (equipmentDef != null)
			{
				return Language.GetString(equipmentDef.nameToken);
			}
			return "Equip.null";
		}

		internal static string Name(this BodyIndex index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			CharacterBody bodyPrefabBodyComponent = BodyCatalog.GetBodyPrefabBodyComponent(index);
			if (bodyPrefabBodyComponent != null)
			{
				return Language.GetString(bodyPrefabBodyComponent.baseNameToken);
			}
			if ((int)index == -1)
			{
				return "Body.None";
			}
			return "Body.null";
		}
	}
}
namespace ItemStatistics.Networking
{
	internal class BlastMessage
	{
		private readonly Index source_index;

		internal BlastAttackDamageInfo blastAttack;

		internal BlastMessage(in BlastAttackDamageInfo blastAttack)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			source_index = blastAttack.source_inflictor.source_chain.source_index;
			this.blastAttack = blastAttack;
		}

		internal BlastMessage(NetworkReader reader)
		{
			source_index = Index.Deserialize(reader);
			((BlastAttackDamageInfo)(ref blastAttack)).Read(reader);
			blastAttack.source_inflictor = new SourceInflictor(source_index);
		}

		internal static void Serialize(NetworkWriter writer, BlastMessage value)
		{
			Index.Serialize(writer, value.source_index);
			((BlastAttackDamageInfo)(ref value.blastAttack)).Write(writer);
		}

		internal static BlastMessage Deserialize(NetworkReader reader)
		{
			return new BlastMessage(reader);
		}
	}
	internal readonly struct BulletMessage
	{
		internal readonly Index source_index;

		internal readonly byte[] buffer;

		private readonly uint buffer_length;

		internal BulletMessage(NetworkWriter bullet_writer, BulletAttack attack)
		{
			source_index = attack.source_inflictor.source_chain.source_index;
			buffer = bullet_writer.m_Buffer.m_Buffer;
			buffer_length = bullet_writer.m_Buffer.Position;
		}

		public BulletMessage(NetworkReader reader)
		{
			source_index = Index.Deserialize(reader);
			buffer = reader.ReadBytesAndSize();
			buffer_length = (uint)buffer.Length;
		}

		internal static void Serialize(NetworkWriter writer, BulletMessage value)
		{
			Index.Serialize(writer, value.source_index);
			writer.WriteBytesAndSize(value.buffer, (int)value.buffer_length);
		}

		internal static BulletMessage Deserialize(NetworkReader reader)
		{
			return new BulletMessage(reader);
		}
	}
	[Hook]
	internal static class NetworkHooks
	{
		private delegate void BlastAttack_ClientReportDamage(in BlastAttackDamageInfo blastAttack);

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		internal readonly struct OverlapSourceContext : IDisposable
		{
			private static readonly Stack<Index> contexts = new Stack<Index>();

			internal static bool has_value
			{
				get
				{
					if (contexts.Count > 0)
					{
						return contexts.Peek().isNotNone;
					}
					return false;
				}
			}

			internal static Index current => contexts.Peek();

			public OverlapSourceContext(Index index)
			{
				contexts.Push(index);
			}

			public void Dispose()
			{
				contexts.Pop();
			}
		}

		internal static Action<NetworkReader, Index> modified_HandleBulletDamage;

		internal static Action<OverlapMessage> modified_HandleOverlapAttackHits;

		[Hook(typeof(BlastAttack), "ClientReportDamage")]
		private static void NetworkMessage_On_BlastAttack_ClientReportDamage(BlastAttack_ClientReportDamage orig, in BlastAttackDamageInfo blastAttack)
		{
			if (TrackModdedUsers.isModdedServer && blastAttack.source_inflictor != null)
			{
				TrackModdedUsers.localUser.CallCmdBlastAttack(new BlastMessage(in blastAttack));
			}
			else
			{
				orig(in blastAttack);
			}
		}

		[Hook]
		private static void GenerateBulletDealDamage()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0090: 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)
			//IL_00a3: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			DynamicMethodDefinition val = new DynamicMethodDefinition((MethodBase)HookManager.GetMethod(typeof(BulletAttack), "HandleBulletDamage"));
			try
			{
				((ParameterReference)((MethodReference)val.Definition).Parameters[0]).ParameterType = val.Module.ImportReference(typeof(NetworkReader));
				((MethodReference)val.Definition).Parameters.Add(new ParameterDefinition(val.Module.ImportReference(typeof(Index))));
				typeof(DynamicMethodDefinition).GetProperty("OriginalMethod").SetValue(val, null);
				ILContext val2 = new ILContext(val.Definition);
				try
				{
					ILCursor val3 = new ILCursor(val2);
					while (val3.TryGotoNext(new Func<Instruction, bool>[1]
					{
						(Instruction a) => ILPatternMatchingExt.MatchLdfld<NetworkMessage>(a, "reader")
					}))
					{
						val3.Remove();
					}
					val3.Index = 0;
					VariableDefinition infovar = ((IEnumerable<VariableDefinition>)val2.Body.Variables).First((VariableDefinition a) => ((MemberReference)((VariableReference)a).VariableType).Name == "DamageInfo");
					if (!val3.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
					{
						(Instruction a) => ILPatternMatchingExt.MatchStloc(a, ((VariableReference)infovar).Index)
					}))
					{
						val3.LogErrorCaller("bullet networking");
						return;
					}
					val3.Emit(OpCodes.Ldloc, infovar);
					val3.Emit(OpCodes.Ldarg_1);
					val3.Emit(OpCodes.Newobj, (MethodBase)typeof(SourceInflictor).GetConstructor(new Type[1] { typeof(Index) }));
					val3.Emit<DamageInfo>(OpCodes.Stfld, "source_inflictor");
				}
				finally
				{
					((IDisposable)val2)?.Dispose();
				}
				modified_HandleBulletDamage = Extensions.CreateDelegate<Action<NetworkReader, Index>>((MethodBase)val.Generate());
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		[Hook(typeof(BulletAttack), "DefaultHitCallbackImplementation")]
		private static void NetworkSource_IL_BulletAttack_DefaultHitCallbackImplementation(ILContext il)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			SourceHooks.PassSource_IL_Attack_OnArrival<DamageInfo>(il);
			if (modified_HandleBulletDamage == null)
			{
				log.error("failed to generate HandleBulletDamage, skipping bullet source networking");
				return;
			}
			ILCursor val = new ILCursor(il);
			ILLabel branch_end = 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 branch_end)
			}) || !val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt<NetworkWriter>(a, "FinishMessage")
			}))
			{
				val.LogErrorCaller("bullet source networking");
				return;
			}
			ILLabel val2 = val.MarkLabel();
			val.MoveBeforeLabels();
			val.Emit<TrackModdedUsers>(OpCodes.Ldsfld, "isModdedServer");
			val.Emit(OpCodes.Brfalse, (object)val2);
			val.Emit(OpCodes.Ldarg_0);
			val.Emit<BulletAttack>(OpCodes.Ldfld, "source_inflictor");
			val.Emit(OpCodes.Brfalse, (object)val2);
			val.Emit<BulletAttack>(OpCodes.Ldsfld, "messageWriter");
			val.Emit(OpCodes.Ldarg_0);
			val.EmitDelegate<Action<NetworkWriter, BulletAttack>>((Action<NetworkWriter, BulletAttack>)SendBulletMessage);
			val.Emit(OpCodes.Br, (object)branch_end);
			static void SendBulletMessage(NetworkWriter writer, BulletAttack attack)
			{
				TrackModdedUsers.localUser.CallCmdBulletAttack(new BulletMessage(writer, attack));
			}
		}

		[Hook]
		private static void GenerateOverlapDealDamage()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_0103: 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)
			DynamicMethodDefinition val = new DynamicMethodDefinition((MethodBase)HookManager.GetMethod(typeof(OverlapAttack), "HandleOverlapAttackHits"));
			try
			{
				((ParameterReference)((MethodReference)val.Definition).Parameters[0]).ParameterType = val.Module.ImportReference(typeof(OverlapMessage));
				typeof(DynamicMethodDefinition).GetProperty("OriginalMethod").SetValue(val, null);
				ILCont

plugins/ItemStatistics.Unsafe.dll

Decompiled 4 days ago
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace ItemStatistics;

public static class UnsafeUtils
{
	public unsafe static ref TValue GetValueRefOrNullRef<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
	{
		int num = dictionary.FindEntry(key);
		if (num >= 0)
		{
			return ref dictionary._entries[num].value;
		}
		return ref Unsafe.AsRef<TValue>((void*)null);
	}

	public static DictionaryRefEntries<TKey, TValue> GetRefEntries<TKey, TValue>(this Dictionary<TKey, TValue> dictionary)
	{
		return new DictionaryRefEntries<TKey, TValue>(dictionary);
	}

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public unsafe static bool IsNullRef<T>(in T value)
	{
		return Unsafe.AsPointer<T>(ref Unsafe.AsRef<T>(ref value)) == null;
	}
}
public ref struct DictionaryRefEntries<TKey, TValue>
{
	private readonly Dictionary<TKey, TValue> dictionary;

	private int current;

	public readonly ref TKey current_key => ref dictionary._entries[current - 1].key;

	public readonly ref TValue current_value => ref dictionary._entries[current - 1].value;

	public DictionaryRefEntries(Dictionary<TKey, TValue> dictionary)
	{
		this.dictionary = dictionary;
		current = 0;
	}

	public bool MoveNext()
	{
		while ((uint)current < (uint)dictionary._count)
		{
			if (dictionary._entries[current++].hashCode >= 0)
			{
				return true;
			}
		}
		current = dictionary._count - 1;
		return false;
	}
}

patchers/ItemStatisticsPatcher.dll

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

[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("0.0.0.0")]
public static class ItemStatisticsPatcher
{
	private static ManualLogSource _log;

	private static ManualLogSource log => _log ?? (_log = Logger.CreateLogSource("ItemStatisticsPatcher"));

	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_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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"));
		TypeReference fieldType3 = mainModule.ImportReference((TypeReference)(object)val.MainModule.GetType("ItemStatistics.SourceInflictor"));
		AddField(mainModule.GetType("RoR2.CharacterMaster"), fieldType, "trackedInventory").CustomAttributes.Add(new CustomAttribute(mainModule.ImportReference((MethodBase)typeof(NonSerializedAttribute).GetConstructor(Type.EmptyTypes))));
		AddField(mainModule.GetType("RoR2.DotController/DotStack"), val2, "source_chain");
		AddField(mainModule.GetType("RoR2.DotController/PendingDamage"), (TypeReference)(object)val3, "pendingDotChainList");
		AddField(mainModule.GetType("RoR2.DamageInfo"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.BlastAttack"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.BlastAttack/BlastAttackDamageInfo"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.BulletAttack"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.DelayBlast"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.OverlapAttack"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.GenericDamageOrb"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.DevilOrb"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.BounceOrb"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.HealOrb"), fieldType2, "source_index");
		AddField(mainModule.GetType("RoR2.Orbs.LightningOrb"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("RoR2.Orbs.VoidLightningOrb"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("EntityStates.Drone.DroneCopycat.LaserDiscOrb"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("EntityStates.Drone.Command.CommandBombardment/BombardmentOrb"), fieldType3, "source_inflictor");
		AddField(mainModule.GetType("EntityStates.FrozenState"), fieldType2, "freeze_source");
		AddField(mainModule.GetType("EntityStates.FrozenState"), (TypeReference)(object)mainModule.GetType("RoR2.CharacterMaster"), "freeze_master");
		AddField(mainModule.GetType("RoR2.Orbs.VineOrb/SplitDebuffInformation"), val2, "source_chain");
	}

	private static FieldDefinition AddField(TypeDefinition target, TypeReference fieldType, string fieldName)
	{
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected O, but got Unknown
		if (target == null || fieldType == null)
		{
			log.LogError((object)("Null types in AddField: " + ((target != null) ? ((MemberReference)target).Name : null) + "." + fieldName));
			return null;
		}
		TypeDefinition val = target;
		TypeReference baseType;
		do
		{
			if (((IEnumerable<FieldDefinition>)val.Fields).Any((FieldDefinition a) => ((MemberReference)a).Name == fieldName))
			{
				log.LogWarning((object)(((MemberReference)target).Name + "." + fieldName + " already exists"));
				return null;
			}
			baseType = val.BaseType;
		}
		while ((val = ((baseType != null) ? baseType.Resolve() : null)) != null);
		FieldDefinition val2 = new FieldDefinition(fieldName, (FieldAttributes)6, fieldType);
		target.Fields.Add(val2);
		return val2;
	}
}