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 ExtendedLoadout v2.3.0
plugins/ExtendedLoadout/ExtendedLoadout.dll
Decompiled 2 years 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(); } }