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();
}
}