Decompiled source of SurvivorSortOrder v1.1.2

SillySortOrder.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using On.RoR2;
using RoR2;
using Survariants;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SillySortOrder")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SillySortOrder")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("68d4b4da-4f05-4c48-a834-bb2de3af9e55")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: UnverifiableCode]
namespace SillyMod;

public class ConFiguration
{
	public enum Ror1MixType
	{
		Default,
		Risky1First,
		Risky1ButMixed
	}

	public static bool MixRor1Survivors;

	public static Ror1MixType Ror1Mix;

	public static bool NemesesSeparate;

	public static bool ForceModdedCharactersOut;

	public static string ForceOutWhiteList;

	public static Dictionary<string, float> CustomOrderSortings = new Dictionary<string, float>();

	public static Dictionary<string, string> CustomVariants = new Dictionary<string, string>();

	public static Dictionary<string, string> CustomVariantDescriptions = new Dictionary<string, string>();

	public static bool NemesesVariants;

	public static List<string> ParseErrorLog = new List<string>();

	private static BaseUnityPlugin plugin;

	public static bool Debug;

	public static void DoConfig(BaseUnityPlugin plugin)
	{
		ConFiguration.plugin = plugin;
		MixRor1Survivors = plugin.Config.Bind<bool>("love ya", "Mix ror1 surivors", true, "Modded ror1 survivors will be mixed in with the rest of the cast, loosely based on their unlock condition.\nSet to false to separate them out and neatly place them together right after Vanilla\nOverrides those mods' original configs").Value;
		NemesesSeparate = plugin.Config.Bind<bool>("love ya", "Separate Nemesis", false, "Set to true to separate out nemesis survivors from the main lineup, grouped up after ror1 and ror2 survivors.\nSet to false to place next to their counterpart").Value;
		ForceModdedCharactersOut = plugin.Config.Bind<bool>("love ya", "Force Modded Characters Out", true, "Set to true to separate out any other non-ror1 modded characters.\nSet to false to leave them where their mod placed them").Value;
		string value = plugin.Config.Bind<string>("love ya", "Custom Order", "", "List of characters to apply a custom order, comma separated.\nFormat is BodyName:Number. Number can be decimal between two values to place your character in between.\nExample: EngiBody:69,HereticBody:2,EnforcerBody:6.5,HANDOverclockedBody:8.1\nYou can copy from Print Sorting config below.").Value;
		ParseCustomOrder(value);
		string value2 = plugin.Config.Bind<string>("Variants", "Custom Variants", "", "Requires Survariants mod. List of characters to set as variants of other characters.\nFormat is VariantBodyName:TargetBodyName.\nOptionally set a description with another : (VariantBodyName:TargetBodyName:Description).\nex: NemCommandoBody:CommandoBody, NemesisEnforcerBody:EnforcerBody:Heavy TF2.").Value;
		ParseVariants(value2);
		NemesesVariants = plugin.Config.Bind<bool>("Variants", "Nemesis variants", false, "Requires Survariants mod. Set to true to put nemesis survivors as variants of the original").Value;
	}

	public static void PrintSortingConfig(string log)
	{
		Debug = plugin.Config.Bind<bool>("love ya", "Print Sorting", true, "This config does nothing. just shows what the game's current order is when you run the game so you can copy paste\n" + log).Value;
	}

	private static void ParseCustomOrder(string customOrder)
	{
		string[] array = customOrder.Split(new char[1] { ',' });
		foreach (string text in array)
		{
			if (string.IsNullOrEmpty(text))
			{
				continue;
			}
			string[] array2 = text.Split(new char[1] { ':' });
			if (array2.Length == 2)
			{
				try
				{
					string key = array2[0].TrimStart(Array.Empty<char>()).TrimEnd(Array.Empty<char>());
					CustomOrderSortings[key] = float.Parse(array2[1].TrimStart(Array.Empty<char>()).TrimEnd(Array.Empty<char>()));
				}
				catch (Exception arg)
				{
					ParseErrorLog.Add($"Custom Sort could not find sort position for entry: {text}\n{arg}");
				}
			}
			else
			{
				ParseErrorLog.Add("Custom Sort Entry Invalid: " + text + ". Should be BodyName:Number");
			}
			if (array2.Length > 2)
			{
				ParseErrorLog.Add("If someone put : in their bodyname there's nothing I can do. Reach out to the mod creator, tell them Timesweeper sent you.");
			}
		}
	}

