Decompiled source of ExtendedLoadout v2.3.0

plugins/ExtendedLoadout/ExtendedLoadout.dll

Decompiled 2 months ago
using 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();
	}
}