Decompiled source of MoonstormSharedUtils v1.6.3

plugins/MoonstormSharedUtils.dll

Decompiled 5 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Events;
using HG;
using HG.Reflection;
using IL.RoR2;
using JetBrains.Annotations;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using Moonstorm;
using Moonstorm.AddressableAssets;
using Moonstorm.Components;
using Moonstorm.Config;
using Moonstorm.Loaders;
using On.RoR2;
using On.RoR2.Items;
using On.RoR2.UI;
using R2API;
using R2API.AddressReferencedAssets;
using R2API.ContentManagement;
using R2API.ScriptableObjects;
using RiskOfOptions;
using RiskOfOptions.Components.Panel;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Achievements;
using RoR2.Audio;
using RoR2.ContentManagement;
using RoR2.EntitlementManagement;
using RoR2.ExpansionManagement;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.UI;
using RoR2BepInExPack.VanillaFixes;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Moonstorm Shared Utils")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Moonstorm Shared Utils")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: OptIn]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace EntityStates.Events
{
	public sealed class DummyEventState : EventState
	{
	}
	public abstract class EventState : EntityState
	{
		[SerializeField]
		[Tooltip("The EventCard that triggers this EventState")]
		public EventCard eventCard;

		[SerializeField]
		[Tooltip("The minimum duration for this EventState")]
		public float minDuration = 30f;

		[SerializeField]
		[Tooltip("The maximum duration for this EventState")]
		public float maxDuration = 90f;

		[SerializeField]
		[Tooltip("The amount of time before the event officially starts")]
		public float warningDur = 10f;

		public virtual bool OverrideTimer => false;

		public bool HasWarned { get; protected set; }

		public float DiffScaledDuration { get; protected set; }

		public float DiffScalingValue { get; protected set; }

		public float TotalDuration { get; protected set; }

		public static event Action<EventCard> onEventStartGlobal;

		public static event Action<EventCard> onEventStartServer;

		public static event Action<EventCard> onEventEndGlobal;

		public static event Action<EventCard> onEventEndServer;

		public override void OnEnter()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			((EntityState)this).OnEnter();
			DiffScalingValue = DifficultyCatalog.GetDifficultyDef(Run.instance.selectedDifficulty).scalingValue;
			DiffScaledDuration = Util.Remap(DiffScalingValue, 1f, (float)MSUConfig.maxDifficultyScaling, minDuration, maxDuration);
			TotalDuration = DiffScaledDuration + warningDur;
			if (!eventCard.startMessageToken.Equals(string.Empty))
			{
				if ((bool)MSUConfig.eventAnnouncementsAsChatMessages)
				{
					Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
					{
						paramTokens = Array.Empty<string>(),
						baseToken = Util.GenerateColoredString(Language.GetString(eventCard.startMessageToken), Color32.op_Implicit(eventCard.messageColor))
					});
				}
				else
				{
					EventHelpers.AnnounceEvent(new EventHelpers.EventAnnounceInfo(eventCard, warningDur, isEventStart: true));
				}
			}
		}

		public override void FixedUpdate()
		{
			((EntityState)this).FixedUpdate();
			if (((EntityState)this).fixedAge >= TotalDuration && !OverrideTimer)
			{
				base.outer.SetNextStateToMain();
			}
			else if (!HasWarned && ((EntityState)this).fixedAge >= warningDur)
			{
				StartEvent();
			}
		}

		public override void OnExit()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			((EntityState)this).OnExit();
			if (!eventCard.startMessageToken.Equals(string.Empty))
			{
				if ((bool)MSUConfig.eventAnnouncementsAsChatMessages)
				{
					Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
					{
						paramTokens = Array.Empty<string>(),
						baseToken = Util.GenerateColoredString(Language.GetString(eventCard.endMessageToken), Color32.op_Implicit(eventCard.messageColor))
					});
				}
				else
				{
					EventHelpers.AnnounceEvent(new EventHelpers.EventAnnounceInfo(eventCard, warningDur, isEventStart: false));
				}
			}
			if (NetworkServer.active)
			{
				EventState.onEventEndServer?.Invoke(eventCard);
			}
			EventState.onEventEndGlobal?.Invoke(eventCard);
		}

		public virtual void StartEvent()
		{
			HasWarned = true;
			EventState.onEventStartGlobal?.Invoke(eventCard);
			if (NetworkServer.active)
			{
				EventState.onEventStartServer?.Invoke(eventCard);
			}
		}
	}
}
namespace Moonstorm
{
	[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
	public class ConfigurableFieldAttribute : SearchableAttribute
	{
		private string configFileIdentifier;

		public string ConfigSection { get; set; }

		public string ConfigName { get; set; }

		public string ConfigDesc { get; set; }

		public string ConfigFileIdentifier => configFileIdentifier;

		public FieldInfo Field => (FieldInfo)((SearchableAttribute)this).target;

		public ConfigEntryBase ConfigEntryBase { get; private set; }

		public ConfigurableFieldAttribute(string fileIdentifier = null)
		{
			configFileIdentifier = fileIdentifier;
		}

		public ConfigEntry<T> GetConfigEntry<T>()
		{
			try
			{
				return (ConfigEntryBase == null) ? null : ((ConfigEntry<T>)(object)ConfigEntryBase);
			}
			catch (Exception data)
			{
				LogLoader<MSULog>.Error(data, 73, "GetConfigEntry");
				return null;
			}
		}

		internal void ConfigureField<T>(ConfigFile configFile, T value)
		{
			ConfigEntryBase = (ConfigEntryBase)(object)configFile.Bind<T>(GetSection(), GetName(), value, GetDescription());
			GetConfigEntry<T>().SettingChanged += SettingChanged;
			SetValue(ConfigEntryBase.BoxedValue);
			OnConfigured(configFile, value);
		}

		protected virtual void OnConfigured(ConfigFile configFile, object value)
		{
		}

		private void SettingChanged(object sender, EventArgs e)
		{
			SetValue(ConfigEntryBase.BoxedValue);
		}

		private void SetValue(object boxedValue)
		{
			Field.SetValue(Field.DeclaringType, boxedValue);
		}

		private string GetSection()
		{
			Type declaringType = Field.DeclaringType;
			if (!string.IsNullOrEmpty(ConfigSection))
			{
				return ConfigSection;
			}
			return MSUtil.NicifyString(declaringType.Name);
		}

		private string GetName()
		{
			if (!string.IsNullOrEmpty(ConfigName))
			{
				return ConfigName;
			}
			return MSUtil.NicifyString(Field.Name);
		}

		private string GetDescription()
		{
			if (!string.IsNullOrEmpty(ConfigDesc))
			{
				return ConfigDesc;
			}
			return string.Empty;
		}
	}
	public class RooConfigurableFieldAttribute : ConfigurableFieldAttribute
	{
		public string OwnerGUID { get; internal set; }

		public string OwnerName { get; internal set; }

		protected override void OnConfigured(ConfigFile file, object value)
		{
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			bool num = ConfigSystem.configFilesWithSeparateRooEntries.Contains(file);
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file.ConfigFilePath);
			string text = (num ? (OwnerGUID + "." + fileNameWithoutExtension) : OwnerGUID);
			string text2 = (num ? (OwnerName + "." + fileNameWithoutExtension) : OwnerName);
			if (value == null)
			{
				return;
			}
			if (!(value is bool))
			{
				if (!(value is float))
				{
					if (!(value is int))
					{
						if (!(value is string))
						{
							if (!(value is Color))
							{
								if (!(value is Enum))
								{
									object obj;
									if ((obj = value) is KeyboardShortcut)
									{
										KeyboardShortcut val2 = (KeyboardShortcut)obj;
										ModSettingsManager.AddOption((BaseOption)new KeyBindOption(GetConfigEntry<KeyboardShortcut>()), text, text2);
									}
								}
								else
								{
									ModSettingsManager.AddOption((BaseOption)new ChoiceOption(base.ConfigEntryBase), text, text2);
								}
							}
							else
							{
								ModSettingsManager.AddOption((BaseOption)new ColorOption(GetConfigEntry<Color>()), text, text2);
							}
						}
						else
						{
							ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(GetConfigEntry<string>()), text, text2);
						}
					}
					else
					{
						ModSettingsManager.AddOption((BaseOption)new IntSliderOption(GetConfigEntry<int>()), text, text2);
					}
				}
				else
				{
					ModSettingsManager.AddOption((BaseOption)new SliderOption(GetConfigEntry<float>()), text, text2);
				}
			}
			else
			{
				ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(GetConfigEntry<bool>()), text, text2);
			}
		}

		public RooConfigurableFieldAttribute(string identifier = null)
			: base(identifier)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class DisabledContentAttribute : Attribute
	{
	}
	public enum StatTypes
	{
		Default,
		[Obsolete("Use MultiplyByN and set the extraData field to 100")]
		Percentage,
		[Obsolete("Use DivideByN and set the extraData field to 2")]
		DivideBy2,
		DivideByN,
		MultiplyByN,
		AddN,
		SubtractN,
		ModuloN
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
	public class TokenModifierAttribute : SearchableAttribute
	{
		public string langToken;

		public StatTypes statType;

		public int formatIndex;

		[Obsolete("Creating floats from strings is error prone, use \"operationData\" instead.")]
		public string extraData;

		public float operationData = float.NaN;

		private object valueForFormatting;

		public TokenModifierAttribute(string langToken, StatTypes statType, int formatIndex = 0)
		{
			this.langToken = langToken;
			this.statType = statType;
			this.formatIndex = formatIndex;
		}

		public TokenModifierAttribute(string langToken, StatTypes statType, int formatIndex = 0, string extraData = "")
		{
			this.langToken = langToken;
			this.statType = statType;
			this.formatIndex = formatIndex;
			operationData = float.Parse(extraData, CultureInfo.InvariantCulture);
		}

		public TokenModifierAttribute(string langToken, StatTypes statType, int formatIndex = 0, float operationData = 1f)
		{
			this.langToken = langToken;
			this.statType = statType;
			this.formatIndex = formatIndex;
			this.operationData = operationData;
		}

		internal object GetFormattingValue()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			object obj = null;
			if (((SearchableAttribute)this).target is FieldInfo fieldInfo)
			{
				obj = fieldInfo.GetValue(null);
			}
			else if (((SearchableAttribute)this).target is PropertyInfo propertyInfo)
			{
				obj = propertyInfo.GetMethod?.Invoke(null, null);
			}
			if (!Utility.IsNullOrWhiteSpace(extraData) && float.IsNaN(operationData))
			{
				operationData = float.Parse(extraData, CultureInfo.InvariantCulture);
				extraData = string.Empty;
			}
			Type type = obj.GetType();
			if (type.IsSubclassOf(typeof(ConfigurableVariable)))
			{
				obj = ((ConfigEntryBase)type.GetProperty("ConfigEntryBase", BindingFlags.Instance | BindingFlags.Public).GetGetMethod().Invoke(obj, null)).BoxedValue;
			}
			if (obj != null && IsNumber(obj))
			{
				switch (statType)
				{
				case StatTypes.Default:
					valueForFormatting = obj;
					return valueForFormatting;
				case StatTypes.Percentage:
					operationData = 100f;
					valueForFormatting = MultiplyByN(CastToFloat(obj));
					return valueForFormatting;
				case StatTypes.DivideBy2:
					operationData = 2f;
					valueForFormatting = DivideByN(CastToFloat(obj));
					return valueForFormatting;
				case StatTypes.MultiplyByN:
					valueForFormatting = (float.IsNaN(operationData) ? obj : MultiplyByN(CastToFloat(obj)));
					return valueForFormatting;
				case StatTypes.DivideByN:
					valueForFormatting = (float.IsNaN(operationData) ? obj : DivideByN(CastToFloat(obj)));
					return valueForFormatting;
				case StatTypes.AddN:
					valueForFormatting = (float.IsNaN(operationData) ? obj : AddN(CastToFloat(obj)));
					return valueForFormatting;
				case StatTypes.SubtractN:
					valueForFormatting = (float.IsNaN(operationData) ? obj : SubtractN(CastToFloat(obj)));
					return valueForFormatting;
				case StatTypes.ModuloN:
					valueForFormatting = (float.IsNaN(operationData) ? obj : ModuloN(CastToFloat(obj)));
					return valueForFormatting;
				}
			}
			else
			{
				LogLoader<MSULog>.Error(string.Format("The Field/Property {0}'s Type is not a number, the {1} attribute should only be used on fields/properties that are numbers!", ((SearchableAttribute)this).target, "TokenModifierAttribute"), 168, "GetFormattingValue");
			}
			return null;
		}

		private float CastToFloat(object obj)
		{
			return Convert.ToSingle(obj, CultureInfo.InvariantCulture);
		}

		private object MultiplyByN(float number)
		{
			float num = operationData;
			return number * num;
		}

		private object DivideByN(float number)
		{
			float num = operationData;
			return number / num;
		}

		private object AddN(float number)
		{
			float num = operationData;
			return number + num;
		}

		private object SubtractN(float number)
		{
			float num = operationData;
			return number - num;
		}

		private object ModuloN(float number)
		{
			float num = operationData;
			return number % num;
		}

		private static bool IsNumber(object value)
		{
			if (!(value is sbyte) && !(value is byte) && !(value is short) && !(value is ushort) && !(value is int) && !(value is uint) && !(value is long) && !(value is ulong) && !(value is float) && !(value is double))
			{
				return value is decimal;
			}
			return true;
		}
	}
	public static class ConfigSystem
	{
		private struct ManagedModData
		{
			public PluginInfo pluginInfo;

			public ConfigFile mainConfigFile;

			public Assembly tiedAssembly;

			public (MemberInfo, ConfigurableVariable)[] ConfigurableVariables;

			public ManagedModData(BaseUnityPlugin plugin, (MemberInfo, ConfigurableVariable)[] configurableVariables)
			{
				pluginInfo = plugin.Info;
				mainConfigFile = plugin.Config;
				tiedAssembly = ((object)plugin).GetType().Assembly;
				ConfigurableVariables = configurableVariables;
			}
		}

		private static readonly Dictionary<string, ManagedModData> assemblyNameToModData = new Dictionary<string, ManagedModData>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, ConfigFile> identifierToConfigFile = new Dictionary<string, ConfigFile>(StringComparer.OrdinalIgnoreCase);

		internal static HashSet<ConfigFile> configFilesWithSeparateRooEntries = new HashSet<ConfigFile>();

		private static bool initialized = false;

		public static void AddMod(BaseUnityPlugin baseUnityPlugin)
		{
			if (!initialized)
			{
				Assembly assembly = ((object)baseUnityPlugin).GetType().Assembly;
				if (!assemblyNameToModData.ContainsKey(assembly.FullName))
				{
					ManagedModData value = new ManagedModData(baseUnityPlugin, GetConfigurableVariables(assembly));
					assemblyNameToModData.Add(assembly.FullName, value);
					AddConfigFileAndIdentifier(value.pluginInfo.Metadata.GUID, value.mainConfigFile);
				}
			}
		}

		public static ConfigFile GetConfigFile(string identifier)
		{
			if (identifierToConfigFile.TryGetValue(identifier, out var value))
			{
				return value;
			}
			return null;
		}

		public static void AddConfigFileAndIdentifier(string identifier, ConfigFile configFile)
		{
			AddConfigFileAndIdentifier(identifier, configFile, createSeparateRooEntry: false);
		}

		public static void AddConfigFileAndIdentifier(string identifier, ConfigFile configFile, bool createSeparateRooEntry)
		{
			if (!initialized && !identifierToConfigFile.ContainsKey(identifier))
			{
				identifierToConfigFile.Add(identifier, configFile);
				if (createSeparateRooEntry)
				{
					configFilesWithSeparateRooEntries.Add(configFile);
				}
			}
		}

		[SystemInitializer(new Type[] { })]
		private static void Init()
		{
			initialized = true;
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(BindConfigs));
		}

		private static void BindConfigs()
		{
			BindConfigurableFieldAttributes();
			BindConfigurableVariables();
		}

		private static void BindConfigurableFieldAttributes()
		{
			List<ConfigurableFieldAttribute> list = new List<ConfigurableFieldAttribute>();
			SearchableAttribute.GetInstances<ConfigurableFieldAttribute>(list);
			LogLoader<MSULog>.Info($"Configuring a total of {list.Count} fields with ConfigurableFieldAttributes.", 145, "BindConfigurableFieldAttributes");
			foreach (ConfigurableFieldAttribute item in list)
			{
				try
				{
					FieldInfo field = item.Field;
					Type declaringType = field.DeclaringType;
					if (!TomlTypeConverter.CanConvert(field.FieldType))
					{
						throw new InvalidOperationException("ConfigurableField for " + declaringType.FullName + "." + field.Name + " cannot be configured as the Field's Type (" + field.FieldType.FullName + ") is not supported by BepInEx's TomlTypeConverter");
					}
					if (declaringType.GetCustomAttribute<DisabledContentAttribute>() == null)
					{
						string fullName = declaringType.Assembly.FullName;
						if (!assemblyNameToModData.ContainsKey(fullName))
						{
							throw new InvalidOperationException("ConfigurableField for " + declaringType.FullName + "." + field.Name + " cannot be configured as it's assembly is not in the ConfigSystem");
						}
						ConfigFile config2 = (Utility.IsNullOrWhiteSpace(item.ConfigFileIdentifier) ? assemblyNameToModData[fullName].mainConfigFile : GetConfigFile(item.ConfigFileIdentifier));
						if (item is RooConfigurableFieldAttribute rooConfigurableFieldAttribute)
						{
							PluginInfo pluginInfo = assemblyNameToModData[fullName].pluginInfo;
							rooConfigurableFieldAttribute.OwnerGUID = pluginInfo.Metadata.GUID;
							rooConfigurableFieldAttribute.OwnerName = pluginInfo.Metadata.Name;
						}
						ConfigureField(item, config2);
					}
				}
				catch (Exception arg)
				{
					LogLoader<MSULog>.Error($"Error while configuring {item.Field.DeclaringType.Name}.{item.Field.Name}\n{arg}", 181, "BindConfigurableFieldAttributes");
				}
			}
			static void ConfigureField(ConfigurableFieldAttribute attribute, ConfigFile config)
			{
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				//IL_016a: Unknown result type (might be due to invalid IL or missing references)
				//IL_017e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0183: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0197: Unknown result type (might be due to invalid IL or missing references)
				//IL_019c: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_02de: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
				object value = attribute.Field.GetValue(null);
				if (value != null)
				{
					if (value is string text)
					{
						string value2 = text;
						attribute.ConfigureField(config, value2);
						return;
					}
					if (value is bool flag)
					{
						bool value3 = flag;
						attribute.ConfigureField(config, value3);
						return;
					}
					if (value is byte b)
					{
						byte value4 = b;
						attribute.ConfigureField(config, value4);
						return;
					}
					if (value is sbyte b2)
					{
						sbyte value5 = b2;
						attribute.ConfigureField(config, value5);
						return;
					}
					if (value is short num)
					{
						short value6 = num;
						attribute.ConfigureField(config, value6);
						return;
					}
					if (value is ushort num2)
					{
						ushort value7 = num2;
						attribute.ConfigureField(config, value7);
						return;
					}
					if (value is int num3)
					{
						int value8 = num3;
						attribute.ConfigureField(config, value8);
						return;
					}
					if (value is uint num4)
					{
						uint value9 = num4;
						attribute.ConfigureField(config, value9);
						return;
					}
					if (value is long num5)
					{
						long value10 = num5;
						attribute.ConfigureField(config, value10);
						return;
					}
					if (value is ulong num6)
					{
						ulong value11 = num6;
						attribute.ConfigureField(config, value11);
						return;
					}
					if (value is float num7)
					{
						float value12 = num7;
						attribute.ConfigureField(config, value12);
						return;
					}
					if (value is double num8)
					{
						double value13 = num8;
						attribute.ConfigureField(config, value13);
						return;
					}
					if (value is decimal num9)
					{
						decimal value14 = num9;
						attribute.ConfigureField(config, value14);
						return;
					}
					if (value is Enum @enum)
					{
						Enum value15 = @enum;
						attribute.ConfigureField(config, value15);
						return;
					}
					if (value is Color val)
					{
						Color value16 = val;
						attribute.ConfigureField<Color>(config, value16);
						return;
					}
					if (value is Vector2 val2)
					{
						Vector2 value17 = val2;
						attribute.ConfigureField<Vector2>(config, value17);
						return;
					}
					if (value is Vector3 val3)
					{
						Vector3 value18 = val3;
						attribute.ConfigureField<Vector3>(config, value18);
						return;
					}
					if (value is Vector4 val4)
					{
						Vector4 value19 = val4;
						attribute.ConfigureField<Vector4>(config, value19);
						return;
					}
					if (value is Quaternion val5)
					{
						Quaternion value20 = val5;
						attribute.ConfigureField<Quaternion>(config, value20);
						return;
					}
					if (value is KeyboardShortcut val6)
					{
						KeyboardShortcut value21 = val6;
						attribute.ConfigureField<KeyboardShortcut>(config, value21);
						return;
					}
				}
				LogLoader<MSULog>.Error($"Due to the nature of the Config system in bepinex, MSU cannot bind a config of type {attribute.Field.FieldType}. If you see this, please create an issue on our github.", 209, "BindConfigurableFieldAttributes");
			}
		}

		private static void BindConfigurableVariables()
		{
			int num = 0;
			foreach (ManagedModData value in assemblyNameToModData.Values)
			{
				num += BindConfigurableVariablesForMod(value);
			}
			LogLoader<MSULog>.Info($"Configured a total of {num} ConfigurableVariables", 221, "BindConfigurableVariables");
		}

		private static int BindConfigurableVariablesForMod(ManagedModData data)
		{
			int num = 0;
			(MemberInfo, ConfigurableVariable)[] configurableVariables = data.ConfigurableVariables;
			for (int i = 0; i < configurableVariables.Length; i++)
			{
				var (memberInfo, configurableVariable) = configurableVariables[i];
				try
				{
					if (!configurableVariable.IsConfigured && configurableVariable.IsActuallyConfigurable)
					{
						if (configurableVariable.ConfigFile == null)
						{
							configurableVariable.ConfigFile = (Utility.IsNullOrWhiteSpace(configurableVariable.ConfigIdentifier) ? data.mainConfigFile : GetConfigFile(configurableVariable.ConfigIdentifier));
						}
						configurableVariable.Section = (Utility.IsNullOrWhiteSpace(configurableVariable.Section) ? MSUtil.NicifyString(memberInfo.DeclaringType.Name) : configurableVariable.Section);
						configurableVariable.Key = (Utility.IsNullOrWhiteSpace(configurableVariable.Key) ? MSUtil.NicifyString(memberInfo.Name) : configurableVariable.Key);
						configurableVariable.ModGUID = (Utility.IsNullOrWhiteSpace(configurableVariable.ModGUID) ? data.pluginInfo.Metadata.GUID : configurableVariable.ModGUID);
						configurableVariable.ModName = (Utility.IsNullOrWhiteSpace(configurableVariable.ModName) ? data.pluginInfo.Metadata.Name : configurableVariable.ModName);
						configurableVariable.Configure();
						num++;
					}
				}
				catch (Exception arg)
				{
					LogLoader<MSULog>.Error($"Error while trying to Configure the ConfigurableVariable for member: {memberInfo.DeclaringType.FullName}.{memberInfo.Name}\n{arg}", 252, "BindConfigurableVariablesForMod");
				}
			}
			return num;
		}

		private static (MemberInfo, ConfigurableVariable)[] GetConfigurableVariables(Assembly assembly)
		{
			MemberInfo[] source = assembly.GetTypesSafe().SelectMany((Type t) => t.GetMembers(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)).ToArray();
			FieldInfo[] array = source.OfType<FieldInfo>().ToArray();
			PropertyInfo[] array2 = source.OfType<PropertyInfo>().ToArray();
			ConfigurableVariable configurableVariable = null;
			List<(MemberInfo, ConfigurableVariable)> list = new List<(MemberInfo, ConfigurableVariable)>();
			FieldInfo[] array3 = array;
			foreach (FieldInfo fieldInfo in array3)
			{
				if (fieldInfo.FieldType.IsSubclassOf(typeof(ConfigurableVariable)))
				{
					configurableVariable = (ConfigurableVariable)fieldInfo.GetValue(null);
					list.Add((fieldInfo, configurableVariable));
				}
			}
			PropertyInfo[] array4 = array2;
			foreach (PropertyInfo propertyInfo in array4)
			{
				if (propertyInfo.PropertyType.IsSubclassOf(typeof(ConfigurableVariable)))
				{
					MethodInfo getMethod = propertyInfo.GetGetMethod();
					if (!(getMethod == null))
					{
						configurableVariable = (ConfigurableVariable)getMethod.Invoke(null, null);
						list.Add((propertyInfo, configurableVariable));
					}
				}
			}
			return list.ToArray();
		}
	}
	[Obsolete("Use Moonstorm.Config.ConfigSystem class instead")]
	public static class ConfigurableFieldManager
	{
		[Obsolete("Use ConfigSystem.AddMod() instead")]
		public static void AddMod(BaseUnityPlugin baseUnityPlugin)
		{
			ConfigSystem.AddMod(baseUnityPlugin);
		}

		[Obsolete("Use ConfigSystem.GetConfigFile() instead")]
		public static ConfigFile GetConfigFile(string configIdentifier)
		{
			return ConfigSystem.GetConfigFile(configIdentifier);
		}
	}
	public abstract class ArtifactBase : ContentBase
	{
		public abstract ArtifactDef ArtifactDef { get; }

		public virtual ArtifactCode ArtifactCode { get; }

		public abstract void OnArtifactDisabled();

		public abstract void OnArtifactEnabled();
	}
	public abstract class BuffBase : ContentBase
	{
		public abstract BuffDef BuffDef { get; }

		public virtual Material OverlayMaterial { get; }
	}
	public abstract class CharacterBase : ContentBase
	{
		public abstract GameObject BodyPrefab { get; }

		public abstract GameObject MasterPrefab { get; }

		public override void Initialize()
		{
			ModifyPrefab();
			Hook();
		}

		public virtual void ModifyPrefab()
		{
		}

		public virtual void Hook()
		{
		}
	}
	public abstract class ContentBase
	{
		public virtual void Initialize()
		{
		}
	}
	public abstract class DamageTypeBase : ContentBase
	{
		public abstract ModdedDamageType ModdedDamageType { get; protected set; }

		internal void SetDamageType(ModdedDamageType dt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			ModdedDamageType = dt;
		}

		public abstract void Delegates();
	}
	public abstract class EliteEquipmentBase : EquipmentBase
	{
		public abstract List<MSEliteDef> EliteDefs { get; }
	}
	public abstract class EliteTierDefBase : ContentBase
	{
		public abstract SerializableEliteTierDef SerializableEliteTierDef { get; }

		public abstract Func<EliteRules, bool> IsAvailable { get; }
	}
	public abstract class EquipmentBase : ContentBase
	{
		public abstract EquipmentDef EquipmentDef { get; }

		public virtual GameObject ItemDisplayPrefab { get; }

		public virtual void AddBehavior(ref CharacterBody body, int stack)
		{
		}

		public virtual bool FireAction(EquipmentSlot slot)
		{
			return false;
		}
	}
	public abstract class InteractableBase : ContentBase
	{
		public delegate bool IsAvailableForDCCSDelegate(StageInfo stageInfo);

		public abstract GameObject Interactable { get; }

		[Obsolete("Use the InteractableDirectorCards list instead.")]
		public virtual MSInteractableDirectorCard InteractableDirectorCard { get; }

		public virtual List<MSInteractableDirectorCard> InteractableDirectorCards { get; } = new List<MSInteractableDirectorCard>();


		public virtual IsAvailableForDCCSDelegate IsAvailableForDCCS { get; } = DefaultIsAvailable;


		private static bool DefaultIsAvailable(StageInfo stageInfo)
		{
			return true;
		}
	}
	public abstract class ItemBase : ContentBase
	{
		public abstract ItemDef ItemDef { get; }

		public virtual GameObject ItemDisplayPrefab { get; }
	}
	public abstract class ItemTierBase : ContentBase
	{
		public virtual SerializableColorCatalogEntry ColorIndex { get; }

		public virtual SerializableColorCatalogEntry DarkColorIndex { get; }

		public abstract ItemTierDef ItemTierDef { get; }

		public abstract GameObject PickupDisplayVFX { get; }

		public List<ItemIndex> ItemsWithThisTier { get; internal set; } = new List<ItemIndex>();


		public List<PickupIndex> AvailableTierDropList { get; internal set; } = new List<PickupIndex>();

	}
	public abstract class MonsterBase : CharacterBase
	{
		public delegate bool IsAvailableForDCCSDelegate(StageInfo stageInfo);

		[Obsolete("Use the MonsterDirectorCards list instead.")]
		public virtual MSMonsterDirectorCard MonsterDirectorCard { get; }

		public virtual List<MSMonsterDirectorCard> MonsterDirectorCards { get; } = new List<MSMonsterDirectorCard>();


		public virtual IsAvailableForDCCSDelegate IsAvailableForDCCS { get; } = DefaultIsAvailable;


		private static bool DefaultIsAvailable(StageInfo stageInfo)
		{
			return true;
		}
	}
	public abstract class ProjectileBase : ContentBase
	{
		public abstract GameObject ProjectilePrefab { get; }
	}
	public abstract class SceneBase : ContentBase
	{
		public abstract SceneDef SceneDef { get; }
	}
	public abstract class SurvivorBase : CharacterBase
	{
		public abstract SurvivorDef SurvivorDef { get; }
	}
	public abstract class UnlockableBase : ContentBase
	{
		public abstract MSUnlockableDef UnlockableDef { get; }

		public Type[] RequiredTypes { get; private set; } = Array.Empty<Type>();


		public AchievementDef GetAchievementDef => UnlockableDef.AchievementDef;

		protected void AddRequiredType<T>() where T : ContentBase
		{
			List<Type> list = RequiredTypes.ToList();
			list.Add(typeof(T));
			RequiredTypes = list.ToArray();
		}

		public virtual void OnCheckPassed()
		{
		}
	}
	public abstract class VoidItemBase : ItemBase
	{
		public abstract IEnumerable<ItemDef> LoadItemsToInfect();
	}
	internal static class ContentManagerSystem
	{
		[SystemInitializer(new Type[]
		{
			typeof(BodyCatalog),
			typeof(ItemCatalog),
			typeof(EquipmentCatalog),
			typeof(BuffCatalog)
		})]
		private static void SystemInit()
		{
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			LogLoader<MSULog>.Info("Initializing Content Manager System...", 14, "SystemInit");
			for (int i = 0; i < BodyCatalog.bodyPrefabs.Length; i++)
			{
				try
				{
					GameObject val = BodyCatalog.bodyPrefabs[i];
					MoonstormContentManager moonstormContentManager = val.AddComponent<MoonstormContentManager>();
					moonstormContentManager.body = val.GetComponent<CharacterBody>();
					ModelLocator component = val.GetComponent<ModelLocator>();
					if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.modelTransform) && Object.op_Implicit((Object)(object)((Component)component.modelTransform).GetComponent<CharacterModel>()))
					{
						MoonstormEliteBehavior moonstormEliteBehavior = val.AddComponent<MoonstormEliteBehavior>();
						moonstormEliteBehavior.characterModel = ((Component)component.modelTransform).GetComponent<CharacterModel>();
						moonstormEliteBehavior.body = val.GetComponent<CharacterBody>();
						moonstormContentManager.eliteBehavior = moonstormEliteBehavior;
						BodyCatalog.bodyPrefabs[i] = val;
					}
				}
				catch (Exception data)
				{
					LogLoader<MSULog>.Error(data, 41, "SystemInit");
				}
			}
			CharacterBody.onBodyStartGlobal += OnBodyStart;
			if (MSUtil.HolyDLLInstalled)
			{
				CharacterBody.RecalculateStats += new hook_RecalculateStats(HolyfiedRecalculateStats);
				RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(HolyfiedGetStatCoefficients);
			}
			else
			{
				CharacterBody.RecalculateStats += new hook_RecalculateStats(OnRecaluclateStats);
				RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(OnGetStatCoefficients);
			}
		}

		private static void OnBodyStart(CharacterBody body)
		{
			MoonstormContentManager component = ((Component)body).GetComponent<MoonstormContentManager>();
			if (Object.op_Implicit((Object)(object)component))
			{
				if (Object.op_Implicit((Object)(object)body.master))
				{
					component.hasMaster = true;
				}
				component.StartGetInterfaces();
			}
		}

		private static void OnRecaluclateStats(orig_RecalculateStats orig, CharacterBody self)
		{
			MoonstormContentManager component = ((Component)self).GetComponent<MoonstormContentManager>();
			component.AsValidOrNull<MoonstormContentManager>()?.RunStatRecalculationsStart();
			orig.Invoke(self);
			component.AsValidOrNull<MoonstormContentManager>()?.RunStatRecalculationsEnd();
		}

		private static void HolyfiedRecalculateStats(orig_RecalculateStats orig, CharacterBody self)
		{
			orig.Invoke(self);
			((Component)self).GetComponent<MoonstormContentManager>().AsValidOrNull<MoonstormContentManager>()?.RunStatRecalculationsEnd();
		}

		private static void OnGetStatCoefficients(CharacterBody sender, StatHookEventArgs args)
		{
			((Component)sender).GetComponent<MoonstormContentManager>().AsValidOrNull<MoonstormContentManager>()?.RunStatHookEventModifiers(args);
		}

		private static void HolyfiedGetStatCoefficients(CharacterBody sender, StatHookEventArgs args)
		{
			MoonstormContentManager component = ((Component)sender).GetComponent<MoonstormContentManager>();
			component.AsValidOrNull<MoonstormContentManager>()?.RunStatRecalculationsStart();
			component.AsValidOrNull<MoonstormContentManager>()?.RunStatHookEventModifiers(args);
		}
	}
	public static class EventCatalog
	{
		private static EventDirectorCategorySelection[] categories = Array.Empty<EventDirectorCategorySelection>();

		private static EventDirectorCategorySelection[] registeredCategories = Array.Empty<EventDirectorCategorySelection>();

		private static EventCard[] eventCards = Array.Empty<EventCard>();

		private static EventCard[] registeredEventCards = Array.Empty<EventCard>();

		private static readonly Dictionary<string, EventIndex> nameToEventIndex = new Dictionary<string, EventIndex>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, int> nameToCategoryIndex = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<Stage, EventDirectorCategorySelection> stageToCategory = new Dictionary<Stage, EventDirectorCategorySelection>();

		private static readonly Dictionary<string, EventDirectorCategorySelection> baseSceneNameToCategory = new Dictionary<string, EventDirectorCategorySelection>(StringComparer.OrdinalIgnoreCase);

		public static ResourceAvailability resourceAvailability = default(ResourceAvailability);

		private static bool initialized = false;

		public static int RegisteredCategoriesCount => registeredCategories.Length;

		public static int RegisteredEventCount => registeredEventCards.Length;

		public static EventIndex FindEventIndex(string eventName)
		{
			if (!initialized)
			{
				throw new InvalidOperationException("EventCatalog not initialized");
			}
			if (nameToEventIndex.TryGetValue(eventName.ToLowerInvariant(), out var value))
			{
				return value;
			}
			return EventIndex.None;
		}

		public static EventCard GetEventCard(EventIndex eventIndex)
		{
			if (!initialized)
			{
				throw new InvalidOperationException("EventCatalog not initialized");
			}
			return ArrayUtils.GetSafe<EventCard>(registeredEventCards, (int)eventIndex);
		}

		public static int FindCategorySelectionIndex(string name)
		{
			if (!initialized)
			{
				throw new InvalidOperationException("EventCatalog not initialized");
			}
			if (nameToCategoryIndex.TryGetValue(name.ToLowerInvariant(), out var value))
			{
				return value;
			}
			return -1;
		}

		public static EventDirectorCategorySelection GetCategorySelection(int categoryIndex)
		{
			if (!initialized)
			{
				throw new InvalidOperationException("EventCatalog not initialized");
			}
			return ArrayUtils.GetSafe<EventDirectorCategorySelection>(registeredCategories, categoryIndex);
		}

		public static EventDirectorCategorySelection GetCategoryFromCurrentStage(Stage stage, string customName = null)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!initialized)
				{
					throw new InvalidOperationException("EventCatalog not initialized");
				}
				if ((int)stage == 1)
				{
					if (string.IsNullOrEmpty(customName))
					{
						return null;
					}
					customName = customName.ToLowerInvariant();
					if (baseSceneNameToCategory.TryGetValue(customName.ToLowerInvariant(), out var value))
					{
						return value;
					}
					return null;
				}
				if (stageToCategory.TryGetValue(stage, out var value2))
				{
					return value2;
				}
				return null;
			}
			catch (Exception data)
			{
				LogLoader<MSULog>.Error(data, 141, "GetCategoryFromCurrentStage");
				return null;
			}
		}

		public static EventDirectorCategorySelection GetCategoryFromSceneDef(SceneDef sceneDef)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!initialized)
				{
					throw new InvalidOperationException("EventCatalog not initialized");
				}
				Stage stageEnumFromSceneDef = DirectorAPI.GetStageEnumFromSceneDef(sceneDef);
				if ((int)stageEnumFromSceneDef == 1)
				{
					string key = sceneDef.baseSceneName.ToLowerInvariant();
					if (baseSceneNameToCategory.TryGetValue(key, out var value))
					{
						return value;
					}
					LogLoader<MSULog>.Warning($"Scene {sceneDef} not found in the baseSceneNameToCategory dictionary.", 166, "GetCategoryFromSceneDef");
					return null;
				}
				return stageToCategory[stageEnumFromSceneDef];
			}
			catch (Exception data)
			{
				LogLoader<MSULog>.Error(data, 173, "GetCategoryFromSceneDef");
				return null;
			}
		}

		public static void AddCards(EventCard[] cards)
		{
			if (initialized)
			{
				throw new InvalidOperationException("EventCatalog already initialized");
			}
			cards.ToList().ForEach(delegate(EventCard card)
			{
				AddCard(card);
			});
		}

		public static void AddCard(EventCard card)
		{
			if (initialized)
			{
				throw new InvalidOperationException("EventCatalog already initialized");
			}
			ArrayUtils.ArrayAppend<EventCard>(ref eventCards, ref card);
		}

		public static void AddCategories(EventDirectorCategorySelection[] categories)
		{
			if (initialized)
			{
				throw new InvalidOperationException("EventCatalog already initialized");
			}
			categories.ToList().ForEach(delegate(EventDirectorCategorySelection category)
			{
				AddCategory(category);
			});
		}

		public static void AddCategory(EventDirectorCategorySelection category)
		{
			if (initialized)
			{
				throw new InvalidOperationException("EventCatalog already initialized");
			}
			ArrayUtils.ArrayAppend<EventDirectorCategorySelection>(ref categories, ref category);
		}

		[SystemInitializer(new Type[]
		{
			typeof(SceneCatalog),
			typeof(EntityStateCatalog)
		})]
		private static void Init()
		{
			AddCategories(MoonstormSharedUtils.MSUAssetBundle.LoadAllAssets<EventDirectorCategorySelection>());
			nameToEventIndex.Clear();
			stageToCategory.Clear();
			baseSceneNameToCategory.Clear();
			categories = categories.OrderBy((EventDirectorCategorySelection so) => ((Object)so).name).ToArray();
			eventCards = eventCards.OrderBy((EventCard so) => ((Object)so).name).ToArray();
			registeredCategories = RegisterCategories(categories).ToArray();
			categories = null;
			registeredEventCards = RegisterEventCards(eventCards).ToArray();
			eventCards = null;
			initialized = true;
			((ResourceAvailability)(ref resourceAvailability)).MakeAvailable();
		}

		private static List<EventDirectorCategorySelection> RegisterCategories(EventDirectorCategorySelection[] eventDirectorCategorySelections)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			List<EventDirectorCategorySelection> list = new List<EventDirectorCategorySelection>();
			for (int i = 0; i < eventDirectorCategorySelections.Length; i++)
			{
				try
				{
					EventDirectorCategorySelection eventDirectorCategorySelection = eventDirectorCategorySelections[i];
					bool? flag = null;
					if (HasMultipleFlags(eventDirectorCategorySelection.stage))
					{
						continue;
					}
					if ((int)eventDirectorCategorySelection.stage == 1)
					{
						flag = true;
						if (!baseSceneNameToCategory.ContainsKey(eventDirectorCategorySelection.stageName.ToLowerInvariant()))
						{
							goto IL_0078;
						}
					}
					else
					{
						flag = false;
						if (!stageToCategory.ContainsKey(eventDirectorCategorySelection.stage))
						{
							goto IL_0078;
						}
					}
					goto end_IL_000e;
					IL_0078:
					if (IsCategorySelectionValid(eventDirectorCategorySelection) && flag.HasValue)
					{
						if (flag == true)
						{
							baseSceneNameToCategory.Add(eventDirectorCategorySelection.stageName.ToLowerInvariant(), eventDirectorCategorySelection);
						}
						else if (flag == false)
						{
							stageToCategory.Add(eventDirectorCategorySelection.stage, eventDirectorCategorySelection);
						}
						nameToCategoryIndex.Add(((Object)eventDirectorCategorySelection).name.ToLowerInvariant(), i);
						list.Add(eventDirectorCategorySelection);
					}
					end_IL_000e:;
				}
				catch (Exception data)
				{
					LogLoader<MSULog>.Error(data, 325, "RegisterCategories");
				}
			}
			return list;
		}

		private static List<EventCard> RegisterEventCards(EventCard[] eventCards)
		{
			List<EventCard> list = new List<EventCard>();
			for (int i = 0; i < eventCards.Length; i++)
			{
				try
				{
					EventCard eventCard = eventCards[i];
					if (!(eventCard.selectionWeight <= 0f) && eventCard.cost > 0 && !(((SerializableEntityStateType)(ref eventCard.eventState)).stateType == null) && ((SerializableEntityStateType)(ref eventCard.eventState)).stateType.IsSubclassOf(typeof(EventState)))
					{
						list.Add(eventCard);
					}
				}
				catch (Exception data)
				{
					LogLoader<MSULog>.Error(data, 380, "RegisterEventCards");
				}
			}
			int num = list.ToArray().Length;
			for (EventIndex eventIndex = (EventIndex)0; (int)eventIndex < num; eventIndex++)
			{
				try
				{
					RegisterCard(list[(int)eventIndex], eventIndex);
					AddCardToCategories(list[(int)eventIndex]);
				}
				catch (Exception data2)
				{
					LogLoader<MSULog>.Error(data2, 394, "RegisterEventCards");
				}
			}
			return list;
		}

		private static void RegisterCard(EventCard card, EventIndex index)
		{
			card.EventIndex = index;
			nameToEventIndex.Add(((Object)card).name.ToLowerInvariant(), index);
		}

		private static void AddCardToCategories(EventCard card)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			foreach (Stage value in Enum.GetValues(typeof(Stage)))
			{
				if (((Enum)card.availableStages).HasFlag((Enum)(object)value))
				{
					if ((int)value == 1)
					{
						AddCardToCustomStages(card);
					}
					else
					{
						AddCardToStage(card, value);
					}
				}
			}
		}

		private static void AddCardToCustomStages(EventCard card)
		{
			foreach (string customStageName in card.customStageNames)
			{
				if (baseSceneNameToCategory.TryGetValue(customStageName.ToLowerInvariant(), out var value))
				{
					int num = value.FindCategoryIndexByName(card.category.ToLowerInvariant());
					if (num != -1)
					{
						value.AddCard(num, card);
					}
				}
			}
		}

		private static void AddCardToStage(EventCard card, Stage stage)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (stageToCategory.TryGetValue(stage, out var value))
			{
				int num = value.FindCategoryIndexByName(card.category.ToLowerInvariant());
				if (num != -1)
				{
					value.AddCard(num, card);
				}
			}
		}

		private static bool IsCategorySelectionValid(EventDirectorCategorySelection categorySelection)
		{
			for (int i = 0; i < categorySelection.categories.Length; i++)
			{
				EventDirectorCategorySelection.EventCategory eventCategory = categorySelection.categories[i];
				if (eventCategory.selectionWeight <= 0f)
				{
					LogLoader<MSULog>.Error($"{eventCategory.categoryName} in {categorySelection} has no weight!", 480, "IsCategorySelectionValid");
					return false;
				}
			}
			return true;
		}

		private static bool HasMultipleFlags(Stage stage)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			int num = -1;
			foreach (Stage value in Enum.GetValues(typeof(Stage)))
			{
				if (((Enum)stage).HasFlag((Enum)(object)value))
				{
					num++;
				}
			}
			if (num > -1)
			{
				return num >= 1;
			}
			return true;
		}
	}
	[Flags]
	public enum EventFlags : uint
	{
		[Obsolete("Set your EventCard's \"Required State Machine\" to \"Weather\"")]
		WeatherRelated = 1u,
		AfterVoidFields = 2u,
		AfterLoop = 4u,
		EnemySpawn = 8u,
		OncePerRun = 0x10u
	}
	public static class EventHelpers
	{
		public struct EventAnnounceInfo
		{
			public EventCard card;

			public float eventWarningDuration;

			public bool isEventStart;

			public bool fadeOnStart;

			public EventAnnounceInfo(EventCard card, float warningDuration, bool isEventStart)
			{
				this.card = card;
				eventWarningDuration = warningDuration;
				this.isEventStart = isEventStart;
				fadeOnStart = true;
			}
		}

		private static GameObject EventAnnouncer = MoonstormSharedUtils.MSUAssetBundle.LoadAsset<GameObject>("EventAnnouncer");

		private static HUD hudInstance;

		[SystemInitializer(new Type[] { typeof(EventCatalog) })]
		private static void SystemInit()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			HUD.Awake += new hook_Awake(GetHUD);
			MSUConfig.eventMessageFontSize.OnConfigChanged += delegate(float f)
			{
				HGTextMeshProUGUI component = EventAnnouncer.GetComponent<HGTextMeshProUGUI>();
				((TMP_Text)component).fontSize = f;
				((TMP_Text)component).fontSizeMax = f;
			};
			MSUConfig.familyEventUsesEventAnnouncementInsteadOfChatMessage.OnConfigChanged += delegate(bool val)
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Expected O, but got Unknown
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Expected O, but got Unknown
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Expected O, but got Unknown
				if (val)
				{
					ClassicStageInfo.BroadcastFamilySelection -= new hook_BroadcastFamilySelection(ShowAnnouncement);
					ClassicStageInfo.BroadcastFamilySelection += new hook_BroadcastFamilySelection(ShowAnnouncement);
				}
				else
				{
					ClassicStageInfo.BroadcastFamilySelection -= new hook_BroadcastFamilySelection(ShowAnnouncement);
				}
			};
		}

		private static void GetHUD(orig_Awake orig, HUD self)
		{
			orig.Invoke(self);
			hudInstance = self;
		}

		private static IEnumerator ShowAnnouncement(orig_BroadcastFamilySelection orig, ClassicStageInfo self, string familySelectionChatString)
		{
			GameObject instance = AnnounceFamilyEvent(familySelectionChatString, Color.white, 9f);
			if (Object.op_Implicit((Object)(object)instance))
			{
				yield return (object)new WaitForSeconds(4f);
				instance.transform.SetParent(hudInstance.mainContainer.transform, false);
				instance.GetComponent<RectTransform>().anchoredPosition = Vector2.op_Implicit(new Vector3((float)MSUConfig.eventMessageXOffset, (float)MSUConfig.eventMessageYOffset));
				instance.GetComponent<EventTextController>().BeginFade();
			}
			else
			{
				orig.Invoke(self, familySelectionChatString);
			}
		}

		public static GameObject AnnounceEvent(EventAnnounceInfo announceInfo)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Object.Instantiate<GameObject>(EventAnnouncer, hudInstance.mainContainer.transform, false);
			obj.GetComponent<RectTransform>().anchoredPosition = Vector2.op_Implicit(new Vector3((float)MSUConfig.eventMessageXOffset, (float)MSUConfig.eventMessageYOffset));
			HGTextMeshProUGUI component = obj.GetComponent<HGTextMeshProUGUI>();
			string text = (announceInfo.isEventStart ? announceInfo.card.startMessageToken : announceInfo.card.endMessageToken);
			Color messageColor = announceInfo.card.messageColor;
			((TMP_Text)component).text = Language.GetString(text);
			((Graphic)component).color = messageColor;
			((TMP_Text)component).outlineColor = GetOutlineColor(messageColor);
			((TMP_Text)component).autoSizeTextContainer = false;
			((Behaviour)component).enabled = true;
			EventTextController component2 = obj.GetComponent<EventTextController>();
			component2.warningDuration = (announceInfo.isEventStart ? announceInfo.eventWarningDuration : (announceInfo.eventWarningDuration / 2f));
			component2.fadeOnStart = announceInfo.fadeOnStart;
			return obj;
		}

		private static GameObject AnnounceFamilyEvent(string token, Color color, float duration)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = null;
			try
			{
				val = Object.Instantiate<GameObject>(EventAnnouncer);
				HGTextMeshProUGUI component = val.GetComponent<HGTextMeshProUGUI>();
				string[] array = Language.GetString(token).Split(new char[1] { ']' });
				((TMP_Text)component).text = array[0] + "]\n" + array[1];
				((Graphic)component).color = color;
				((TMP_Text)component).outlineColor = GetOutlineColor(color);
				((TMP_Text)component).autoSizeTextContainer = false;
				EventTextController component2 = val.GetComponent<EventTextController>();
				component2.warningDuration = duration;
				component2.fadeOnStart = false;
				return val;
			}
			catch (Exception arg)
			{
				LogLoader<MSULog>.Error($"Cannot announce FamilyEvent! reason: {arg}", 149, "AnnounceFamilyEvent");
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
				return null;
			}
		}

		private static Color32 GetOutlineColor(Color messageColor)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(messageColor, ref num, ref num2, ref num3);
			if ((double)num3 > 0.5)
			{
				float num4 = Mathf.Clamp01(num2 - 0.5f);
				float num5 = Mathf.Clamp01(num3 - 0.5f);
				return Color32.op_Implicit(Color.HSVToRGB(num, num4, num5));
			}
			float num6 = Mathf.Clamp01(num2 + 0.5f);
			float num7 = Mathf.Clamp01(num3 + 0.5f);
			return Color32.op_Implicit(Color.HSVToRGB(num, num6, num7));
		}
	}
	public enum EventIndex
	{
		None = -1
	}
	public static class VanillaEventDirectorCategorySelections
	{
		public static EventDirectorCategorySelection AbandonedAqueduct { get; } = Load("AbandonedAqueduct");


		public static EventDirectorCategorySelection AbyssalDepths { get; } = Load("AbyssalDepths");


		public static EventDirectorCategorySelection AphelianSanctuary { get; } = Load("AphelianSanctuary");


		public static EventDirectorCategorySelection ArtifactReliquary { get; } = Load("ArtifactReliquary");


		public static EventDirectorCategorySelection Commencement { get; } = Load("Commencement");


		public static EventDirectorCategorySelection DistantRoost { get; } = Load("DistantRoost");


		public static EventDirectorCategorySelection RallypointDelta { get; } = Load("RallypointDelta");


		public static EventDirectorCategorySelection ScorchedAcres { get; } = Load("ScorchedAcres");


		public static EventDirectorCategorySelection SiphonedForest { get; } = Load("SiphonedForest");


		public static EventDirectorCategorySelection SirensCall { get; } = Load("SirensCall");


		public static EventDirectorCategorySelection SkyMeadow { get; } = Load("SkyMeadow");


		public static EventDirectorCategorySelection SulphurPools { get; } = Load("SulphurPools");


		public static EventDirectorCategorySelection SunderedGrove { get; } = Load("SunderedGrove");


		public static EventDirectorCategorySelection ThePlanetarium { get; } = Load("ThePlanetarium");


		public static EventDirectorCategorySelection VoidCell { get; } = Load("VoidCell");


		public static EventDirectorCategorySelection VoidLocus { get; } = Load("VoidLocus");


		public static EventDirectorCategorySelection WetlandAspect { get; } = Load("WetlandAspect");


		public static EventDirectorCategorySelection TitanicPlains { get; } = Load("TitanicPlains");


		public static EventDirectorCategorySelection GildedCoast { get; } = Load("GildedCoast");


		public static EventDirectorCategorySelection AbandonedAqueductSimulacrum { get; } = Load("AbandonedAqueductSimulacrum");


		public static EventDirectorCategorySelection AbyssalDepthsSimulacrum { get; } = Load("AbyssalDepthsSimulacrum");


		public static EventDirectorCategorySelection AphelianSanctuarySimulacrum { get; } = Load("AphelianSanctuarySimulacrum");


		public static EventDirectorCategorySelection CommencementSimulacrum { get; } = Load("CommencementSimulacrum");


		public static EventDirectorCategorySelection RallypointDeltaSimulacrum { get; } = Load("RallypointDeltaSimulacrum");


		public static EventDirectorCategorySelection SkyMeadowSimulacrum { get; } = Load("SkyMeadowSimulacrum");


		public static EventDirectorCategorySelection TitanicPlainsSimulacrum { get; } = Load("TitanicPlainsSimulacrum");


		private static EventDirectorCategorySelection Load(string name)
		{
			return MoonstormSharedUtils.MSUAssetBundle.LoadAsset<EventDirectorCategorySelection>("edcs" + name);
		}
	}
	public interface IBodyStatArgModifier
	{
		void ModifyStatArguments(StatHookEventArgs args);
	}
	public interface IOnIncomingDamageOtherServerReciever
	{
		void OnIncomingDamageOther(HealthComponent victimHealthComponent, DamageInfo damageInfo);
	}
	public interface IStatItemBehavior
	{
		void RecalculateStatsEnd();

		void RecalculateStatsStart();
	}
	internal static class Interfaces
	{
		[SystemInitializer(new Type[] { })]
		private static void Init()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			LogLoader<MSULog>.Info("Setting up Interfaces", 13, "Init");
			HealthComponent.TakeDamage += new Manipulator(HealthComponent_TakeDamage);
		}

		private static void HealthComponent_TakeDamage(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			val.GotoNext((MoveType)2, new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchStfld<DamageInfo>(x, "rejected"),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<HealthComponent>(x, "onIncomingDamageReceivers")
			});
			val.Index -= 1;
			val.Emit(OpCodes.Ldarg_0);
			val.Emit(OpCodes.Ldarg_1);
			val.EmitDelegate<Action<HealthComponent, DamageInfo>>((Action<HealthComponent, DamageInfo>)RunOnIncomingDamageOther);
		}

		private static void RunOnIncomingDamageOther(HealthComponent healthComponent, DamageInfo damageInfo)
		{
			if (Object.op_Implicit((Object)(object)damageInfo.attacker))
			{
				IOnIncomingDamageOtherServerReciever[] components = damageInfo.attacker.GetComponents<IOnIncomingDamageOtherServerReciever>();
				for (int i = 0; i < components.Length; i++)
				{
					components[i].OnIncomingDamageOther(healthComponent, damageInfo);
				}
			}
		}
	}
	internal static class ItemDisplayCatalog
	{
		private static Dictionary<string, ItemDisplayRuleSet> idrsDictionary = new Dictionary<string, ItemDisplayRuleSet>(StringComparer.OrdinalIgnoreCase);

		private static Dictionary<string, GameObject> displayDictionary = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		public static ResourceAvailability catalogAvailability;

		public static GameObject GetItemDisplay(string key)
		{
			string key2 = key.ToLowerInvariant();
			if (!displayDictionary.ContainsKey(key2))
			{
				return null;
			}
			return displayDictionary[key2];
		}

		public static ItemDisplayRuleSet GetItemDisplayRuleSet(string key)
		{
			string key2 = key.ToLowerInvariant();
			if (!idrsDictionary.ContainsKey(key2))
			{
				return null;
			}
			return idrsDictionary[key2];
		}

		public static void AddDisplay(ItemDisplayDictionary idd)
		{
			if (!Object.op_Implicit((Object)(object)idd))
			{
				return;
			}
			for (int i = 0; i < idd.displayPrefabs.Length; i++)
			{
				GameObject val = idd.displayPrefabs[i];
				string key = ((Object)val).name.ToLowerInvariant();
				if (!displayDictionary.ContainsKey(key))
				{
					displayDictionary.Add(key, val);
				}
			}
		}

		[SystemInitializer(new Type[] { })]
		private static void SystemInitializer()
		{
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(FillCatalog));
		}

		private static void FillCatalog()
		{
			CreateIDRSDictionary();
			CreateDisplayDictionary();
			((ResourceAvailability)(ref catalogAvailability)).MakeAvailable();
			idrsDictionary.Clear();
			displayDictionary.Clear();
		}

		private static void CreateIDRSDictionary()
		{
			GameObject[] bodyPrefabs = BodyCatalog.bodyPrefabs;
			foreach (GameObject val in bodyPrefabs)
			{
				CharacterModel componentInChildren = val.GetComponentInChildren<CharacterModel>();
				if (!Object.op_Implicit((Object)(object)componentInChildren))
				{
					continue;
				}
				ItemDisplayRuleSet itemDisplayRuleSet = componentInChildren.itemDisplayRuleSet;
				if (Object.op_Implicit((Object)(object)itemDisplayRuleSet))
				{
					string key = (Utility.IsNullOrWhiteSpace(((Object)itemDisplayRuleSet).name) ? ("idrs" + ((Object)val).name) : ((Object)itemDisplayRuleSet).name).ToLowerInvariant();
					if (!idrsDictionary.ContainsKey(key))
					{
						idrsDictionary.Add(key, itemDisplayRuleSet);
					}
				}
			}
		}

		private static void CreateDisplayDictionary()
		{
			foreach (ItemDisplayRuleSet value in idrsDictionary.Values)
			{
				PopulateFrom(value);
			}
			static void PopulateFrom(ItemDisplayRuleSet idrs)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				KeyAssetRuleGroup[] keyAssetRuleGroups = idrs.keyAssetRuleGroups;
				foreach (KeyAssetRuleGroup val in keyAssetRuleGroups)
				{
					DisplayRuleGroup displayRuleGroup = val.displayRuleGroup;
					if (!((DisplayRuleGroup)(ref displayRuleGroup)).isEmpty)
					{
						ItemDisplayRule[] rules = val.displayRuleGroup.rules;
						for (int j = 0; j < rules.Length; j++)
						{
							GameObject followerPrefab = rules[j].followerPrefab;
							if (Object.op_Implicit((Object)(object)followerPrefab))
							{
								string key = (Utility.IsNullOrWhiteSpace(((Object)followerPrefab).name) ? $"{val.keyAsset.name}Display_{j}" : ((Object)followerPrefab).name).ToLowerInvariant();
								if (!displayDictionary.ContainsKey(key))
								{
									displayDictionary.Add(key, followerPrefab);
								}
								else if (!((Object)(object)displayDictionary[key] == (Object)(object)followerPrefab))
								{
									int num = j - 1;
									while (displayDictionary.ContainsKey(key))
									{
										num++;
										key = $"{val.keyAsset.name}Display_{num}".ToLowerInvariant();
									}
									displayDictionary.Add(key, followerPrefab);
								}
							}
						}
					}
				}
			}
		}
	}
	public abstract class BundleModule : ModuleBase<ContentBase>
	{
		public abstract AssetBundle MainBundle { get; }

		protected sealed override void InitializeContent(ContentBase contentClass)
		{
			throw new NotSupportedException("A BundleModule does not have a ContentBase by definition.");
		}

		protected new IEnumerable<T> GetContentClasses<T>(Type excludedType = null) where T : ContentBase
		{
			throw new NotSupportedException("A BundleModule does not have a ContentBase by definition.");
		}

		public TObject Load<TObject>(string name) where TObject : Object
		{
			return MainBundle.LoadAsset<TObject>(name);
		}

		public TObject[] LoadAll<TObject>() where TObject : Object
		{
			return MainBundle.LoadAllAssets<TObject>();
		}
	}
	public abstract class ContentModule<T> : ModuleBase<T> where T : ContentBase
	{
		public abstract R2APISerializableContentPack SerializableContentPack { get; }

		protected bool AddSafely<TAsset>(ref TAsset[] contentPackArray, TAsset content, string correspondingArrayName = null) where TAsset : Object
		{
			if (contentPackArray.Contains(content))
			{
				return true;
			}
			ArrayUtils.ArrayAppend<TAsset>(ref contentPackArray, ref content);
			return true;
		}
	}
	public abstract class ArtifactModuleBase : ContentModule<ArtifactBase>
	{
		internal static Dictionary<ArtifactDef, ArtifactBase> artifacts = new Dictionary<ArtifactDef, ArtifactBase>();

		[Obsolete("use \"moduleAvailability.CallWhenAvailable()\" instead")]
		public static Action<ReadOnlyDictionary<ArtifactDef, ArtifactBase>> OnDictionaryCreated;

		public static ResourceAvailability moduleAvailability;

		public static ReadOnlyDictionary<ArtifactDef, ArtifactBase> MoonstormArtifacts { get; private set; }

		public static ArtifactDef[] LoadedArtifactDefs => MoonstormArtifacts.Keys.ToArray();

		[SystemInitializer(new Type[] { typeof(ArtifactCatalog) })]
		private static void SystemInit()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			LogLoader<MSULog>.Info("Initializing Artifact Module...", 46, "SystemInit");
			RunArtifactManager.onArtifactEnabledGlobal += new ArtifactStateChangeDelegate(OnArtifactEnabled);
			RunArtifactManager.onArtifactDisabledGlobal += new ArtifactStateChangeDelegate(OnArtifactDisabled);
			MoonstormArtifacts = new ReadOnlyDictionary<ArtifactDef, ArtifactBase>(artifacts);
			artifacts = null;
			OnDictionaryCreated?.Invoke(MoonstormArtifacts);
			((ResourceAvailability)(ref moduleAvailability)).MakeAvailable();
		}

		protected virtual IEnumerable<ArtifactBase> GetArtifactBases()
		{
			return GetContentClasses<ArtifactBase>();
		}

		protected void AddArtifact(ArtifactBase artifact, Dictionary<ArtifactDef, ArtifactBase> artifactDictionary = null)
		{
			InitializeContent(artifact);
			artifactDictionary?.Add(artifact.ArtifactDef, artifact);
		}

		protected override void InitializeContent(ArtifactBase contentClass)
		{
			AddSafely<ArtifactDef>(ref SerializableContentPack.artifactDefs, contentClass.ArtifactDef, (string)null);
			contentClass.Initialize();
			if (Object.op_Implicit((Object)(object)contentClass.ArtifactCode))
			{
				ArtifactCodeAPI.AddCode(contentClass.ArtifactDef, contentClass.ArtifactCode);
			}
			artifacts[contentClass.ArtifactDef] = contentClass;
		}

		private static void OnArtifactEnabled([NotNull] RunArtifactManager runArtifactManager, [NotNull] ArtifactDef artifactDef)
		{
			foreach (KeyValuePair<ArtifactDef, ArtifactBase> moonstormArtifact in MoonstormArtifacts)
			{
				if (!((Object)(object)artifactDef != (Object)(object)moonstormArtifact.Key) && NetworkServer.active)
				{
					moonstormArtifact.Value.OnArtifactEnabled();
				}
			}
		}

		private static void OnArtifactDisabled([NotNull] RunArtifactManager runArtifactManager, [NotNull] ArtifactDef artifactDef)
		{
			foreach (KeyValuePair<ArtifactDef, ArtifactBase> moonstormArtifact in MoonstormArtifacts)
			{
				if (!((Object)(object)artifactDef != (Object)(object)moonstormArtifact.Key))
				{
					moonstormArtifact.Value.OnArtifactDisabled();
				}
			}
		}
	}
	public abstract class BuffModuleBase : ContentModule<BuffBase>
	{
		internal static Dictionary<BuffDef, BuffBase> buffs = new Dictionary<BuffDef, BuffBase>();

		internal static Dictionary<BuffDef, Material> overlayMaterials = new Dictionary<BuffDef, Material>();

		[Obsolete("use \"moduleAvailability.CallWhenAvailable()\" instead")]
		public static Action<ReadOnlyDictionary<BuffDef, BuffBase>, ReadOnlyDictionary<BuffDef, Material>> OnDictionariesCreated;

		public static ResourceAvailability moduleAvailability;

		public static ReadOnlyDictionary<BuffDef, BuffBase> MoonstormBuffs { get; private set; }

		public static ReadOnlyDictionary<BuffDef, Material> MoonstormOverlayMaterials { get; private set; }

		public static BuffDef[] LoadedBuffDefs => MoonstormBuffs.Keys.ToArray();

		[SystemInitializer(new Type[] { typeof(BuffCatalog) })]
		private static void SystemInit()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			LogLoader<MSULog>.Info("Initializing Buff Module...", 52, "SystemInit");
			CharacterBody.SetBuffCount += new hook_SetBuffCount(OnBuffsChanged);
			CharacterModel.UpdateOverlays += new hook_UpdateOverlays(AddBuffOverlay);
			MoonstormBuffs = new ReadOnlyDictionary<BuffDef, BuffBase>(buffs);
			buffs = null;
			MoonstormOverlayMaterials = new ReadOnlyDictionary<BuffDef, Material>(overlayMaterials);
			overlayMaterials = null;
			OnDictionariesCreated?.Invoke(MoonstormBuffs, MoonstormOverlayMaterials);
			((ResourceAvailability)(ref moduleAvailability)).MakeAvailable();
		}

		protected virtual IEnumerable<BuffBase> GetBuffBases()
		{
			return GetContentClasses<BuffBase>();
		}

		protected void AddBuff(BuffBase buff, Dictionary<BuffDef, BuffBase> buffDictionary = null)
		{
			InitializeContent(buff);
			buffDictionary?.Add(buff.BuffDef, buff);
		}

		protected override void InitializeContent(BuffBase contentClass)
		{
			AddSafely<BuffDef>(ref SerializableContentPack.buffDefs, contentClass.BuffDef, (string)null);
			contentClass.Initialize();
			if (Object.op_Implicit((Object)(object)contentClass.OverlayMaterial))
			{
				overlayMaterials[contentClass.BuffDef] = contentClass.OverlayMaterial;
			}
			buffs[contentClass.BuffDef] = contentClass;
		}

		private static void OnBuffsChanged(orig_SetBuffCount orig, CharacterBody self, BuffIndex buffType, int newCount)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self, buffType, newCount);
			if (Object.op_Implicit((Object)(object)self))
			{
				((Component)self).GetComponent<MoonstormContentManager>().StartGetInterfaces();
			}
		}

		private static void AddBuffOverlay(orig_UpdateOverlays orig, CharacterModel model)
		{
			orig.Invoke(model);
			if (!Object.op_Implicit((Object)(object)model.body))
			{
				return;
			}
			foreach (KeyValuePair<BuffDef, Material> moonstormOverlayMaterial in MoonstormOverlayMaterials)
			{
				if (model.body.HasBuff(moonstormOverlayMaterial.Key))
				{
					AddOverlay(model, moonstormOverlayMaterial.Value);
				}
			}
		}

		private static void AddOverlay(CharacterModel model, Material overlayMaterial)
		{
			if (model.activeOverlayCount < CharacterModel.maxOverlays && Object.op_Implicit((Object)(object)overlayMaterial))
			{
				Material[] currentOverlays = model.currentOverlays;
				int activeOverlayCount = model.activeOverlayCount;
				model.activeOverlayCount = activeOverlayCount + 1;
				currentOverlays[activeOverlayCount] = overlayMaterial;
			}
		}
	}
	public abstract class CharacterModuleBase : ContentModule<CharacterBase>
	{
		private class MonsterCollectionFuncPair
		{
			[StructLayout(LayoutKind.Sequential, Size = 1)]
			public struct Comparer : IEqualityComparer<MonsterCollectionFuncPair>
			{
				bool IEqualityComparer<MonsterCollectionFuncPair>.Equals(MonsterCollectionFuncPair x, MonsterCollectionFuncPair y)
				{
					if (x == null || y == null)
					{
						return false;
					}
					if (x.tiedMonsterBase == null || y.tiedMonsterBase == null)
					{
						return false;
					}
					return x.tiedMonsterBase == y.tiedMonsterBase;
				}

				int IEqualityComparer<MonsterCollectionFuncPair>.GetHashCode(MonsterCollectionFuncPair obj)
				{
					if (obj == null)
					{
						return -1;
					}
					if (obj.tiedMonsterBase == null)
					{
						return -1;
					}
					return obj.tiedMonsterBase.GetHashCode();
				}
			}

			public HashSet<MSMonsterDirectorCard> cards = new HashSet<MSMonsterDirectorCard>(default(MSMonsterDirectorCard.PrefabComparer));

			public MonsterBase tiedMonsterBase;

			public MonsterBase.IsAvailableForDCCSDelegate IsAvailable => tiedMonsterBase.IsAvailableForDCCS;
		}

		internal static Dictionary<GameObject, CharacterBase> characters = new Dictionary<GameObject, CharacterBase>();

		[Obsolete("use \"moduleAvailability.CallWhenAvailable()\" instead")]
		public static Action<ReadOnlyDictionary<GameObject, CharacterBase>> OnDictionaryCreated;

		public static ResourceAvailability moduleAvailability;

		private static Dictionary<Stage, HashSet<MonsterCollectionFuncPair>> currentStageToCards = new Dictionary<Stage, HashSet<MonsterCollectionFuncPair>>();

		private static Dictionary<string, HashSet<MonsterCollectionFuncPair>> currentCustomStageToCards = new Dictionary<string, HashSet<MonsterCollectionFuncPair>>(StringComparer.OrdinalIgnoreCase);

		public static ReadOnlyDictionary<GameObject, CharacterBase> MoonstormCharacters { get; private set; }

		public static MonsterBase[] MoonstormMonsters => MoonstormCharacters.Values.Where((CharacterBase cb) => cb.GetType().IsSubclassOf(typeof(MonsterBase))).Cast<MonsterBase>().ToArray();

		public static MonsterBase[] MonstersWithCards => MoonstormMonsters.Where((MonsterBase mb) => mb.MonsterDirectorCards.Count > 0).ToArray();

		public static SurvivorBase[] MoonstormSurvivors => MoonstormCharacters.Values.Where((CharacterBase cb) => cb.GetType().IsSubclassOf(typeof(SurvivorBase))).Cast<SurvivorBase>().ToArray();

		public static GameObject[] LoadedCharacterBodies => MoonstormCharacters.Values.Select((CharacterBase cb) => cb.BodyPrefab).ToArray();

		public static GameObject[] LoadedCharacterMasters => MoonstormCharacters.Values.Select((CharacterBase cb) => cb.MasterPrefab).ToArray();

		[SystemInitializer(new Type[]
		{
			typeof(BodyCatalog),
			typeof(MasterCatalog)
		})]
		private static void SystemInit()
		{
			LogLoader<MSULog>.Info("Initializing Character Module...", 96, "SystemInit");
			Run.onRunStartGlobal += PopulateDictionaries;
			DirectorAPI.MonsterActions += AddCustomMonsters;
			MoonstormCharacters = new ReadOnlyDictionary<GameObject, CharacterBase>(characters);
			characters = null;
			OnDictionaryCreated?.Invoke(MoonstormCharacters);
			((ResourceAvailability)(ref moduleAvailability)).MakeAvailable();
		}

		protected virtual IEnumerable<CharacterBase> GetCharacterBases()
		{
			LogLoader<MSULog>.Debug($"Getting the Characters found inside {GetType().Assembly}...", 115, "GetCharacterBases");
			return GetContentClasses<CharacterBase>();
		}

		protected void AddCharacter(CharacterBase character, Dictionary<GameObject, CharacterBase> characterDictionary = null)
		{
			InitializeContent(character);
			characterDictionary?.Add(character.BodyPrefab, character);
		}

		protected override void InitializeContent(CharacterBase contentClass)
		{
			AddSafely<GameObject>(ref SerializableContentPack.bodyPrefabs, contentClass.BodyPrefab, "BodyPrefabs");
			contentClass.Initialize();
			if (contentClass != null)
			{
				if (!(contentClass is MonsterBase monsterBase))
				{
					if (contentClass is SurvivorBase survivorBase)
					{
						SurvivorBase survivorBase2 = survivorBase;
						AddSafely<SurvivorDef>(ref SerializableContentPack.survivorDefs, survivorBase2.SurvivorDef, (string)null);
						AddSafely<GameObject>(ref SerializableContentPack.masterPrefabs, survivorBase2.MasterPrefab, "MasterPrefabs");
						LogLoader<MSULog>.Debug($"Character {survivorBase2} Initialized and ensured it's body, master prefabs & survivor def in {((Object)SerializableContentPack).name}", 157, "InitializeContent");
					}
				}
				else
				{
					MonsterBase monsterBase2 = monsterBase;
					AddSafely<GameObject>(ref SerializableContentPack.masterPrefabs, monsterBase2.MasterPrefab, "MasterPrefabs");
					MSMonsterDirectorCard monsterDirectorCard = monsterBase2.MonsterDirectorCard;
					if (Object.op_Implicit((Object)(object)monsterDirectorCard) && !monsterBase2.MonsterDirectorCards.Contains(monsterDirectorCard))
					{
						monsterBase2.MonsterDirectorCards.Add(monsterDirectorCard);
					}
					LogLoader<MSULog>.Debug($"Character {monsterBase2} Initialized and ensured it's body and master prefabs in {((Object)SerializableContentPack).name}", 152, "InitializeContent");
				}
			}
			characters.Add(contentClass.BodyPrefab, contentClass);
		}

		private static void PopulateDictionaries(Run run)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			ClearDictionaries();
			ExpansionDef[] runExpansions = ((IEnumerable<ExpansionDef>)(object)ExpansionCatalog.expansionDefs).Where((ExpansionDef exp) => run.IsExpansionEnabled(exp)).ToArray();
			MonsterBase[] array = MonstersWithCards.ToArray();
			int totalMonstersAdded = 0;
			MonsterBase[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				AddMonsterBaseToRun(array2[i], run, runExpansions, ref totalMonstersAdded);
			}
		}

		private static void AddMonsterBaseToRun(MonsterBase monsterBase, Run run, ExpansionDef[] runExpansions, ref int totalMonstersAdded)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			foreach (MSMonsterDirectorCard monsterDirectorCard in monsterBase.MonsterDirectorCards)
			{
				try
				{
					if (!monsterDirectorCard.IsAvailable(runExpansions))
					{
						continue;
					}
					foreach (Stage value in Enum.GetValues(typeof(Stage)))
					{
						if ((int)value == 1 && ((Enum)monsterDirectorCard.stages).HasFlag((Enum)(object)value))
						{
							AddCardToCustomStages(monsterDirectorCard, monsterBase);
						}
						else if (((Enum)monsterDirectorCard.stages).HasFlag((Enum)(object)value))
						{
							AddCardToStage(monsterDirectorCard, monsterBase, value);
						}
					}
					totalMonstersAdded++;
				}
				catch (Exception arg)
				{
					LogLoader<MSULog>.Error($"{arg}\nCard: {monsterDirectorCard}", 213, "AddMonsterBaseToRun");
				}
			}
		}

		private static void AddCardToCustomStages(MSMonsterDirectorCard card, MonsterBase monsterBase)
		{
			foreach (string customStage in card.customStages)
			{
				if (!currentCustomStageToCards.ContainsKey(customStage))
				{
					currentCustomStageToCards.Add(customStage, new HashSet<MonsterCollectionFuncPair>(default(MonsterCollectionFuncPair.Comparer)));
				}
				HashSet<MonsterCollectionFuncPair> hashSet = currentCustomStageToCards[customStage];
				MonsterCollectionFuncPair monsterCollectionFuncPair = FindMonsterCollection(monsterBase, hashSet) ?? new MonsterCollectionFuncPair();
				monsterCollectionFuncPair.cards.Add(card);
				monsterCollectionFuncPair.tiedMonsterBase = monsterBase;
				hashSet.Add(monsterCollectionFuncPair);
			}
		}

		private static void AddCardToStage(MSMonsterDirectorCard card, MonsterBase monsterBase, Stage stageValue)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!currentStageToCards.ContainsKey(stageValue))
			{
				currentStageToCards[stageValue] = new HashSet<MonsterCollectionFuncPair>(default(MonsterCollectionFuncPair.Comparer));
			}
			HashSet<MonsterCollectionFuncPair> hashSet = currentStageToCards[stageValue];
			MonsterCollectionFuncPair monsterCollectionFuncPair = FindMonsterCollection(monsterBase, hashSet) ?? new MonsterCollectionFuncPair();
			monsterCollectionFuncPair.cards.Add(card);
			monsterCollectionFuncPair.tiedMonsterBase = monsterBase;
			hashSet.Add(monsterCollectionFuncPair);
		}

		private static MonsterCollectionFuncPair FindMonsterCollection(MonsterBase monsterBase, HashSet<MonsterCollectionFuncPair> set)
		{
			foreach (MonsterCollectionFuncPair item in set)
			{
				if (item.tiedMonsterBase == monsterBase)
				{
					return item;
				}
			}
			return null;
		}

		private static void ClearDictionaries()
		{
			currentCustomStageToCards.Clear();
			currentStageToCards.Clear();
		}

		private static void AddCustomMonsters(DccsPool pool, List<DirectorCardHolder> cardList, StageInfo stageInfo)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				HashSet<MonsterCollectionFuncPair> value;
				if ((int)stageInfo.stage == 1)
				{
					if (currentCustomStageToCards.TryGetValue(stageInfo.CustomStageName, out value))
					{
						AddMonstersToPool(pool, value, stageInfo);
					}
				}
				else if (currentStageToCards.TryGetValue(stageInfo.stage, out value))
				{
					AddMonstersToPool(pool, value, stageInfo);
				}
			}
			catch (Exception ex)
			{
				LogLoader<MSULog>.Error($"Failed to add custom monsters: {ex}\n(Pool: {pool}, CardList: {cardList}, Stage: {stageInfo}, currentCustomStageToCards: {currentCustomStageToCards}, currentStageToCards: {currentStageToCards}", 312, "AddCustomMonsters");
			}
		}

		private static void AddMonstersToPool(DccsPool pool, HashSet<MonsterCollectionFuncPair> monsters, StageInfo stageInfo)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			Category val = ((IEnumerable<Category>)pool.poolCategories).FirstOrDefault((Func<Category, bool>)((Category category) => category.name == MonsterPoolCategories.Standard));
			if (val == null)
			{
				LogLoader<MSULog>.Error("Couldnt find standard category for current stage! not adding monsters!", 321, "AddMonstersToPool");
				return;
			}
			IEnumerable<DirectorCardCategorySelection> enumerable = val.alwaysIncluded.Select((PoolEntry pe) => pe.dccs).Concat(val.includedIfConditionsMet.Select((ConditionalPoolEntry cpe) => ((PoolEntry)cpe).dccs)).Concat(val.includedIfNoConditionsMet.Select((PoolEntry pe) => pe.dccs));
			foreach (MonsterCollectionFuncPair monster in monsters)
			{
				if (!monster.IsAvailable(stageInfo))
				{
					continue;
				}
				try
				{
					foreach (DirectorCardCategorySelection item in enumerable)
					{
						foreach (MSMonsterDirectorCard card in monster.cards)
						{
							DirectorAPI.AddCard(item, card.DirectorCardHolder);
						}
					}
				}
				catch (Exception arg)
				{
					LogLoader<MSULog>.Error($"{arg}\n(Monster Collection: {monster})", 347, "AddMonstersToPool");
				}
			}
		}
	}
	public abstract class DamageTypeModuleBase : ModuleBase<DamageTypeBase>
	{
		internal static Dictionary<ModdedDamageType, DamageTypeBase> damageTypes = new Dictionary<ModdedDamageType, DamageTypeBase>();

		[Obsolete("use \"moduleAvailability.CallWhenAvailable()\" instead")]
		public static Action<ReadOnlyDictionary<ModdedDamageType, DamageTypeBase>> OnDictionaryCreated;

		public static ResourceAvailability moduleAvailability;

		public static ReadOnlyDictionary<ModdedDamageType, DamageTypeBase> MoonstormDamageTypes { get; private set; }

		public static ModdedDamageType[] ModdedDamageTypes => MoonstormDamageTypes.Keys.ToArray();

		[SystemInitializer(new Type[] { })]
		private static void SystemInit()
		{
			LogLoader<MSULog>.Info("Initializing DamageType Module...", 43, "SystemInit");
			MoonstormDamageTypes = new ReadOnlyDictionary<ModdedDamageType, DamageTypeBase>(damageTypes);
			damageTypes = null;
			OnDictionaryCreated?.Invoke(MoonstormDamageTypes);
			((ResourceAvailability)(ref moduleAvailability)).MakeAvailable();
		}

		protected virtual IEnumerable<DamageTypeBase> GetDamageTypeBases()
		{
			return GetContentClasses<DamageTypeBase>();
		}

		protected void AddDamageType(DamageTypeBase damageType, Dictionary<ModdedDamageType, DamageTypeBase> damageTypeDictionary = null)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			InitializeContent(damageType);
			damageTypeDictionary?.Add(damageType.ModdedDamageType, damageType);
		}

		protected override void InitializeContent(DamageTypeBase contentClass)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			contentClass.SetDamageType(DamageAPI.ReserveDamageType());
			contentClass.Initialize();
			contentClass.Delegates();
			damageTypes[contentClass.ModdedDamageType] = contentClass;
		}
	}
	public abstract class EliteModuleBase : ContentModule<EliteEquipmentBase>
	{
		internal static List<MSEliteDef> eliteDefs = new List<MSEliteDef>();

		[Obsolete("use \"moduleAvailability.CallWhenAvailable()\" instead")]
		public static Action<ReadOnlyCollection<MSEliteDef>> OnListCreated;

		public static ResourceAvailability moduleAvailability;

		public static ReadOnlyCollection<MSEliteDef> MoonstormElites { get; private set; }

		public abstract AssetBundle AssetBundle { get; }

		[SystemInitializer(new Type[]
		{
			typeof(BuffCatalog),
			typeof(EquipmentCatalog),
			typeof(EliteCatalog)
		})]
		private static void SystemInit()
		{
			LogLoader<MSULog>.Info("Initializing Elite Module...", 45, "SystemInit");
			AddElitesViaDirectorAPI();
			MoonstormElites = new ReadOnlyCollection<MSEliteDef>(eliteDefs);
			eliteDefs = null;
			OnListCreated?.Invoke(MoonstormElites);
			((ResourceAvailability)(ref moduleAvailability)).MakeAvailable();
		}

		private static void AddElitesViaDirectorAPI()
		{
			EliteTierDef[] vanillaEliteTiers = EliteAPI.VanillaEliteTiers;
			foreach (MSEliteDef eliteDef in eliteDefs)
			{
				switch (eliteDef.eliteTier)
				{
				case VanillaEliteTier.HonorDisabled:
				{
					ref EliteDef[] eliteTypes4 = ref vanillaEliteTiers[1].eliteTypes;
					EliteDef val = (EliteDef)(object)eliteDef;
					ArrayUtils.ArrayAppend<EliteDef>(ref eliteTypes4, ref val);
					break;
				}
				case VanillaEliteTier.HonorActive:
				{
					ref EliteDef[] eliteTypes3 = ref vanillaEliteTiers[2].eliteTypes;
					EliteDef val = (EliteDef)(object)eliteDef;
					ArrayUtils.ArrayAppend<EliteDef>(ref eliteTypes3, ref val);
					break;
				}
				case VanillaEliteTier.PostLoop:
				{
					ref EliteDef[] eliteTypes2 = ref vanillaEliteTiers[3].eliteTypes;
					EliteDef val = (EliteDef)(object)eliteDef;
					ArrayUtils.ArrayAppend<EliteDef>(ref eliteTypes2, ref val);
					break;
				}
				case VanillaEliteTier.Lunar:
				{
					ref EliteDef[] eliteTypes = ref vanillaEliteTiers[4].eliteTypes;
					EliteDef val = (EliteDef)(object)eliteDef;
					ArrayUtils.ArrayAppend<EliteDef>(ref eliteTypes, ref val);
					break;
				}
				}
			}
		}

		protected virtual IEnumerable<EliteEquipmentBase> GetInitializedEliteEquipmentBases()
		{
			List<EliteEquipmentBase> list = new List<EliteEquipmentBase>();
			MSEliteDef[] array = AssetBundle.LoadAllAssets<MSEliteDef>();
			foreach (MSEliteDef mSEliteDef in array)
			{
				if (EquipmentModuleBase.eliteEquip.TryGetValue(((EliteDef)mSEliteDef).eliteEquipmentDef, out var value) && !list.Contains(value))
				{
					list.Add(value);
				}
			}
			return list;
		}

		protected void AddElite(EliteEquipmentBase elite, List<MSEliteDef> list = null)
		{
			InitializeContent(elite);
			list?.AddRange(elite.EliteDefs);
		}

		protected override void InitializeContent(EliteEquipmentBase contentClass)
		{
			contentClass.Initialize();
			Dictionary<Texture2D, List<MSEliteDef>> dictionary = new Dictionary<Texture2D, List<MSEliteDef>>();
			foreach (MSEliteDef eliteDef in contentClass.EliteDefs)
			{
				AddSafely<EliteDef>(ref SerializableContentPack.eliteDefs, (EliteDef)(object)eliteDef, (string)null);
				eliteDefs.Add(eliteDef);
				if (Object.op_Implicit((Object)(object)eliteDef.overlay) && Object.op_Implicit((Object)(object)contentClass.EquipmentDef.passiveBuffDef))
				{
					BuffModuleBase.overlayMaterials[contentClass.EquipmentDef.passiveBuffDef] = eliteDef.overlay;
				}
				if (Object.op_Implicit((Object)(object)eliteDef.eliteRamp))
				{
					if (!dictionary.ContainsKey(eliteDef.eliteRamp))
					{
						dictionary.Add(eliteDef.eliteRamp, new List<MSEliteDef>());
					}
					dictionary[eliteDef.eliteRamp].Add(eliteDef);
				}
			}
			foreach (KeyValuePair<Texture2D, List<MSEliteDef>> item in dictionary)
			{
				EliteRamp.AddRampToMultipleElites((IEnumerable<EliteDef>)item.Value, item.Key);
			}
		}
	}
	public abstract class EliteTierDefModuleBase : ModuleBase<EliteTierDefBase>
	{
		internal static Dictionary<SerializableEliteTierDef, EliteTierDefBase> eliteTierDefs = new Dictionary<SerializableEliteTierDef, EliteTierDefBase>();

		[Obsolete("use \"moduleAvailability.CallWhenAvailable()\" instead")]
		public static Action<ReadOnlyDictionary<SerializableEliteTierDef, EliteTierDefBase>> OnDictionaryCreated;

		public static ResourceAvailability moduleAvailability;

		public static ReadOnlyDictionary<SerializableEliteTierDef, EliteTierDefBase> MoonstormEliteTiers { get; private set; }

		public static SerializableEliteTierDef[] LoadedEliteTierDefs => MoonstormEliteTiers.Keys.ToArray();

		[SystemInitializer(new Type[] { })]
		private static void SystemInit()
		{
			AddressReferencedAsset.OnAddressReferencedAssetsLoaded += delegate
			{
				LogLoader<MSULog>.Info("Initializing EliteTierDef Module...", 47, "SystemInit");
				CreateAndAddTiers();
				MoonstormEliteTiers = new ReadOnlyDictionary<SerializableEliteTierDef, EliteTierDefBase>(eliteTierDefs);
				eliteTierDefs = null;
				OnDictionaryCreated?.Invoke(MoonstormEliteTiers);
				((ResourceAvailability)(ref moduleAvailability)).MakeAvailable();
			};
		}

		private static void CreateAndAddTiers()
		{
			foreach (EliteTierDefBase value in eliteTierDefs.Values)
			{
				SerializableEliteTierDef serializableEliteTierDef = value.SerializableEliteTierDef;
				serializableEliteTierDef.Create();
				serializableEliteTierDef.EliteTierDef.isAvailable = value.IsAvailable;
				EliteAPI.AddCustomEliteTier(serializableEliteTierDef.EliteTierDef);
			}
		}

		protected virtual IEnumerable<EliteTierDefBase> GetEliteTierDefBases()
		{
			return GetContentClasses<EliteTierDefBase>();
		}

		protected void AddEliteTierDef(EliteTierDefBase eliteTierDef, Dictionary<SerializableEliteTierDef, EliteTierDefBase> dictionary = null)
		{
			InitializeContent(eliteTierDef);
			dictionary?.Add(eliteTierDef.SerializableEliteTierDef, eliteTierDef);
		}

		protected override void InitializeContent(EliteTierDefBase contentClass)
		{
			contentClass.Initialize();
			eliteTierDefs[contentClass.SerializableEliteTierDef] = contentClass;
		}
	}
	public abstract class EquipmentModuleBase : ContentModule<EquipmentBase>
	{
		internal static Dictionary<EquipmentDef, EquipmentBase> nonEliteEquip = new Dictionary<EquipmentDef, EquipmentBase>();

		internal static Dictionary<EquipmentDef, EliteEquipmentBase> eliteEquip = new Dictionary<EquipmentDef, EliteEquipmentBase>();

		private static ReadOnlyDictionary<EquipmentDef, EquipmentBase> allMoonstormEquipments;

		[Obsolete("use \"moduleAvailability.CallWhenAvailable()\" instead")]
		public static Action<ReadOnlyDictionary<EquipmentDef, EquipmentBase>, ReadOnlyDictionary<EquipmentDef, EliteEquipmentBase>> OnDictionariesCreated;

		public static ResourceAvailability moduleAvailability;

		public static ReadOnlyDictionary<EquipmentDef, EquipmentBase> NonEliteMoonstormEquipments { get; private set; }

		public static ReadOnlyDictionary<EquipmentDef, EliteEquipmentBase> EliteMoonstormEquipments { get; private set; }

		public static ReadOnlyDictionary<EquipmentDef, EquipmentBase> AllMoonstormEquipments => allMoonstormEquipments;

		public static EquipmentDef[] LoadedNonEliteEquipmentDefs => NonEliteMoonstormEquipments.Keys.ToArray();

		public static EquipmentDef[] EliteEquipmentDefs => EliteMoonstormEquipments.Keys.ToArray();

		public static EquipmentDef[] AllEquipmentDefs => AllMoonstormEquipments.Keys.ToArray();

		[SystemInitializer(new Type[] { typeof(EquipmentCatalog) })]
		private static void SystemInit()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			LogLoader<MSULog>.Info("Initializing Equipment Module...", 72, "SystemInit");
			EquipmentSlot.PerformEquipmentAction += new hook_PerformEquipmentAction(PerformAction);
			EliteMoonstormEquipments = new ReadOnlyDictionary<EquipmentDef, EliteEquipmentBase>(eliteEquip);
			eliteEquip = null;
			NonEliteMoonstormEquipments = new ReadOnlyDictionary<EquipmentDef, EquipmentBase>(nonEliteEquip);
			nonEliteEquip = null;
			allMoonstormEquipments = new ReadOnlyDictionary<EquipmentDef, EquipmentBase>(NonEliteMoonstormEquipments.Union(((IEnumerable<KeyValuePair<EquipmentDef, EliteEquipmentBase>>)EliteMoonstormEquipments).ToDictionary((Func<KeyValuePair<EquipmentDef, EliteEquipmentBase>, EquipmentDef>)((KeyValuePair<EquipmentDef, EliteEquipmentBase> k) => k.Key), (Func<KeyValuePair<EquipmentDef, EliteEquipmentBase>, EquipmentBase>)((KeyValuePair<EquipmentDef, EliteEquipmentBase> v) => v.Value))).ToDictionary((KeyValuePair<EquipmentDef, EquipmentBase> k) => k.Key, (KeyValuePair<EquipmentDef, EquipmentBase> v) => v.Value));
			OnDictionariesCreated?.Invoke(NonEliteMoonstormEquipments, EliteMoonstormEquipments);
			((ResourceAvailability)(ref moduleAvailability)).MakeAvailable();
		}

		protected virtual IEnumerable<EquipmentBase> GetEquipmentBases()
		{
			return GetContentClasses<EquipmentBase>(typeof(EliteEquipmentBase));
		}

		protected void AddEquipment(EquipmentBase equip, Dictionary<EquipmentDef, EquipmentBase> dictionary = null)
		{
			InitializeContent(equip);
			dictionary?.Add(equip.EquipmentDef, equip);
		}

		protected virtual IEnumerable<EliteEquipmentBase> GetEliteEquipmentBases()
		{
			return GetContentClasses<EliteEquipmentBase>();
		}

		protected void AddEliteEquipment(EliteEquipmentBase eliteEqp, Dictionary<EquipmentDef, EliteEquipmentBase> dictionary = null)
		{
			InitializeContent(eliteEqp);
			dictionary?.Add(eliteEqp.EquipmentDef, eliteEqp);
		}

		protected override void InitializeContent(EquipmentBase contentClass)
		{
			AddSafely<EquipmentDef>(ref SerializableContentPack.equipmentDefs, contentClass.EquipmentDef, (string)null);
			if (contentClass is EliteEquipmentBase eliteEquipmentBase)
			{
				eliteEquip[eliteEquipmentBase.EquipmentDef] = eliteEquipmentBase;
				return;
			}
			nonEliteEquip[contentClass.EquipmentDef] = contentClass;
			contentClass.Initialize();
		}

		private static bool PerformAction(orig_PerformEquipmentAction orig, EquipmentSlot self, EquipmentDef equipmentDef)
		{
			if (!NetworkServer.active)
			{
				LogLoader<MSULog>.Warning("[Server] function 'System.Boolean RoR2.EquipmentSlot::PerformEquipmentAction(RoR2.EquipmentDef)' called on client", 175, "PerformAction");
				return false;
			}
			if (AllMoonstormEquipments.TryGetValue(equipmentDef, out var value))
			{
				_ = self.characterBody;
				return value.FireAction(self);
			}
			return orig.Invoke(self, equipmentDef);
		}
	}
	public abstract class InteractableModuleBase : ContentModule<InteractableBase>
	{
		private class InteractableCollectionFuncPair
		{
			[StructLayout(LayoutKind.Sequential, Size = 1)]
			public struct Comparer : IEqualityComparer<InteractableCollectionFuncPair>
			{
				bool IEqualityComparer<InteractableCollectionFuncPair>.Equals(InteractableCollectionFuncPair x, InteractableCollectionFuncPair y)
				{
					if (x == null || y == null)
					{
						return false;
					}
					if (x.tiedInteractableBase == null || y.tiedInteractableBase == null)
					{
						return false;
					}
					return x.tiedInteractableBase == y.