	private static void ParseVariants(string variants)
	{
		string[] array = variants.Split(new char[1] { ',' });
		foreach (string text in array)
		{
			if (string.IsNullOrEmpty(text))
			{
				continue;
			}
			string[] array2 = text.Split(new char[1] { ':' });
			if (array2.Length >= 2)
			{
				try
				{
					string key = array2[0].TrimStart(Array.Empty<char>()).TrimEnd(Array.Empty<char>());
					CustomVariants[key] = array2[1].TrimStart(Array.Empty<char>()).TrimEnd(Array.Empty<char>());
					if (array2.Length > 2)
					{
						CustomVariantDescriptions[key] = array2[2].TrimStart(Array.Empty<char>()).TrimEnd(Array.Empty<char>());
					}
				}
				catch (Exception arg)
				{
					ParseErrorLog.Add($"Custom Variants could not find Variant Set for entry: {text}\n{arg}");
				}
			}
			else
			{
				ParseErrorLog.Add("Custom Variant Entry Invalid: " + text + ". Should be BodyName:BodyName or BodyName:BodyName:Description");
			}
		}
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.TheTimeSweeper.SurvivorSortOrder", "SurvivorSortOrder", "1.1.2")]
public class SillySortPlugin : BaseUnityPlugin
{
	public static Dictionary<string, float> ClassicSurivorSortings = new Dictionary<string, float>();

	public static Dictionary<string, float> VanillaSurivorSortings = new Dictionary<string, float>();

	public static List<SurvivorDef> HackMakeSureOff = new List<SurvivorDef>();

	public static ManualLogSource Log;

	public const float AFTER_VANILLA_INDEX = 20f;

	public const float NEMESES_INDEX = 21f;

	public const float AFTER_END_INDEX = 25f;

	private bool _didVariants;

	private void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		ConFiguration.DoConfig((BaseUnityPlugin)(object)this);
		SetSurvivorSortings();
		SurvivorCatalog.SetSurvivorDefs += new hook_SetSurvivorDefs(SurvivorCatalog_SetSurvivorDefs);
		CharacterSelectBarController.Awake += new hook_Awake(CharacterSelectBarController_Awake);
	}

	private void SetSurvivorSortings()
	{
		VanillaSurivorSortings = new Dictionary<string, float>();
		VanillaSurivorSortings["CommandoBody"] = 1f;
		VanillaSurivorSortings["HuntressBody"] = 2f;
		VanillaSurivorSortings["Bandit2Body"] = 3f;
		VanillaSurivorSortings["ToolbotBody"] = 4f;
		VanillaSurivorSortings["EngiBody"] = 5f;
		VanillaSurivorSortings["MageBody"] = 6f;
		VanillaSurivorSortings["MercBody"] = 7f;
		VanillaSurivorSortings["TreebotBody"] = 8f;
		VanillaSurivorSortings["LoaderBody"] = 9f;
		VanillaSurivorSortings["CrocoBody"] = 10f;
		VanillaSurivorSortings["CaptainBody"] = 11f;
		VanillaSurivorSortings["HereticBody"] = 13f;
		VanillaSurivorSortings["RailgunnerBody"] = 14f;
		VanillaSurivorSortings["VoidSurvivorBody"] = 15f;
		VanillaSurivorSortings["SeekerBody"] = 16f;
		VanillaSurivorSortings["FalseSonBody"] = 17f;
		VanillaSurivorSortings["ChefBody"] = 18f;
		if (ConFiguration.MixRor1Survivors)
		{
			ClassicSurivorSortings["HANDOverclockedBody"] = 4.1f;
			ClassicSurivorSortings["EnforcerBody"] = 5.1f;
			ClassicSurivorSortings["SniperClassicBody"] = 7.1f;
			ClassicSurivorSortings["CHEF"] = 19f;
			ClassicSurivorSortings["MinerBody"] = 9.1f;
		}
		else
		{
			ClassicSurivorSortings["EnforcerBody"] = 20.1f;
			ClassicSurivorSortings["SniperClassicBody"] = 20.2f;
			ClassicSurivorSortings["HANDOverclockedBody"] = 20.3f;
			ClassicSurivorSortings["CHEF"] = 20.4f;
			ClassicSurivorSortings["MinerBody"] = 20.5f;
		}
	}

	private void SurvivorCatalog_SetSurvivorDefs(orig_SetSurvivorDefs orig, SurvivorDef[] newSurvivorDefs)
	{
		try
		{
			Log.LogMessage((object)"[Before Sort]");
			PrintOrder(newSurvivorDefs);
			Dictionary<string, float> dictionary = new Dictionary<string, float>();
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
			for (int num = newSurvivorDefs.Length - 1; num >= 0; num--)
			{
				string name = ((Object)newSurvivorDefs[num].bodyPrefab).name;
				if (ConFiguration.ForceModdedCharactersOut && !ClassicSurivorSortings.ContainsKey(name) && !VanillaSurivorSortings.ContainsKey(name))
				{
					newSurvivorDefs[num].desiredSortPosition = 25f + newSurvivorDefs[num].desiredSortPosition * 0.001f;
				}
				if (ClassicSurivorSortings.ContainsKey(name))
				{
					newSurvivorDefs[num].desiredSortPosition = ClassicSurivorSortings[name];
				}
				if (!string.IsNullOrEmpty(newSurvivorDefs[num].displayNameToken))
				{
					string key = Language.GetString(newSurvivorDefs[num].displayNameToken, "en").ToLowerInvariant();
					dictionary[key] = newSurvivorDefs[num].desiredSortPosition;
					dictionary2[key] = ((Object)newSurvivorDefs[num].bodyPrefab).name;
				}
			}
			for (int i = 0; i < newSurvivorDefs.Length; i++)
			{
				if (string.IsNullOrEmpty(newSurvivorDefs[i].displayNameToken))
				{
					continue;
				}
				string text = Language.GetString(newSurvivorDefs[i].displayNameToken, "en").ToLowerInvariant();
				if (!text.Contains("nemesis"))
				{
					continue;
				}
				string[] array = text.Replace("nemesis ", "").Split(new char[1] { ' ' });
				for (int j = 0; j < array.Length; j++)
				{
					foreach (string key2 in dictionary.Keys)
					{
						if (array[j].Contains(key2.ToLowerInvariant()))
						{
							if (ConFiguration.NemesesSeparate)
							{
								newSurvivorDefs[i].desiredSortPosition = 21f + newSurvivorDefs[i].desiredSortPosition * 0.01f;
							}
							else
							{
								newSurvivorDefs[i].desiredSortPosition = dictionary[key2] + 1E-05f;
							}
							if (ConFiguration.NemesesVariants && !ConFiguration.CustomVariants.ContainsKey(((Object)newSurvivorDefs[i].bodyPrefab).name))
							{
								ConFiguration.CustomVariants[((Object)newSurvivorDefs[i].bodyPrefab).name] = dictionary2[key2];
							}
						}
					}
				}
			}
			for (int k = 0; k < newSurvivorDefs.Length; k++)
			{
				string name2 = ((Object)newSurvivorDefs[k].bodyPrefab).name;
				if (ConFiguration.CustomOrderSortings.ContainsKey(name2))
				{
					newSurvivorDefs[k].desiredSortPosition = ConFiguration.CustomOrderSortings[name2];
					ConFiguration.CustomOrderSortings.Remove(name2);
				}
			}
			Log.LogMessage((object)"[After Sort]");
			PrintOrder(newSurvivorDefs, toConfig: true);
			string text2 = "";
			foreach (KeyValuePair<string, float> customOrderSorting in ConFiguration.CustomOrderSortings)
			{
				text2 = text2 + customOrderSorting.Key + ", ";
			}
			if (!string.IsNullOrEmpty(text2))
			{
				Log.LogWarning((object)("Could not find body to sort for: " + text2 + "\nEither these characters don't exist or you messed up typing lol."));
			}
			for (int l = 0; l < ConFiguration.ParseErrorLog.Count; l++)
			{
				Log.LogError((object)ConFiguration.ParseErrorLog[l]);
			}
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Failed to sort survivors. Reach out to `thetimesweeper` on discord and send this error pls\n" + ex));
		}
		orig.Invoke(newSurvivorDefs);
	}

	[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
	private static void SetVariants(SurvivorDef[] newSurvivorDefs)
	{
		List<SurvivorDef> list = newSurvivorDefs.ToList();
		list.Sort((SurvivorDef def1, SurvivorDef def2) => (def1.desiredSortPosition >= def2.desiredSortPosition) ? 1 : (-1));
		LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
		foreach (string customVariantname in ConFiguration.CustomVariants.Keys)
		{
			SurvivorDef variantSurvivor = list.Where((SurvivorDef def) => ((Object)def.bodyPrefab).name.ToLowerInvariant() == customVariantname.ToLowerInvariant()).FirstOrDefault();
			if ((Object)(object)variantSurvivor == (Object)null)
			{
				Log.LogWarning((object)("Could not set variant " + customVariantname + ". Could not find body"));
				continue;
			}
			if (string.IsNullOrEmpty(variantSurvivor.displayNameToken))
			{
				Log.LogWarning((object)("Could not set variant " + customVariantname + ". SurvivorDef displayNameToken is invalid"));
				continue;
			}
			if ((Object)(object)SurvivorVariantCatalog.SurvivorVariantDefs.Find((SurvivorVariantDef variantDef) => (Object)(object)variantDef.VariantSurvivor == (Object)(object)variantSurvivor) != (Object)null)
			{
				Log.LogDebug((object)("Did not set variant " + customVariantname + ". Survivor already set as a variant"));
				continue;
			}
			if (!variantSurvivor.CheckUserHasRequiredEntitlement(firstLocalUser))
			{
				Log.LogWarning((object)("Could not set variant " + customVariantname + ". User does not have required expansion"));
				continue;
			}
			SurvivorDef val = list.Where((SurvivorDef def) => ((Object)def.bodyPrefab).name.ToLowerInvariant() == ConFiguration.CustomVariants[customVariantname].ToLowerInvariant()).FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				Log.LogWarning((object)("Could not set variant " + customVariantname + ". Could not find target body " + ConFiguration.CustomVariants[customVariantname]));
				continue;
			}
			try
			{
				SurvivorVariantDef val2 = ScriptableObject.CreateInstance<SurvivorVariantDef>();
				((Object)val2).name = customVariantname + "Variant";
				val2.VariantSurvivor = variantSurvivor;
				val2.TargetSurvivor = val;
				if (ConFiguration.CustomVariantDescriptions.ContainsKey(customVariantname) && !string.IsNullOrEmpty(ConFiguration.CustomVariantDescriptions[customVariantname]))
				{
					val2.Description = ConFiguration.CustomVariantDescriptions[customVariantname];
				}
				else
				{
					val2.Description = variantSurvivor.bodyPrefab.GetComponent<CharacterBody>().subtitleNameToken;
				}
				SurvivorVariantCatalog.AddSurvivorVariant(val2);
				HackMakeSureOff.Add(variantSurvivor);
				variantSurvivor.hidden = true;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to add Variant " + customVariantname + "\n" + ex));
			}
		}
	}

	private void CharacterSelectBarController_Awake(orig_Awake orig, CharacterSelectBarController self)
	{
		TrySetVariants();
		orig.Invoke(self);
		for (int i = 0; i < HackMakeSureOff.Count; i++)
		{
			HackMakeSureOff[i].hidden = true;
		}
	}

	private void TrySetVariants()
	{
		if (!_didVariants && Chainloader.PluginInfos.ContainsKey("pseudopulse.Survariants"))
		{
			_didVariants = true;
			try
			{
				SetVariants(SurvivorCatalog.survivorDefs);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("catastrophic failure I guess while adding variants:\n" + ex));
			}
		}
	}

