Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of ExtendedLoadout v2.3.0
plugins/ExtendedLoadout/ExtendedLoadout.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Treebot.Weapon; using ExtraSkillSlots; using HG; using On.EntityStates.Treebot.Weapon; using On.RoR2.Projectile; using RoR2; using RoR2.ContentManagement; using RoR2.Projectile; using RoR2.Skills; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.3.0.0")] namespace ExtendedLoadout; [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.KingEnderBrine.ExtendedLoadout", "Extended Loadout", "2.3.0")] public class ExtendedLoadoutPlugin : BaseUnityPlugin, IContentPackProvider { public const string GUID = "com.KingEnderBrine.ExtendedLoadout"; public const string Name = "Extended Loadout"; public const string Version = "2.3.0"; private ContentPack contentPack; private readonly Dictionary<SurvivorDef, SkillFamily[]> cachedFamilies = new Dictionary<SurvivorDef, SkillFamily[]>(); private Language english; private static ExtendedLoadoutPlugin Instance { get; set; } private static ManualLogSource InstanceLogger { get { ExtendedLoadoutPlugin instance = Instance; if (instance == null) { return null; } return ((BaseUnityPlugin)instance).Logger; } } public static SkillDef DisabledSkill { get; private set; } public string identifier => "ExtendedLoadout"; private void Start() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown Instance = this; NetworkModCompatibilityHelper.networkModList = NetworkModCompatibilityHelper.networkModList.Append("com.KingEnderBrine.ExtendedLoadout;2.3.0"); ContentManager.collectContentPackProviders += new CollectContentPackProvidersDelegate(CollectContentPackProviders); AimMortar2.KeyIsDown += new hook_KeyIsDown(TreebotHooks.AimMortar2KeyIsDown); FlyState.DeductOwnerStock += new hook_DeductOwnerStock(LoaderHooks.ProjectileGrappleControllerDeductOwnerStockHook); Language.collectLanguageRootFolders += CollectLanguageRootFolders; } private void CollectLanguageRootFolders(List<string> folders) { folders.Add(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Language")); } private void CollectContentPackProviders(AddContentPackProviderDelegate addContentPackProvider) { addContentPackProvider.Invoke((IContentPackProvider)(object)this); } private SkillFamily[] ExtendSurvivor(SurvivorDef survivorDef) { string text = survivorDef.displayNameToken; try { GameObject bodyPrefab = survivorDef.bodyPrefab; if (text == null) { text = bodyPrefab.GetComponent<CharacterBody>().baseNameToken; } if (Object.op_Implicit((Object)(object)bodyPrefab.GetComponent<ExtraSkillLocator>())) { return Array.Empty<SkillFamily>(); } SkillMapConfigSection skillMapConfigSection = new SkillMapConfigSection(((BaseUnityPlugin)Instance).Config, english.GetLocalizedStringByToken(text)); SkillLocator component = bodyPrefab.GetComponent<SkillLocator>(); ExtraSkillLocator val = bodyPrefab.AddComponent<ExtraSkillLocator>(); val.extraFirst = CopySkill(bodyPrefab, text, "First", component.primary, skillMapConfigSection.FirstRowSkills.Value); val.extraSecond = CopySkill(bodyPrefab, text, "Second", component.secondary, skillMapConfigSection.SecondRowSkills.Value); val.extraThird = CopySkill(bodyPrefab, text, "Third", component.utility, skillMapConfigSection.ThirdRowSkills.Value); val.extraFourth = CopySkill(bodyPrefab, text, "Fourth", component.special, skillMapConfigSection.FourthRowSkills.Value); List<SkillFamily> list = new List<SkillFamily>(); if (Object.op_Implicit((Object)(object)val.extraFirst)) { list.Add(val.extraFirst.skillFamily); } if (Object.op_Implicit((Object)(object)val.extraSecond)) { list.Add(val.extraSecond.skillFamily); } if (Object.op_Implicit((Object)(object)val.extraThird)) { list.Add(val.extraThird.skillFamily); } if (Object.op_Implicit((Object)(object)val.extraFourth)) { list.Add(val.extraFourth.skillFamily); } return list.ToArray(); } catch (Exception ex) { InstanceLogger.LogWarning((object)("Failed adding extra skill slots for \"" + text + "\"")); InstanceLogger.LogError((object)ex); } return Array.Empty<SkillFamily>(); } private static GenericSkill CopySkill(GameObject bodyPrefab, string familyPrefix, string familySuffix, GenericSkill original, string skillMap) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)original)) { return null; } SkillFamily skillFamily = original.skillFamily; if (!Object.op_Implicit((Object)(object)skillFamily) || skillFamily.variants == null || skillFamily.variants.Length < 2) { return null; } IEnumerable<Variant> enumerable = FilterVariants(skillFamily.variants, skillMap); if (enumerable.Count() == 0) { return null; } GenericSkill obj = bodyPrefab.AddComponent<GenericSkill>(); obj.skillName = "Extra" + familySuffix; SkillFamily val = ScriptableObject.CreateInstance<SkillFamily>(); ((Object)val).name = familyPrefix + "Extra" + familySuffix + "Family"; List<Variant> list = new List<Variant> { new Variant { skillDef = DisabledSkill } }; list.AddRange(enumerable); val.variants = list.ToArray(); obj._skillFamily = val; return obj; } private static IEnumerable<Variant> FilterVariants(Variant[] variants, string skillMap) { string text = skillMap.Trim(); bool isBlacklist = text.StartsWith("^"); IEnumerable<int> indices = from el in (isBlacklist ? text.Substring(1) : text).Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select int.Parse(el.Trim()); return variants.Where((Variant el, int index) => isBlacklist ^ indices.Contains(index)); } IEnumerator IContentPackProvider.LoadStaticContentAsync(LoadStaticContentAsyncArgs args) { contentPack = new ContentPack(); DisabledSkill = ScriptableObject.CreateInstance<SkillDef>(); DisabledSkill.skillName = "Disabled"; ((Object)DisabledSkill).name = DisabledSkill.skillName; DisabledSkill.skillNameToken = LanguageConsts.EXTENDED_LOADOUT_SKILL_DISABLED_NAME; DisabledSkill.skillDescriptionToken = LanguageConsts.EXTENDED_LOADOUT_SKILL_DISABLED_DESCRIPTION; DisabledSkill.icon = Sprite.Create(Texture2D.blackTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0f, 0f)); DisabledSkill.activationStateMachineName = "Weapon"; DisabledSkill.activationState = new SerializableEntityStateType(typeof(Idle)); DisabledSkill.interruptPriority = (InterruptPriority)0; DisabledSkill.baseRechargeInterval = 0f; DisabledSkill.baseMaxStock = 1; DisabledSkill.rechargeStock = 0; DisabledSkill.beginSkillCooldownOnSkillEnd = false; DisabledSkill.rechargeStock = 1; DisabledSkill.stockToConsume = 2; DisabledSkill.isCombatSkill = false; contentPack.skillDefs.Add((SkillDef[])(object)new SkillDef[1] { DisabledSkill }); args.ReportProgress(0.9f); english = new Language("en"); english.SetFolders((from d in Language.GetLanguageRootFolders() where Directory.Exists(d) select d).SelectMany((string el) => Directory.EnumerateDirectories(el, "en"))); english.LoadStrings(); args.ReportProgress(1f); yield break; } IEnumerator IContentPackProvider.GenerateContentPackAsync(GetContentPackAsyncArgs args) { ContentPack.Copy(contentPack, args.output); Enumerator<ContentPackLoadInfo> enumerator = args.peerLoadInfos.GetEnumerator(); try { while (enumerator.MoveNext()) { ContentPackLoadInfo current = enumerator.Current; AssetEnumerator<SurvivorDef> enumerator2 = ((ReadOnlyContentPack)(ref current.previousContentPack)).survivorDefs.GetEnumerator(); try { while (enumerator2.MoveNext()) { SurvivorDef current2 = enumerator2.Current; if (!cachedFamilies.TryGetValue(current2, out var value)) { value = (cachedFamilies[current2] = ExtendSurvivor(current2)); } if (value.Length != 0) { args.output.skillFamilies.Add(value); } } } finally { ((IDisposable)enumerator2).Dispose(); } } } finally { ((IDisposable)enumerator).Dispose(); } args.ReportProgress(1f); yield break; } IEnumerator IContentPackProvider.FinalizeAsync(FinalizeAsyncArgs args) { english.UnloadStrings(); english = null; cachedFamilies.Clear(); args.ReportProgress(1f); yield break; } } public static class LanguageConsts { public static readonly string EXTENDED_LOADOUT_SKILL_DISABLED_NAME = "EXTENDED_LOADOUT_SKILL_DISABLED_NAME"; public static readonly string EXTENDED_LOADOUT_SKILL_DISABLED_DESCRIPTION = "EXTENDED_LOADOUT_SKILL_DISABLED_DESCRIPTION"; } public static class LoaderHooks { public static void ProjectileGrappleControllerDeductOwnerStockHook(orig_DeductOwnerStock orig, BaseState self) { FlyState val = (FlyState)(object)((self is FlyState) ? self : null); if (val != null && ((BaseState)val).ownerValid && ((BaseState)val).owner.hasEffectiveAuthority) { EntityState state = ((BaseState)val).owner.stateMachine.state; BaseSkillState val2 = (BaseSkillState)(object)((state is BaseSkillState) ? state : null); if (val2 != null) { val2.activatorSkillSlot.DeductStock(1); } } } } public class SkillMapConfigSection { private const string skillsDescription = "List of indices (comma-separated, starting from 0) of skills which should be enabled.\nIf \"^\" added at the start then all the skill will be enabled except of specified indices.\nFor example:\n\"0, 3, 4\" - will enable only skills at these indices.\n\"^0, 3, 4\" - will enable skills at indices 1, 2, 5 and so on if there are any.\nLeaving option empty will disable extra skill row.\nLeaving option with only \"^\" will enable all skills for this row.\n"; public string SectionName { get; private set; } public ConfigEntry<string> FirstRowSkills { get; private set; } public ConfigEntry<string> SecondRowSkills { get; private set; } public ConfigEntry<string> ThirdRowSkills { get; private set; } public ConfigEntry<string> FourthRowSkills { get; private set; } public SkillMapConfigSection(ConfigFile file, string sectionName) { SkillMapConfigSection skillMapConfigSection = this; SectionName = RemoveInvalidCharacters(sectionName); switch (SectionName) { case "Acrid": SetupRowSkills(); break; case "Artificer": SetupRowSkills(); break; case "Captain": SetupRowSkills(); break; case "Commando": SetupRowSkills(); break; case "Engineer": SetupRowSkills("^", "^", "^", ""); break; case "Huntress": SetupRowSkills(); break; case "Loader": SetupRowSkills(); break; case "Mercenary": SetupRowSkills(); break; case "MUL-T": SetupRowSkills(""); break; case "Rex": SetupRowSkills(); break; case "Bandit": SetupRowSkills(""); break; case "Heretic": SetupRowSkills(); break; case "Railgunner": SetupRowSkills(); break; case "「V??oid Fiend』": SetupRowSkills(); break; default: SetupRowSkills("", "", "", ""); break; } void SetupRowSkills(string first = "^", string second = "^", string third = "^", string fourth = "^") { FirstRowSkills = file.Bind<string>(SectionName, "FirstRowSkills", first, "List of indices (comma-separated, starting from 0) of skills which should be enabled.\nIf \"^\" added at the start then all the skill will be enabled except of specified indices.\nFor example:\n\"0, 3, 4\" - will enable only skills at these indices.\n\"^0, 3, 4\" - will enable skills at indices 1, 2, 5 and so on if there are any.\nLeaving option empty will disable extra skill row.\nLeaving option with only \"^\" will enable all skills for this row.\n"); SecondRowSkills = file.Bind<string>(SectionName, "SecondRowSkills", second, (ConfigDescription)null); ThirdRowSkills = file.Bind<string>(SectionName, "ThirdRowSkills", third, (ConfigDescription)null); FourthRowSkills = file.Bind<string>(SectionName, "FourthRowSkills", fourth, (ConfigDescription)null); } } private string RemoveInvalidCharacters(string sectionName) { return Regex.Replace(sectionName, "[=\\n\\t\"'\\\\[\\]]", "").Trim(); } } public static class TreebotHooks { public static bool AimMortar2KeyIsDown(orig_KeyIsDown orig, AimMortar2 self) { return ((BaseSkillState)self).IsKeyDownAuthority(); } }