Decompiled source of MoonstormSharedUtils v1.6.3
plugins/MoonstormSharedUtils.dll
Decompiled 5 months ago
The result has been truncated due to the large size, download it to view full contents!
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.