Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LoadoutEnigma v1.0.0
plugins/LoadoutEnigma/LoadoutEnigma.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Toolbot; using HG; using HG.Reflection; using HarmonyLib; using IL.EntityStates.Toolbot; using LoadoutEnigma.Content; using LoadoutEnigma.ModCompatibility; using LoadoutEnigma.Utilities; using LoadoutEnigma.Utilities.Extensions; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.Utils; using On.RoR2; using On.RoR2.UI; using R2API; using R2API.Utils; using RiskOfOptions; using RiskOfOptions.Options; using RoR2; using RoR2.ContentManagement; using RoR2.Skills; using RoR2.UI; using RoR2BepInExPack.Utilities; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: NetworkCompatibility(/*Could not decode attribute arguments.*/)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LoadoutEnigma")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c4c174cc9cf27e1d12cf41fa8b96356f24d66ea3")] [assembly: AssemblyProduct("LoadoutEnigma")] [assembly: AssemblyTitle("LoadoutEnigma")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LoadoutEnigma { public static class CatalogAvailability { public static ResourceAvailability SkillCatalog; [SystemInitializer(new Type[] { typeof(SkillCatalog) })] private static void InitSkillCatalog() { ((ResourceAvailability)(ref SkillCatalog)).MakeAvailable(); } } internal static class Commands { [ConCommand(commandName = "loadout_enigma_force_advance")] private static void CCAdvanceLoadoutEnigma(ConCommandArgs args) { CharacterBody senderBody = ((ConCommandArgs)(ref args)).senderBody; LoadoutEnigmaController loadoutEnigmaController = default(LoadoutEnigmaController); if (Object.op_Implicit((Object)(object)senderBody) && senderBody.hasEffectiveAuthority && ((Component)senderBody).TryGetComponent<LoadoutEnigmaController>(ref loadoutEnigmaController) && ((Behaviour)loadoutEnigmaController).enabled) { loadoutEnigmaController.SetRandomSkills(); } } } public class ConfigSkillIndexList : IDisposable, IList<int>, ICollection<int>, IEnumerable<int>, IEnumerable, IReadOnlyList<int>, IReadOnlyCollection<int> { private readonly ConfigEntry<string> _configEntry; private int[] _includedSkillIndices = Array.Empty<int>(); public int this[int index] { get { return _includedSkillIndices[index]; } set { _includedSkillIndices[index] = value; } } public int Count => _includedSkillIndices.Length; public bool IsReadOnly => true; public ConfigSkillIndexList(ConfigEntry<string> configEntry) { _configEntry = configEntry; _configEntry.SettingChanged += onConfigValueChanged; ((ResourceAvailability)(ref CatalogAvailability.SkillCatalog)).CallWhenAvailable((Action)parseSkills); } public void Dispose() { _configEntry.SettingChanged -= onConfigValueChanged; } private void onConfigValueChanged(object sender, EventArgs e) { if (((ResourceAvailability)(ref CatalogAvailability.SkillCatalog)).available) { parseSkills(); } } private void parseSkills() { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) string[] array = _configEntry.Value.Split(','); HashSet<int> hashSet = new HashSet<int>(array.Length); string[] array2 = array; int i; for (i = 0; i < array2.Length; i++) { string b = array2[i].Trim(); SkillDef val = null; foreach (SkillDef allSkillDef in SkillCatalog.allSkillDefs) { if (string.Equals(SkillCatalog.GetSkillName(allSkillDef.skillIndex), b, StringComparison.OrdinalIgnoreCase)) { val = allSkillDef; break; } } SkillFamily val2 = null; foreach (SkillFamily allSkillFamily in SkillCatalog.allSkillFamilies) { if (string.Equals(SkillCatalog.GetSkillFamilyName(allSkillFamily.catalogIndex), b, StringComparison.OrdinalIgnoreCase)) { val2 = allSkillFamily; break; } } if (Object.op_Implicit((Object)(object)val)) { hashSet.Add(val.skillIndex); } if (!Object.op_Implicit((Object)(object)val2)) { continue; } Variant[] variants = val2.variants; foreach (Variant val3 in variants) { if (Object.op_Implicit((Object)(object)val3.skillDef)) { hashSet.Add(val3.skillDef.skillIndex); } } } i = 0; int[] array3 = new int[hashSet.Count]; foreach (int item in hashSet) { array3[i] = item; i++; } _includedSkillIndices = array3; Array.Sort(_includedSkillIndices); } public bool Contains(int item) { return BinarySearch(item) >= 0; } public int IndexOf(int item) { int num = BinarySearch(item); if (num < 0) { return -1; } return num; } public int BinarySearch(int item) { return Array.BinarySearch(_includedSkillIndices, item); } public void CopyTo(int[] array, int arrayIndex) { _includedSkillIndices.CopyTo(array, arrayIndex); } public IEnumerator<int> GetEnumerator() { int[] includedSkillIndices = _includedSkillIndices; for (int i = 0; i < includedSkillIndices.Length; i++) { yield return includedSkillIndices[i]; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void ICollection<int>.Add(int item) { throw new NotSupportedException(); } void ICollection<int>.Clear() { throw new NotSupportedException(); } void IList<int>.Insert(int index, int item) { throw new NotSupportedException(); } bool ICollection<int>.Remove(int item) { throw new NotSupportedException(); } void IList<int>.RemoveAt(int index) { throw new NotSupportedException(); } } internal static class GenericSkillHooks { public delegate void OnSkillChangedGlobalDelegate(GenericSkill skill, SkillDef previousSkill, SkillDef newSkill); [CompilerGenerated] private static class <>O { public static hook_SetSkillInternal <0>__GenericSkill_SetSkillInternal; } public static event OnSkillChangedGlobalDelegate OnSkillChangedGlobal; [SystemInitializer(new Type[] { })] private static void Init() { //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_001b: Expected O, but got Unknown object obj = <>O.<0>__GenericSkill_SetSkillInternal; if (obj == null) { hook_SetSkillInternal val = GenericSkill_SetSkillInternal; <>O.<0>__GenericSkill_SetSkillInternal = val; obj = (object)val; } GenericSkill.SetSkillInternal += (hook_SetSkillInternal)obj; } private static void GenericSkill_SetSkillInternal(orig_SetSkillInternal orig, GenericSkill self, SkillDef newSkillDef) { SkillDef skillDef = self.skillDef; orig.Invoke(self, newSkillDef); if ((Object)(object)skillDef != (Object)(object)self.skillDef) { GenericSkillHooks.OnSkillChangedGlobal?.Invoke(self, skillDef, self.skillDef); } } } internal static class LanguageFolderHandler { public static void Register(string searchFolder, string langFolderName = "lang") { string langFolderPath = Path.Combine(searchFolder, langFolderName); if (Directory.Exists(langFolderPath)) { Language.collectLanguageRootFolders += delegate(List<string> folders) { folders.Add(langFolderPath); }; } else { Log.Error("Lang folder not found: " + langFolderPath, "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\LanguageFolderHandler.cs", "Register", 21); } } } public static class LoadoutEnigmaCatalog { private static SkillFamily[] _enigmaSkillFamilies; [SystemInitializer(new Type[] { typeof(SkillCatalog), typeof(BodyCatalog), typeof(SurvivorCatalog), typeof(SurvivorSkillComponentResolver) })] private static void Init() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Invalid comparison between Unknown and I4 //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) List<SkillFamily> list = new List<SkillFamily>(SurvivorCatalog.survivorCount); SurvivorSkillComponentResolver.GetAllRequiredBodyComponentTypes(); foreach (SurvivorDef allSurvivorDef in SurvivorCatalog.allSurvivorDefs) { if (!Object.op_Implicit((Object)(object)allSurvivorDef) || allSurvivorDef.hidden || !Object.op_Implicit((Object)(object)allSurvivorDef.bodyPrefab)) { continue; } BodyIndex val = BodyCatalog.FindBodyIndex(allSurvivorDef.bodyPrefab); if ((int)val != -1) { SkillFamily val2 = ScriptableObject.CreateInstance<SkillFamily>(); ((Object)val2).name = BodyCatalog.GetBodyName(val) + "EnigmaFamily"; val2.defaultVariantIndex = 0u; val2.variants = (Variant[])(object)new Variant[3] { new Variant { skillDef = LoadoutEnigmaContent.SkillDefs.EnigmaDisabled }, new Variant { skillDef = LoadoutEnigmaContent.SkillDefs.EnigmaEnabled }, new Variant { skillDef = LoadoutEnigmaContent.SkillDefs.EnigmaEnabledSingleMode } }; ref GenericSkill[] reference = ref BodyCatalog.skillSlots[val]; GenericSkill val3 = allSurvivorDef.bodyPrefab.AddComponent<GenericSkill>(); val3.hideInCharacterSelect = true; SkillsAPI.SetOrderPriority(val3, -100); SkillsAPI.SetLoadoutTitleTokenOverride(val3, "LOADOUT_SKILL_ENIGMA"); val3._skillFamily = val2; val3.skillName = "Enigma"; GenericSkill[] array = reference; int num = 0; GenericSkill[] array2 = (GenericSkill[])(object)new GenericSkill[1 + array.Length]; ReadOnlySpan<GenericSkill> readOnlySpan = new ReadOnlySpan<GenericSkill>(array); readOnlySpan.CopyTo(new Span<GenericSkill>(array2).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; array2[num] = val3; num++; reference = array2; list.Add(val2); LoadoutEnigmaController loadoutEnigmaController = allSurvivorDef.bodyPrefab.AddComponent<LoadoutEnigmaController>(); loadoutEnigmaController.EnigmaSkillSlot = val3; ((Behaviour)loadoutEnigmaController).enabled = false; if (SkillSwapCompat.Enabled && !Object.op_Implicit((Object)(object)allSurvivorDef.bodyPrefab.GetComponent<HuntressTracker>())) { HuntressTracker obj = allSurvivorDef.bodyPrefab.AddComponent<HuntressTracker>(); ((Behaviour)obj).enabled = false; SurvivorSkillComponentResolver.PopulateSurvivorBodyComponent((Component)(object)obj); } } } if (list.Count > 0) { List<SkillFamily> list2 = new List<SkillFamily>(); list2.AddRange(SkillCatalog.allSkillFamilies); list2.AddRange(list); SkillCatalog.SetSkillFamilies(list2.ToArray()); } _enigmaSkillFamilies = list.ToArray(); Array.Sort(_enigmaSkillFamilies, SkillFamilyCatalogIndexComparer.Instance); } public static bool IsEnigmaSkillFamily(SkillFamily skillFamily) { return Array.BinarySearch(_enigmaSkillFamilies, skillFamily, SkillFamilyCatalogIndexComparer.Instance) >= 0; } } public class LoadoutEnigmaController : MonoBehaviour { private class SkillOverrideManager { public readonly GenericSkill SkillSlot; public EntityStateMachine LastActivationStateMachine; public bool IsSwitchPending; private SkillDef _currentOverrideSkill; private bool _isDisabled; public SkillDef CurrentOverrideSkill { get { return _currentOverrideSkill; } set { if (!((Object)(object)value == (Object)(object)_currentOverrideSkill)) { _currentOverrideSkill = value; resolveSkillOverride(); } } } public bool IsDisabled { get { return _isDisabled; } set { if (_isDisabled != value) { _isDisabled = value; resolveSkillOverride(); } } } public SkillDef ResolvedOverrideSkill { get; private set; } public bool ShouldSwitchSkill { get { if (IsSwitchPending) { if (Object.op_Implicit((Object)(object)LastActivationStateMachine)) { return LastActivationStateMachine.IsInMainState(); } return true; } return false; } } public event Action<SkillOverrideManager> OnSkillOverrideChanged; public SkillOverrideManager(GenericSkill skillSlot) { SkillSlot = skillSlot; } private void resolveSkillOverride() { SkillDef val = _currentOverrideSkill; if (_isDisabled) { val = LoadoutEnigmaContent.SkillDefs.DisabledSkill; } if (!((Object)(object)ResolvedOverrideSkill == (Object)(object)val)) { bool num = ResolvedOverrideSkill is DisabledSkillDef; float num2 = 1f; if (SkillSlot.maxStock > 0) { num2 = (float)SkillSlot.stock / (float)SkillSlot.maxStock; } if (Object.op_Implicit((Object)(object)ResolvedOverrideSkill)) { SkillSlot.UnsetSkillOverride((object)this, ResolvedOverrideSkill, (SkillOverridePriority)3); } ResolvedOverrideSkill = val; if (Object.op_Implicit((Object)(object)ResolvedOverrideSkill)) { SkillSlot.SetSkillOverride((object)this, ResolvedOverrideSkill, (SkillOverridePriority)3); } int num3 = Mathf.Min(SkillSlot.stock, Mathf.CeilToInt(num2 * (float)SkillSlot.maxStock)); if (num) { num3 = Mathf.Max(num3, Mathf.Min(SkillSlot.maxStock, 1)); } SkillSlot.stock = num3; this.OnSkillOverrideChanged?.Invoke(this); } } } public GenericSkill EnigmaSkillSlot; private CharacterBody _body; private SkillOverrideManager[] _skillOverrides = Array.Empty<SkillOverrideManager>(); private GenericSkill _currentSingleEnabledSkillSlot; private List<Behaviour> _requiredBodySkillComponents = new List<Behaviour>(); private bool _skillOverridesDirty; private EnigmaSkillDef currentEnigmaSkill { get { if (!Object.op_Implicit((Object)(object)EnigmaSkillSlot)) { return null; } return EnigmaSkillSlot.skillDef as EnigmaSkillDef; } } private unsafe void Awake() { //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) _body = ((Component)this).GetComponent<CharacterBody>(); int skillSlotCount = _body.skillLocator.skillSlotCount; if (!Object.op_Implicit((Object)(object)EnigmaSkillSlot)) { for (int i = 0; i < skillSlotCount; i++) { GenericSkill skillAtIndex = _body.skillLocator.GetSkillAtIndex(i); if (Object.op_Implicit((Object)(object)skillAtIndex) && Object.op_Implicit((Object)(object)skillAtIndex.skillFamily) && LoadoutEnigmaCatalog.IsEnigmaSkillFamily(skillAtIndex.skillFamily)) { EnigmaSkillSlot = skillAtIndex; break; } } } List<GenericSkill> list = new List<GenericSkill>(skillSlotCount); for (int j = 0; j < skillSlotCount; j++) { GenericSkill skillAtIndex2 = _body.skillLocator.GetSkillAtIndex(j); if (Object.op_Implicit((Object)(object)skillAtIndex2) && Object.op_Implicit((Object)(object)skillAtIndex2.skillFamily) && SkillCatalog.GetSkillFamilyName(skillAtIndex2.skillFamily.catalogIndex).Contains("Passive", StringComparison.OrdinalIgnoreCase)) { list.Add(skillAtIndex2); } } List<GenericSkill> list2 = new List<GenericSkill>(skillSlotCount); for (int k = 0; k < skillSlotCount; k++) { GenericSkill skillAtIndex3 = _body.skillLocator.GetSkillAtIndex(k); if ((Object)(object)skillAtIndex3 != (Object)(object)EnigmaSkillSlot && !list.Contains(skillAtIndex3)) { SerializableEntityStateType activationState = skillAtIndex3.activationState; if (((SerializableEntityStateType)(ref activationState)).stateType != typeof(Idle)) { list2.Add(skillAtIndex3); } } } _skillOverrides = new SkillOverrideManager[list2.Count]; for (int l = 0; l < _skillOverrides.Length; l++) { _skillOverrides[l] = new SkillOverrideManager(list2[l]); } ReadOnlyArray<Type> allRequiredBodyComponentTypes = SurvivorSkillComponentResolver.GetAllRequiredBodyComponentTypes(); LoadoutEnigma.Utilities.Extensions.CollectionExtensions.EnsureCapacity(_requiredBodySkillComponents, allRequiredBodyComponentTypes.Length); for (int m = 0; m < allRequiredBodyComponentTypes.Length; m++) { Component component = ((Component)this).GetComponent(Unsafe.Read<Type>((void*)allRequiredBodyComponentTypes[m])); if (Object.op_Implicit((Object)(object)component)) { Behaviour val = (Behaviour)(object)((component is Behaviour) ? component : null); if (val != null && !val.enabled) { val.enabled = true; val.enabled = false; _requiredBodySkillComponents.Add(val); } } } } private void OnEnable() { _body.onSkillActivatedAuthority += onSkillActivatedAuthority; SkillOverrideManager[] skillOverrides = _skillOverrides; for (int i = 0; i < skillOverrides.Length; i++) { skillOverrides[i].OnSkillOverrideChanged += onSkillOverrideChanged; } SetRandomSkills(); } private void OnDisable() { _body.onSkillActivatedAuthority -= onSkillActivatedAuthority; SkillOverrideManager[] skillOverrides = _skillOverrides; foreach (SkillOverrideManager obj in skillOverrides) { obj.OnSkillOverrideChanged -= onSkillOverrideChanged; obj.LastActivationStateMachine = null; obj.IsSwitchPending = false; obj.CurrentOverrideSkill = null; obj.IsDisabled = false; } } private void onSkillOverrideChanged(SkillOverrideManager overrideManager) { _skillOverridesDirty = true; } private void onSkillActivatedAuthority(GenericSkill skill) { GenericSkill val = skill; EntityStateMachine stateMachine = val.stateMachine; if (val.currentSkillOverride != -1) { GenericSkill val2 = null; SkillOverride safe = ArrayUtils.GetSafe<SkillOverride>(val.skillOverrides, val.currentSkillOverride); if (safe != null) { object source = safe.source; ToolbotDualWieldBase val3 = (ToolbotDualWieldBase)((source is ToolbotDualWieldBase) ? source : null); if (val3 == null) { if (source is SkillOverrideManager) { val2 = val; } } else if ((Object)(object)val == (Object)(object)_body.skillLocator.secondary) { val2 = val3.primary2Slot; } } if (!Object.op_Implicit((Object)(object)val2)) { return; } val = val2; } SkillOverrideManager skillOverrideManager = findSlotOverrideManager(val); if (skillOverrideManager == null) { Log.Warning($"Failed to find override manager for activated skill {SkillCatalog.GetSkillName(val.skillDef.skillIndex)} on {_body}", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\LoadoutEnigmaController.cs", "onSkillActivatedAuthority", 165); return; } skillOverrideManager.LastActivationStateMachine = stateMachine; skillOverrideManager.IsSwitchPending = true; } private void FixedUpdate() { if (!_body.hasEffectiveAuthority) { return; } SkillOverrideManager[] skillOverrides = _skillOverrides; foreach (SkillOverrideManager skillOverrideManager in skillOverrides) { if (!Object.op_Implicit((Object)(object)skillOverrideManager.CurrentOverrideSkill)) { continue; } bool flag = false; SkillDef currentOverrideSkill = skillOverrideManager.CurrentOverrideSkill; CaptainOrbitalSkillDef val = (CaptainOrbitalSkillDef)(object)((currentOverrideSkill is CaptainOrbitalSkillDef) ? currentOverrideSkill : null); if (val != null && !val.isAvailable) { flag = true; } SkillDef currentOverrideSkill2 = skillOverrideManager.CurrentOverrideSkill; CaptainSupplyDropSkillDef val2 = (CaptainSupplyDropSkillDef)(object)((currentOverrideSkill2 is CaptainSupplyDropSkillDef) ? currentOverrideSkill2 : null); if (val2 != null) { bool flag2 = false; string[] supplyDropSkillSlotNames = val2.supplyDropSkillSlotNames; foreach (string text in supplyDropSkillSlotNames) { GenericSkill val3 = _body.skillLocator.FindSkill(text); if (Object.op_Implicit((Object)(object)val3) && val3.IsReady()) { flag2 = true; } } if (!flag2) { flag = true; } } if (flag) { skillOverrideManager.IsSwitchPending = true; } } handlePendingSkillActivations(); if (_skillOverridesDirty) { _skillOverridesDirty = false; refreshRequiredSkillComponents(); } } public void SetRandomSkills() { SkillOverrideManager[] skillOverrides = _skillOverrides; for (int i = 0; i < skillOverrides.Length; i++) { skillOverrides[i].IsSwitchPending = true; } } private void refreshRequiredSkillComponents() { HashSet<Type> hashSet = new HashSet<Type>(); SkillOverrideManager[] skillOverrides = _skillOverrides; foreach (SkillOverrideManager skillOverrideManager in skillOverrides) { if (Object.op_Implicit((Object)(object)skillOverrideManager.CurrentOverrideSkill)) { Type[] requiredBodyComponentTypes = SurvivorSkillComponentResolver.GetRequiredBodyComponentTypes(skillOverrideManager.CurrentOverrideSkill); hashSet.UnionWith(requiredBodyComponentTypes); } } foreach (Behaviour requiredBodySkillComponent in _requiredBodySkillComponents) { if (Object.op_Implicit((Object)(object)requiredBodySkillComponent)) { requiredBodySkillComponent.enabled = hashSet.Contains(((object)requiredBodySkillComponent).GetType()); } } } private void handlePendingSkillActivations() { bool flag = false; SkillOverrideManager[] skillOverrides = _skillOverrides; foreach (SkillOverrideManager skillOverrideManager in skillOverrides) { if (skillOverrideManager.ShouldSwitchSkill) { skillOverrideManager.IsSwitchPending = false; SkillDef currentOverrideSkill = pickNextSkill(skillOverrideManager); skillOverrideManager.CurrentOverrideSkill = currentOverrideSkill; flag = true; } } if (flag) { updateSingleEnabledSkillSlot(); } } private SkillDef pickNextSkill(SkillOverrideManager overrideManager) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) if (overrideManager == null || !Object.op_Implicit((Object)(object)overrideManager.SkillSlot) || !Object.op_Implicit((Object)(object)overrideManager.SkillSlot.skillFamily)) { return null; } List<SkillDef> list = new List<SkillDef>(overrideManager.SkillSlot.skillFamily.variants.Length); NetworkUser val = Util.LookUpBodyNetworkUser(_body); LocalUser val2 = (Object.op_Implicit((Object)(object)val) ? val.localUser : null); Variant[] variants = overrideManager.SkillSlot.skillFamily.variants; foreach (Variant val3 in variants) { if ((Object)(object)val3.skillDef == (Object)(object)overrideManager.CurrentOverrideSkill || LoadoutEnigmaPlugin.SkillBlacklist.Contains(val3.skillDef.skillIndex)) { continue; } bool flag = true; if (Object.op_Implicit((Object)(object)val3.unlockableDef)) { if (val2 != null && val2.userProfile != null) { flag = val2.userProfile.HasUnlockable(val3.unlockableDef); } else if (Object.op_Implicit((Object)(object)val)) { flag = val.unlockables.Contains(val3.unlockableDef); } else { Log.Error($"Failed to determine unlockable status for skill variant {val3.skillDef}. Assuming not unlocked.", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\LoadoutEnigmaController.cs", "pickNextSkill", 313); flag = false; } } if (!flag) { continue; } Type[] requiredBodyComponentTypes = SurvivorSkillComponentResolver.GetRequiredBodyComponentTypes(val3.skillDef); bool flag2 = false; Type[] array = requiredBodyComponentTypes; foreach (Type type in array) { if (!Object.op_Implicit((Object)(object)((Component)this).GetComponent(type))) { flag2 = true; break; } } if (!flag2) { list.Add(val3.skillDef); } } if (list.Count == 0) { SkillDef item = overrideManager.SkillSlot.baseSkill; if (Object.op_Implicit((Object)(object)overrideManager.CurrentOverrideSkill)) { item = overrideManager.CurrentOverrideSkill; } list.Add(item); } return list[Random.Range(0, list.Count)]; } private void updateSingleEnabledSkillSlot() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 bool flag = false; if (Object.op_Implicit((Object)(object)currentEnigmaSkill)) { flag = currentEnigmaSkill.SingleSkillMode; } GenericSkill val = (flag ? pickNextSingleEnabledSkillSlot() : null); SkillOverrideManager[] skillOverrides = _skillOverrides; foreach (SkillOverrideManager skillOverrideManager in skillOverrides) { bool flag2 = (int)_body.skillLocator.FindSkillSlot(skillOverrideManager.SkillSlot) != -1; bool flag3 = !Object.op_Implicit((Object)(object)val) || (Object)(object)skillOverrideManager.SkillSlot == (Object)(object)val; skillOverrideManager.IsDisabled = flag2 && !flag3; } _currentSingleEnabledSkillSlot = val; } private GenericSkill pickNextSingleEnabledSkillSlot() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) List<GenericSkill> list = new List<GenericSkill>(_body.skillLocator.skillSlotCount); SkillSlot val = (SkillSlot)0; while ((int)val <= 3) { GenericSkill skill = _body.skillLocator.GetSkill(val); if (Object.op_Implicit((Object)(object)skill)) { list.Add(skill); } val = (SkillSlot)(sbyte)(val + 1); } if (list.Count == 0) { list.Add(_currentSingleEnabledSkillSlot); } return list[Random.Range(0, list.Count)]; } private SkillOverrideManager findSlotOverrideManager(GenericSkill skillSlot) { SkillOverrideManager[] skillOverrides = _skillOverrides; foreach (SkillOverrideManager skillOverrideManager in skillOverrides) { if ((Object)(object)skillOverrideManager.SkillSlot == (Object)(object)skillSlot) { return skillOverrideManager; } } return null; } } [BepInPlugin("Gorakh.LoadoutEnigma", "LoadoutEnigma", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class LoadoutEnigmaPlugin : BaseUnityPlugin { public const string PluginGUID = "Gorakh.LoadoutEnigma"; public const string PluginAuthor = "Gorakh"; public const string PluginName = "LoadoutEnigma"; public const string PluginVersion = "1.0.0"; private static LoadoutEnigmaPlugin _instance; internal static LoadoutEnigmaPlugin Instance => _instance; public static ConfigEntry<string> SkillBlacklistConfig { get; internal set; } public static ConfigSkillIndexList SkillBlacklist { get; private set; } private void Awake() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown Stopwatch stopwatch = Stopwatch.StartNew(); SingletonHelper.Assign<LoadoutEnigmaPlugin>(ref _instance, this); Log.Init(((BaseUnityPlugin)this).Logger); SkillBlacklistConfig = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Skill Blacklist", "ToolbotBodySwap,ToolbotDualWield", new ConfigDescription("A comma-separated list of skills to exclude from Loadout Enigma", (AcceptableValueBase)null, Array.Empty<object>())); SkillBlacklist = new ConfigSkillIndexList(SkillBlacklistConfig); new LoadoutEnigmaContent().Register(); LanguageFolderHandler.Register(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location)); if (RiskOfOptionsCompat.Enabled) { RiskOfOptionsCompat.AddOptions(); } if (SkillSwapCompat.Enabled) { SkillSwapCompat.Init(); } SurvivorSkillComponentResolver.PreCatalogInit(); SystemInitializerInjector.InjectDependency(typeof(Loadout), typeof(LoadoutEnigmaCatalog)); SystemInitializerInjector.InjectDependency(typeof(BodyLoadoutManager), typeof(LoadoutEnigmaCatalog)); stopwatch.Stop(); Log.Message_NoCallerPrefix($"Initialized in {stopwatch.Elapsed.TotalMilliseconds:F0}ms"); } private void OnDestroy() { SingletonHelper.Unassign<LoadoutEnigmaPlugin>(ref _instance, this); } } internal static class LoadoutPanelHooks { } internal static class Log { private static readonly StringBuilder _sharedStringBuilder; private static readonly int _cachedCallerPathPrefixLength; private static ManualLogSource _logSource; static Log() { _sharedStringBuilder = new StringBuilder(256); _cachedCallerPathPrefixLength = getCallerPathPrefixLength("X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\Log.cs"); static int getCallerPathPrefixLength([CallerFilePath] string callerPath = null) { int num = callerPath.LastIndexOf("LoadoutEnigma\\"); if (num >= 0) { return num + "LoadoutEnigma\\".Length; } Debug.LogError((object)"[LoadoutEnigma] Logger failed to determine caller path prefix length"); return 0; } } internal static void Init(ManualLogSource logSource) { _logSource = logSource; } private static StringBuilder AppendCallerPrefix(this StringBuilder stringBuilder, string callerPath, string callerMemberName, int callerLineNumber) { return stringBuilder.Append(callerPath, _cachedCallerPathPrefixLength, callerPath.Length - _cachedCallerPathPrefixLength).Append(':').Append(callerLineNumber) .Append(" (") .Append(callerMemberName) .Append("):"); } private static StringBuilder buildCallerLogString(string callerPath, string callerMemberName, int callerLineNumber, object data) { return _sharedStringBuilder.Clear().AppendCallerPrefix(callerPath, callerMemberName, callerLineNumber).Append(' ') .Append(data); } [Conditional("DEBUG")] internal static void Debug(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogDebug((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Conditional("DEBUG")] internal static void Debug_NoCallerPrefix(object data) { _logSource.LogDebug(data); } internal static void Error(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogError((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Error_NoCallerPrefix(object data) { _logSource.LogError(data); } internal static void Fatal(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogFatal((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Fatal_NoCallerPrefix(object data) { _logSource.LogFatal(data); } internal static void Info(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogInfo((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Info_NoCallerPrefix(object data) { _logSource.LogInfo(data); } internal static void Message(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogMessage((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Message_NoCallerPrefix(object data) { _logSource.LogMessage(data); } internal static void Warning(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogWarning((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Warning_NoCallerPrefix(object data) { _logSource.LogWarning(data); } internal static void LogType(LogLevel level, object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if ((level & 0x20) == 0) { _logSource.Log(level, (object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void LogType_NoCallerPrefix(LogLevel level, object data) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if ((level & 0x20) == 0) { _logSource.Log(level, data); } } } public static class SurvivorSkillComponentResolver { private static Type[] _allBodyComponentTypes = Array.Empty<Type>(); private static readonly Dictionary<int, Type[]> _requiredBodyComponentsBySkillIndex = new Dictionary<int, Type[]>(); private static readonly Dictionary<Type, Dictionary<FieldInfo, object>> _bodyComponentDefaultValues = new Dictionary<Type, Dictionary<FieldInfo, object>>(); public static void PreCatalogInit() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!SkillSwapCompat.Enabled) { return; } Addressables.LoadAssetAsync<GameObject>((object)"RoR2/DLC1/VoidSurvivor/VoidSurvivorBody.prefab").CallOnSuccess(delegate(GameObject voidFieldBody) { VoidSurvivorController templateComponent = default(VoidSurvivorController); if (voidFieldBody.TryGetComponent<VoidSurvivorController>(ref templateComponent)) { recordSurvivorComponentTemplateValues((Component)(object)templateComponent); } }); } [SystemInitializer(new Type[] { typeof(SkillCatalog), typeof(SurvivorCatalog) })] private static void Init() { HashSet<Type> hashSet = new HashSet<Type>(); _requiredBodyComponentsBySkillIndex.Clear(); int num; Type[] array; foreach (SkillDef allSkillDef in SkillCatalog.allSkillDefs) { HashSet<Type> hashSet2 = new HashSet<Type>(); if (allSkillDef is HuntressTrackingSkillDef) { hashSet2.Add(typeof(HuntressTracker)); } if (allSkillDef is VoidSurvivorSkillDef) { hashSet2.Add(typeof(VoidSurvivorController)); } switch (SkillCatalog.GetSkillName(allSkillDef.skillIndex)) { case "ChefDice": case "ChefSear": case "ChefDiceBoosted": case "ChefSearBoosted": case "ChefRolyPolyBoosted": case "ChefRolyPoly": case "YesChef": hashSet2.Add(typeof(ChefController)); break; case "SeekerBodyMeditate2": case "SeekerBodySoulSpiral": case "SeekerBodySojourn": hashSet2.Add(typeof(SeekerController)); break; case "FalseSonBodyClub": hashSet2.Add(typeof(FalseSonController)); break; } if (hashSet2.Count > 0) { int skillIndex = allSkillDef.skillIndex; num = 0; array = new Type[hashSet2.Count]; foreach (Type item in hashSet2) { array[num] = item; num++; } _requiredBodyComponentsBySkillIndex[skillIndex] = array; } hashSet.UnionWith(hashSet2); } Component val2 = default(Component); foreach (Type item2 in hashSet) { if (_bodyComponentDefaultValues.ContainsKey(item2)) { continue; } Component val = null; foreach (SurvivorDef allSurvivorDef in SurvivorCatalog.allSurvivorDefs) { if (Object.op_Implicit((Object)(object)allSurvivorDef) && Object.op_Implicit((Object)(object)allSurvivorDef.bodyPrefab) && allSurvivorDef.bodyPrefab.TryGetComponent(item2, ref val2)) { val = val2; } } if (!Object.op_Implicit((Object)(object)val)) { Log.Warning("No template component found for " + item2.FullName, "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\SurvivorSkillComponentResolver.cs", "Init", 105); } else { recordSurvivorComponentTemplateValues(val); } } num = 0; array = new Type[hashSet.Count]; foreach (Type item3 in hashSet) { array[num] = item3; num++; } _allBodyComponentTypes = array; } private static void recordSurvivorComponentTemplateValues(Component templateComponent) { if (!Object.op_Implicit((Object)(object)templateComponent)) { throw new ArgumentNullException("templateComponent"); } Type type = ((object)templateComponent).GetType(); List<FieldInfo> list = new List<FieldInfo>(); FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if ((fieldInfo.IsPublic || fieldInfo.GetCustomAttribute(typeof(SerializeField)) != null) && fieldInfo.GetCustomAttribute(typeof(NonSerializedAttribute)) == null) { list.Add(fieldInfo); } } if (list.Count == 0) { Log.Warning("No serializable fields found for " + type.FullName, "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\SurvivorSkillComponentResolver.cs", "recordSurvivorComponentTemplateValues", 134); return; } Dictionary<FieldInfo, object> dictionary = new Dictionary<FieldInfo, object>(list.Count); foreach (FieldInfo item in list) { object value; try { value = item.GetValue(templateComponent); } catch (Exception ex) { Log.Error_NoCallerPrefix($"Failed to get template value of field {item.DeclaringType.FullName}.{item.Name} from {templateComponent}: {ex}"); continue; } dictionary[item] = value; } _bodyComponentDefaultValues[type] = dictionary; } public static Type[] GetRequiredBodyComponentTypes(SkillDef skill) { if (!Object.op_Implicit((Object)(object)skill)) { return Array.Empty<Type>(); } return GetRequiredBodyComponentTypes(skill.skillIndex); } public static Type[] GetRequiredBodyComponentTypes(int skillIndex) { if (!_requiredBodyComponentsBySkillIndex.TryGetValue(skillIndex, out var value)) { return Array.Empty<Type>(); } return value; } public static ReadOnlyArray<Type> GetAllRequiredBodyComponentTypes() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return new ReadOnlyArray<Type>(_allBodyComponentTypes); } public static void PopulateSurvivorBodyComponent(Component component) { if (!Object.op_Implicit((Object)(object)component) || !_bodyComponentDefaultValues.TryGetValue(((object)component).GetType(), out var value)) { return; } foreach (KeyValuePair<FieldInfo, object> item in value) { item.Deconstruct(out var key, out var value2); try { key.SetValue(component, value2); } catch (Exception ex) { Log.Error_NoCallerPrefix($"Failed to populate field {key.DeclaringType.FullName}.{key.Name} on {component}: {ex}"); } } } } internal static class ToolbotDualWieldStancePatch { [CompilerGenerated] private static class <>O { public static Manipulator <0>__ToolbotDualWieldBase_OnEnter; public static Action<ToolbotDualWieldBase> <1>__onPrimarySlotsAssigned; } [SystemInitializer(new Type[] { })] private static void Init() { //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_001b: Expected O, but got Unknown object obj = <>O.<0>__ToolbotDualWieldBase_OnEnter; if (obj == null) { Manipulator val = ToolbotDualWieldBase_OnEnter; <>O.<0>__ToolbotDualWieldBase_OnEnter = val; obj = (object)val; } ToolbotDualWieldBase.OnEnter += (Manipulator)obj; } private static void ToolbotDualWieldBase_OnEnter(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); Instruction val2 = null; Instruction val3 = null; ILCursor[] array = default(ILCursor[]); if (val.TryFindNext(ref array, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)AccessTools.DeclaredPropertySetter(typeof(ToolbotDualWieldBase), "primary1Slot")) })) { val2 = array[0].Next; } if (val.TryFindNext(ref array, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)AccessTools.DeclaredPropertySetter(typeof(ToolbotDualWieldBase), "primary2Slot")) })) { val3 = array[0].Next; } Instruction val4 = null; if (val2 != null && val3 != null) { int num = il.Instrs.IndexOf(val2); val4 = ((il.Instrs.IndexOf(val3) > num) ? val3 : val2); } else { val4 = val2 ?? val3; } if (val4 == null) { Log.Error("Failed to find patch location", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\ToolbotDualWieldStancePatch.cs", "ToolbotDualWieldBase_OnEnter", 53); return; } val.Goto(val4, (MoveType)2, false); val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Action<ToolbotDualWieldBase>>((Action<ToolbotDualWieldBase>)onPrimarySlotsAssigned); static void onPrimarySlotsAssigned(ToolbotDualWieldBase state) { bool flag = false; EntityStateMachine val5 = EntityStateMachine.FindByCustomName(((EntityState)state).gameObject, "Stance"); if (Object.op_Implicit((Object)(object)val5) && val5.state is ToolbotStanceB) { flag = true; } if (flag) { GenericSkill primary2Slot = state.primary2Slot; GenericSkill primary1Slot = state.primary1Slot; state.primary1Slot = primary2Slot; state.primary2Slot = primary1Slot; } } } } public sealed class ToolbotSkillSwitchFix : MonoBehaviour { private CharacterBody _body; private EntityStateMachine _bodyStateMachine; private EntityStateMachine _stanceStateMachine; private GenericSkill _primary1Slot; private GenericSkill _primary2Slot; [SystemInitializer(new Type[] { typeof(BodyCatalog) })] private static void Init() { GameObject val = BodyCatalog.FindBodyPrefab("ToolbotBody"); if (Object.op_Implicit((Object)(object)val)) { val.AddComponent<ToolbotSkillSwitchFix>(); } else { Log.Warning("Failed to find MUL-T body prefab", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\ToolbotSkillSwitchFix.cs", "Init", 20); } } private void Awake() { _body = ((Component)this).GetComponent<CharacterBody>(); _bodyStateMachine = EntityStateMachine.FindByCustomName(((Component)this).gameObject, "Body"); _stanceStateMachine = EntityStateMachine.FindByCustomName(((Component)this).gameObject, "Stance"); if (Object.op_Implicit((Object)(object)_body.skillLocator)) { _primary1Slot = _body.skillLocator.FindSkillByFamilyName("ToolbotBodyPrimary1"); _primary2Slot = _body.skillLocator.FindSkillByFamilyName("ToolbotBodyPrimary2"); } } private void OnEnable() { GenericSkillHooks.OnSkillChangedGlobal += onSkillChangedGlobal; } private void OnDisable() { GenericSkillHooks.OnSkillChangedGlobal -= onSkillChangedGlobal; } private void onSkillChangedGlobal(GenericSkill skill, SkillDef previousSkill, SkillDef newSkill) { if (Object.op_Implicit((Object)(object)skill) && ((Object)(object)skill == (Object)(object)_primary1Slot || (Object)(object)skill == (Object)(object)_primary2Slot)) { fixDualWieldSkillOverrides(skill, previousSkill, newSkill); } } private void fixDualWieldSkillOverrides(GenericSkill changedSkill, SkillDef prev, SkillDef current) { GenericSkill secondary = _body.skillLocator.secondary; bool flag = false; for (int i = 0; i < secondary.skillOverrides.Length; i++) { SkillOverride val = secondary.skillOverrides[i]; if (val != null) { object source = val.source; ToolbotDualWieldBase val2 = (ToolbotDualWieldBase)((source is ToolbotDualWieldBase) ? source : null); if (val2 != null && (Object)(object)changedSkill == (Object)(object)val2.primary2Slot && (Object)(object)val.skillDef == (Object)(object)prev) { val.skillDef = current; flag = true; } } } if (flag) { secondary.PickCurrentOverride(); } } private void onPrimaryBaseSkillChanged(GenericSkill primary, SkillDef prev, SkillDef current) { EntityState state = _stanceStateMachine.state; ToolbotStanceBase val = (ToolbotStanceBase)(object)((state is ToolbotStanceBase) ? state : null); if (val != null) { ToolbotWeaponSkillDef val2 = (ToolbotWeaponSkillDef)(object)((current is ToolbotWeaponSkillDef) ? current : null); if (Object.op_Implicit((Object)(object)val2)) { val.SendWeaponStanceToAnimator(val2); ((EntityState)val).PlayAnimation("Stance, Additive", val2.entryAnimState); } val.UpdateCrosshairParameters(val2); } } } } namespace LoadoutEnigma.Utilities { public static class FileUtils { public static FileInfo SearchUpwards(DirectoryInfo startDir, DirectoryInfo endDir, string searchPattern) { if (startDir == null) { throw new ArgumentNullException("startDir"); } if (endDir == null) { throw new ArgumentNullException("endDir"); } if (string.IsNullOrEmpty(searchPattern)) { throw new ArgumentException("'searchPattern' cannot be null or empty.", "searchPattern"); } if (!startDir.IsChildOf(endDir)) { return null; } for (DirectoryInfo directoryInfo = startDir; directoryInfo != null; directoryInfo = directoryInfo.Parent) { FileInfo fileInfo = directoryInfo.EnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly).FirstOrDefault(); if (fileInfo != null) { return fileInfo; } if (string.Equals(directoryInfo.FullName, endDir.FullName, StringComparison.OrdinalIgnoreCase)) { break; } } return null; } public static FileInfo SearchUpwards(DirectoryInfo startDir, string searchPattern) { return SearchUpwards(startDir, startDir.Root, searchPattern); } } public sealed class SkillFamilyCatalogIndexComparer : IComparer<SkillFamily> { public static readonly SkillFamilyCatalogIndexComparer Instance = new SkillFamilyCatalogIndexComparer(); public int Compare(SkillFamily x, SkillFamily y) { return x.catalogIndex.CompareTo(y.catalogIndex); } } } namespace LoadoutEnigma.Utilities.Extensions { public static class AssetLoadExtensions { public static void CallOnSuccess<T>(this AsyncOperationHandle<T> handle, Action<T> onSuccess) { handle.Completed += delegate(AsyncOperationHandle<T> handle) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)handle.Status == 2) { Log.Error("Failed to load asset '" + handle.LocationName + "'", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\Utilities\\Extensions\\AssetLoadExtensions.cs", "CallOnSuccess", 19); } else { onSuccess(handle.Result); } }; } } public static class CollectionExtensions { public static void EnsureCapacity<T>(this List<T> list, int capacity) { if (list.Capacity < capacity) { list.Capacity = capacity; } } } public static class FileExtensions { public static bool IsChildOf(this DirectoryInfo dir, DirectoryInfo other) { if (dir != null && other != null) { return dir.FullName.StartsWith(other.FullName, ignoreCase: true, CultureInfo.InvariantCulture); } return false; } } public static class PatchExtensions { public static void EmitSkipMethodCall(this ILCursor c, MethodDefinition method = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) c.EmitSkipMethodCall(OpCodes.Br, method); } public static void EmitSkipMethodCall(this ILCursor c, OpCode branchOpCode, MethodDefinition method = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) c.EmitSkipMethodCall(branchOpCode, null, method); } public static void EmitSkipMethodCall(this ILCursor c, OpCode branchOpCode, Action<ILCursor> emitSkippedReturnValue, MethodDefinition method = null) { //IL_0010: 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_001f: Invalid comparison between Unknown and I4 //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) if (c == null) { throw new ArgumentNullException("c"); } if ((int)((OpCode)(ref branchOpCode)).FlowControl != 0 && (int)((OpCode)(ref branchOpCode)).FlowControl != 3) { throw new ArgumentException($"Invalid branch OpCode: {branchOpCode}"); } if (method == null) { MethodReference val = default(MethodReference); if (!ILPatternMatchingExt.MatchCallOrCallvirt(c.Next, ref val)) { Log.Error($"Failed to find method call to skip: {((MemberReference)c.Context.Method).FullName} at instruction {c.Next} ({c.Index})", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\Utilities\\Extensions\\PatchExtensions.cs", "EmitSkipMethodCall", 33); return; } method = Extensions.SafeResolve(val); if (method == null) { Log.Error($"Failed to resolve method '{((MemberReference)val).FullName}': {((MemberReference)c.Context.Method).FullName} at instruction {c.Next} ({c.Index})", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\Utilities\\Extensions\\PatchExtensions.cs", "EmitSkipMethodCall", 41); return; } } int num = ((MethodReference)method).Parameters.Count + ((!method.IsStatic) ? 1 : 0); bool flag = Extensions.Is((MemberReference)(object)((MethodReference)method).ReturnType, (MemberInfo)typeof(void)); ILLabel val2 = c.DefineLabel(); c.Emit(branchOpCode, (object)val2); int index = c.Index; c.Index = index + 1; if (num > 0 || !flag) { ILLabel val3 = c.DefineLabel(); c.Emit(OpCodes.Br, (object)val3); c.MarkLabel(val2); for (int i = 0; i < num; i++) { c.Emit(OpCodes.Pop); } if (emitSkippedReturnValue != null) { emitSkippedReturnValue(c); } else if (!flag) { Log.Warning($"Skipped method ({((MemberReference)method).FullName}) is not void, emitting default value: {((MemberReference)c.Context.Method).FullName} at instruction {c.Next} ({c.Index})", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\Utilities\\Extensions\\PatchExtensions.cs", "EmitSkipMethodCall", 73); if (((MethodReference)method).ReturnType.IsValueType) { VariableDefinition val4 = c.Context.AddVariable(((MethodReference)method).ReturnType); c.Emit(OpCodes.Ldloca, val4); c.Emit(OpCodes.Initobj, ((MethodReference)method).ReturnType); c.Emit(OpCodes.Ldloc, val4); } else { c.Emit(OpCodes.Ldnull); } } c.MarkLabel(val3); } else { c.MarkLabel(val2); } } public static bool TryFindParameter(this MethodReference method, Type type, string name, out ParameterDefinition parameter) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<ParameterDefinition> enumerator = method.Parameters.GetEnumerator(); try { while (enumerator.MoveNext()) { ParameterDefinition current = enumerator.Current; if ((string.IsNullOrEmpty(name) || ((ParameterReference)current).Name == name) && (type == null || Extensions.Is((MemberReference)(object)((ParameterReference)current).ParameterType, (MemberInfo)type))) { parameter = current; return true; } } } finally { ((IDisposable)enumerator).Dispose(); } parameter = null; return false; } public static bool TryFindParameter(this MethodReference method, string name, out ParameterDefinition parameter) { return method.TryFindParameter(null, name, out parameter); } public static bool TryFindParameter(this MethodReference method, Type type, out ParameterDefinition parameter) { return method.TryFindParameter(type, null, out parameter); } public static bool TryFindParameter<T>(this MethodReference method, string name, out ParameterDefinition parameter) { return method.TryFindParameter(typeof(T), name, out parameter); } public static bool TryFindParameter<T>(this MethodReference method, out ParameterDefinition parameter) { return method.TryFindParameter(typeof(T), null, out parameter); } public static VariableDefinition AddVariable(this ILContext context, TypeReference variableType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown VariableDefinition val = new VariableDefinition(variableType); context.Method.Body.Variables.Add(val); return val; } public static VariableDefinition AddVariable(this ILContext context, Type variableType) { return context.AddVariable(context.Import(variableType)); } public static VariableDefinition AddVariable<T>(this ILContext context) { return context.AddVariable(context.Import(typeof(T))); } public static void EmitStoreStack(this ILCursor cursor, params VariableDefinition[] variables) { //IL_002a: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (cursor == null) { throw new ArgumentNullException("cursor"); } if (variables == null) { throw new ArgumentNullException("variables"); } if (variables.Length != 0) { for (int num = variables.Length - 1; num >= 1; num--) { cursor.Emit(OpCodes.Stloc, variables[num]); } cursor.Emit(OpCodes.Dup); cursor.Emit(OpCodes.Stloc, variables[0]); for (int i = 1; i < variables.Length; i++) { cursor.Emit(OpCodes.Ldloc, variables[i]); } } } } } namespace LoadoutEnigma.ModCompatibility { internal static class RiskOfOptionsCompat { private static Sprite _iconSprite; private const string MOD_GUID = "Gorakh.LoadoutEnigma"; private const string MOD_NAME = "LoadoutEnigma"; public static bool Enabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"); [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void AddOptions() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown ModSettingsManager.SetModDescription("Options for LoadoutEnigma", "Gorakh.LoadoutEnigma", "LoadoutEnigma"); Sprite val = tryGetIcon(); if (Object.op_Implicit((Object)(object)val)) { ModSettingsManager.SetModIcon(val, "Gorakh.LoadoutEnigma", "LoadoutEnigma"); } ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(LoadoutEnigmaPlugin.SkillBlacklistConfig)); } private static Sprite tryGetIcon() { if (!Object.op_Implicit((Object)(object)_iconSprite)) { _iconSprite = tryGenerateIcon(); if (!Object.op_Implicit((Object)(object)_iconSprite)) { Log.Warning("Failed to get config icon", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\ModCompatibility\\RiskOfOptionsCompat.cs", "tryGetIcon", 43); } } return _iconSprite; } private static Sprite tryGenerateIcon() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) DirectoryInfo startDir = new DirectoryInfo(Path.GetDirectoryName(((BaseUnityPlugin)LoadoutEnigmaPlugin.Instance).Info.Location)); DirectoryInfo endDir = new DirectoryInfo(Paths.PluginPath); FileInfo fileInfo = FileUtils.SearchUpwards(startDir, endDir, "icon.png"); if (fileInfo == null) { return null; } byte[] array; try { array = File.ReadAllBytes(fileInfo.FullName); } catch (Exception arg) { Log.Error_NoCallerPrefix($"Failed to read icon file '{fileInfo.FullName}': {arg}"); return null; } Texture2D val = new Texture2D(256, 256); ((Object)val).name = "texLoadoutEnigmaIcon"; if (!ImageConversion.LoadImage(val, array)) { Object.Destroy((Object)(object)val); Log.Error("Failed to load icon into texture", "X:\\Git\\RoR2\\LoadoutEnigma\\LoadoutEnigma\\ModCompatibility\\RiskOfOptionsCompat.cs", "tryGenerateIcon", 77); return null; } Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)obj).name = "LoadoutEnigmaIcon"; return obj; } } internal static class SkillSwapCompat { private class DummyClass { } [CompilerGenerated] private static class <>O { public static hook_FromSkillSlot <0>__Row_FromSkillSlot; public static hook_Rebuild <1>__LoadoutPanelController_Rebuild; } public const string PLUGIN_GUID = "pseudopulse.SkillSwap"; private static readonly FixedConditionalWeakTable<Row, DummyClass> _enigmaRows = new FixedConditionalWeakTable<Row, DummyClass>(); public static bool Enabled => Chainloader.PluginInfos.ContainsKey("pseudopulse.SkillSwap"); [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void Init() { //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_001b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown object obj = <>O.<0>__Row_FromSkillSlot; if (obj == null) { hook_FromSkillSlot val = Row_FromSkillSlot; <>O.<0>__Row_FromSkillSlot = val; obj = (object)val; } Row.FromSkillSlot += (hook_FromSkillSlot)obj; object obj2 = <>O.<1>__LoadoutPanelController_Rebuild; if (obj2 == null) { hook_Rebuild val2 = LoadoutPanelController_Rebuild; <>O.<1>__LoadoutPanelController_Rebuild = val2; obj2 = (object)val2; } LoadoutPanelController.Rebuild += (hook_Rebuild)obj2; } private static object Row_FromSkillSlot(orig_FromSkillSlot orig, LoadoutPanelController owner, BodyIndex bodyIndex, int skillSlotIndex, GenericSkill skillSlot) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) object obj = orig.Invoke(owner, bodyIndex, skillSlotIndex, skillSlot); Row val = (Row)((obj is Row) ? obj : null); if (val != null && LoadoutEnigmaCatalog.IsEnigmaSkillFamily(skillSlot.skillFamily)) { _enigmaRows.Add(val, new DummyClass()); } return obj; } private static void LoadoutPanelController_Rebuild(orig_Rebuild orig, LoadoutPanelController self) { orig.Invoke(self); DummyClass dummyClass = default(DummyClass); for (int i = 0; i < self.rows.Count; i++) { Row val = self.rows[i]; if (_enigmaRows.TryGetValue(val, ref dummyClass)) { self.rows.RemoveAt(i); self.rows.Insert(0, val); ((Transform)val.rowPanelTransform).SetAsFirstSibling(); } } } } } namespace LoadoutEnigma.Content { public class DisabledSkillDef : SkillDef { public override bool CanExecute(GenericSkill skillSlot) { return false; } public override bool IsReady(GenericSkill skillSlot) { return false; } } public class EnigmaSkillDef : SkillDef { private class InstanceData : BaseSkillInstanceData, IDisposable { public readonly LoadoutEnigmaController EnigmaController; public InstanceData(GenericSkill skillSlot) { EnigmaController = ((Component)skillSlot.characterBody).GetComponent<LoadoutEnigmaController>(); if (Object.op_Implicit((Object)(object)EnigmaController)) { ((Behaviour)EnigmaController).enabled = true; } } public void Dispose() { if (Object.op_Implicit((Object)(object)EnigmaController)) { ((Behaviour)EnigmaController).enabled = false; } } } public bool SingleSkillMode; public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) { return (BaseSkillInstanceData)(object)new InstanceData(skillSlot); } public override void OnUnassigned(GenericSkill skillSlot) { if (skillSlot.skillInstanceData is InstanceData instanceData) { instanceData.Dispose(); } ((SkillDef)this).OnUnassigned(skillSlot); } } internal class LoadoutEnigmaContent : IContentPackProvider { public static class SkillDefs { public static SkillDef DisabledSkill; public static SkillDef EnigmaDisabled; public static SkillDef EnigmaEnabled; public static SkillDef EnigmaEnabledSingleMode; } private readonly ContentPack _contentPack = new ContentPack(); public string identifier => "Gorakh.LoadoutEnigma"; internal LoadoutEnigmaContent() { }//IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)delegate(AddContentPackProviderDelegate addContentPackProvider) { addContentPackProvider.Invoke((IContentPackProvider)(object)this); }; } public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args) { _contentPack.identifier = identifier; DisabledSkillDef disabledSkillDef = ScriptableObject.CreateInstance<DisabledSkillDef>(); ((Object)disabledSkillDef).name = "DisabledSkill"; ((SkillDef)disabledSkillDef).skillName = "DisabledSkill"; ((SkillDef)disabledSkillDef).skillNameToken = "CAPTAIN_SKILL_USED_UP_NAME"; ((SkillDef)disabledSkillDef).activationStateMachineName = "there's no way somebody has a state machine with this name"; ((SkillDef)disabledSkillDef).activationState = new SerializableEntityStateType(typeof(Idle)); ((SkillDef)disabledSkillDef).fullRestockOnAssign = true; ((SkillDef)disabledSkillDef).dontAllowPastMaxStocks = true; ((SkillDef)disabledSkillDef).hideStockCount = true; Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/DLC2/Common/DisabledSkill.asset").CallOnSuccess(delegate(SkillDef disabledSkill) { ((SkillDef)disabledSkillDef).icon = disabledSkill.icon; }); SkillDef enigmaDisabledSkillDef = ScriptableObject.CreateInstance<SkillDef>(); ((Object)enigmaDisabledSkillDef).name = "EnigmaDisabled"; enigmaDisabledSkillDef.skillName = "EnigmaDisabled"; enigmaDisabledSkillDef.skillNameToken = "SKILL_ENIGMA_DISABLED_NAME"; enigmaDisabledSkillDef.skillDescriptionToken = "SKILL_ENIGMA_DISABLED_DESC"; enigmaDisabledSkillDef.keywordTokens = Array.Empty<string>(); enigmaDisabledSkillDef.activationStateMachineName = "there's no way somebody has a state machine with this name"; enigmaDisabledSkillDef.activationState = new SerializableEntityStateType(typeof(Idle)); Addressables.LoadAssetAsync<Sprite>((object)"RoR2/Base/Enigma/texArtifactRandomEquipmentDisabled.png").CallOnSuccess(delegate(Sprite icon) { enigmaDisabledSkillDef.icon = icon; }); EnigmaSkillDef enigmaEnabledSkillDef = ScriptableObject.CreateInstance<EnigmaSkillDef>(); ((Object)enigmaEnabledSkillDef).name = "EnigmaEnabled"; ((SkillDef)enigmaEnabledSkillDef).skillName = "EnigmaEnabled"; ((SkillDef)enigmaEnabledSkillDef).skillNameToken = "SKILL_ENIGMA_ENABLED_NAME"; ((SkillDef)enigmaEnabledSkillDef).skillDescriptionToken = "SKILL_ENIGMA_ENABLED_DESC"; ((SkillDef)enigmaEnabledSkillDef).keywordTokens = Array.Empty<string>(); ((SkillDef)enigmaEnabledSkillDef).activationStateMachineName = "there's no way somebody has a state machine with this name"; ((SkillDef)enigmaEnabledSkillDef).activationState = new SerializableEntityStateType(typeof(Idle)); enigmaEnabledSkillDef.SingleSkillMode = false; Addressables.LoadAssetAsync<Sprite>((object)"RoR2/Base/Enigma/texArtifactRandomEquipmentEnabled.png").CallOnSuccess(delegate(Sprite icon) { ((SkillDef)enigmaEnabledSkillDef).icon = icon; }); EnigmaSkillDef enigmaEnabledSingleModeSkillDef = ScriptableObject.CreateInstance<EnigmaSkillDef>(); ((Object)enigmaEnabledSingleModeSkillDef).name = "EnigmaEnabledSingleMode"; ((SkillDef)enigmaEnabledSingleModeSkillDef).skillName = "EnigmaEnabledSingleMode"; ((SkillDef)enigmaEnabledSingleModeSkillDef).skillNameToken = "SKILL_ENIGMA_SINGLE_MODE_ENABLED_NAME"; ((SkillDef)enigmaEnabledSingleModeSkillDef).skillDescriptionToken = "SKILL_ENIGMA_SINGLE_MODE_ENABLED_DESC"; ((SkillDef)enigmaEnabledSingleModeSkillDef).keywordTokens = Array.Empty<string>(); ((SkillDef)enigmaEnabledSingleModeSkillDef).activationStateMachineName = "there's no way somebody has a state machine with this name"; ((SkillDef)enigmaEnabledSingleModeSkillDef).activationState = new SerializableEntityStateType(typeof(Idle)); enigmaEnabledSingleModeSkillDef.SingleSkillMode = true; Addressables.LoadAssetAsync<Sprite>((object)"RoR2/Base/Enigma/texArtifactRandomEquipmentEnabled.png").CallOnSuccess(delegate(Sprite icon) { ((SkillDef)enigmaEnabledSingleModeSkillDef).icon = icon; }); _contentPack.skillDefs.Add((SkillDef[])(object)new SkillDef[4] { disabledSkillDef, enigmaDisabledSkillDef, enigmaEnabledSkillDef, enigmaEnabledSingleModeSkillDef }); ContentLoadHelper.PopulateTypeFields<SkillDef>(typeof(SkillDefs), _contentPack.skillDefs, (Func<string, string>)null); args.ReportProgress(1f); yield break; } public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args) { ContentPack.Copy(_contentPack, args.output); args.ReportProgress(1f); yield break; } public IEnumerator FinalizeAsync(FinalizeAsyncArgs args) { args.ReportProgress(1f); yield break; } } }