	private void PrintOrder(SurvivorDef[] newSurvivorDefs, bool toConfig = false)
	{
		List<SurvivorDef> list = newSurvivorDefs.ToList();
		list.Sort((SurvivorDef def1, SurvivorDef def2) => (def1.desiredSortPosition >= def2.desiredSortPosition) ? 1 : (-1));
		string text = "Printed Sort Order:\n";
		for (int i = 0; i < list.Count; i++)
		{
			Log.LogMessage((object)(((Object)list[i].bodyPrefab).name + " sort position: " + list[i].desiredSortPosition));
			string arg = ((i == 0) ? "" : ", ");
			text += $"{arg}{((Object)list[i].bodyPrefab).name}:{list[i].desiredSortPosition}";
		}
		if (toConfig)
		{
			Log.LogMessage((object)text);
			ConFiguration.PrintSortingConfig(text);
		}
	}

	private void PrintStats(List<SurvivorDef> newSurvivorDefs)
	{
		for (int i = 0; i < newSurvivorDefs.Count; i++)
		{
			CharacterBody component = newSurvivorDefs[i].bodyPrefab.GetComponent<CharacterBody>();
			Log.LogInfo((object)$"{newSurvivorDefs[i]._cachedName}: Health {component.baseMaxHealth}, Regen: {component.baseRegen}, Armor {component.baseArmor}");
		}
	}
}