Decompiled source of WECCL v1.9.0

plugins/WECCL.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using WECCL.API;
using WECCL.API.Events;
using WECCL.Animation;
using WECCL.Content;
using WECCL.Internal;
using WECCL.Patches;
using WECCL.Saves;
using WECCL.Updates;
using WECCL.Utils;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("WECCL")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WECCL")]
[assembly: AssemblyTitle("WECCL")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WECCL
{
	public static class Locations
	{
		public static DirectoryInfo Root { get; } = new DirectoryInfo(Paths.PluginPath);


		public static DirectoryInfo Export { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "Export"));


		public static DirectoryInfo DeletedCharacters { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "Purgatory"));


		public static DirectoryInfo Cache { get; } = new DirectoryInfo(Path.Combine(Plugin.PersistentDataPath, ".cache"));


		public static DirectoryInfo Debug { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "Debug"));


		public static DirectoryInfo Data { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "Data"));


		public static DirectoryInfo Meta { get; } = new DirectoryInfo(Path.Combine(Plugin.PersistentDataPath, "Meta.meta"));


		public static FileInfo SaveFileVanilla { get; } = new FileInfo(Path.Combine(Application.persistentDataPath, "Save.bytes"));


		public static FileInfo SaveFile { get; } = new FileInfo(Path.Combine(Application.persistentDataPath, Plugin.SaveFileName.Value + ".bytes"));


		public static DirectoryInfo ContentMappings { get; } = new DirectoryInfo(Path.Combine(Plugin.PersistentDataPath, "ContentMappings.mappings"));


		public static DirectoryInfo CharacterMappings { get; } = new DirectoryInfo(Path.Combine(Plugin.PersistentDataPath, "CharacterMappings.mappings"));


		internal static void CreateDirectories()
		{
			if (Plugin.CacheEnabled.Value && !Cache.Exists)
			{
				Cache.Create();
			}
			else if (Plugin.CacheEnabled.Value && Cache.Attributes.HasFlag(FileAttributes.Hidden))
			{
				Cache.Attributes &= ~FileAttributes.Hidden;
			}
			else if (!Plugin.CacheEnabled.Value && Cache.Exists)
			{
				Cache.Delete(recursive: true);
			}
			Debug.Create();
		}

		internal static void MoveLegacyLocations()
		{
			LegacyLocations.MoveLegacyLocations();
		}

		public static void LoadData()
		{
			RuntimeAnimatorController? obj = AssetBundle.LoadFromFile(Path.Combine(Data.FullName, "animationcontroller")).LoadAllAssets<RuntimeAnimatorController>().FirstOrDefault();
			if ((Object)(object)obj == (Object)null)
			{
				throw new Exception("Failed to load data. Please make sure you copied the 'Data' folder alongside the plugin if installed manually.");
			}
			AO.AnimationController = obj;
		}
	}
	internal static class LegacyLocations
	{
		public static DirectoryInfo OldCache { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, ".cache"));


		public static DirectoryInfo OldMetadata { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "Meta.meta"));


		public static DirectoryInfo OldMappings { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "ContentMappings.mappings"));


		public static DirectoryInfo OldMetadata2 { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "CustomConfigsSaveFile.json"));


		public static DirectoryInfo OldMappings2 { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "CustomContentSaveFile.json"));


		public static DirectoryInfo OldMetadata3 { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "Meta.json"));


		public static DirectoryInfo OldMappings3 { get; } = new DirectoryInfo(Path.Combine(Plugin.PluginPath, "ContentMappings.json"));


		public static void MoveLegacyLocations()
		{
			if (OldCache.Exists)
			{
				if (!Locations.Cache.Exists)
				{
					OldCache.MoveTo(Locations.Cache.FullName);
				}
				else
				{
					OldCache.Delete(recursive: true);
				}
			}
			if (OldMetadata.Exists)
			{
				if (!Locations.Meta.Exists)
				{
					OldMetadata.MoveTo(Locations.Meta.FullName);
				}
				else
				{
					OldMetadata.Delete(recursive: true);
				}
			}
			if (OldMappings.Exists)
			{
				if (!Locations.ContentMappings.Exists)
				{
					OldMappings.MoveTo(Locations.ContentMappings.FullName);
				}
				else
				{
					OldMappings.Delete(recursive: true);
				}
			}
			if (OldMetadata2.Exists)
			{
				if (!Locations.Meta.Exists)
				{
					OldMetadata2.MoveTo(Locations.Meta.FullName);
				}
				else
				{
					OldMetadata2.Delete(recursive: true);
				}
			}
			if (OldMappings2.Exists)
			{
				if (!Locations.ContentMappings.Exists)
				{
					OldMappings2.MoveTo(Locations.ContentMappings.FullName);
				}
				else
				{
					OldMappings2.Delete(recursive: true);
				}
			}
			if (OldMetadata3.Exists)
			{
				if (!Locations.Meta.Exists)
				{
					OldMetadata3.MoveTo(Locations.Meta.FullName);
				}
				else
				{
					OldMetadata3.Delete(recursive: true);
				}
			}
			if (OldMappings3.Exists)
			{
				if (!Locations.ContentMappings.Exists)
				{
					OldMappings3.MoveTo(Locations.ContentMappings.FullName);
				}
				else
				{
					OldMappings3.Delete(recursive: true);
				}
			}
		}
	}
	[BepInPlugin("IngoH.WrestlingEmpire.WECCL", "WECCL", "1.9.0")]
	[HarmonyPatch]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "IngoH.WrestlingEmpire.WECCL";

		public const string PluginName = "WECCL";

		public const string PluginVer = "1.9.0";

		public const string PluginPatchVer = "";

		public const string PluginVerLong = "v1.9.0";

		public const float PluginCharacterVersion = 1.56f;

		public const float PluginVersion = 1.63f;

		public static readonly float GameVersion = VlTAYHzGqN.LegBPRbwvz;

		public const bool PreRelease = false;

		public static string[] PreReleaseReasons = new string[1] { "Testing" };

		internal static ManualLogSource Log;

		internal static readonly Harmony Harmony = new Harmony("IngoH.WrestlingEmpire.WECCL");

		internal static string PluginPath;

		internal static string PersistentDataPath;

		internal static Plugin Instance { get; private set; }

		internal static ConfigEntry<bool> AutoExportCharacters { get; set; }

		internal static ConfigEntry<bool> EnableOverrides { get; set; }

		internal static ConfigEntry<bool> EnableCustomContent { get; set; }

		internal static ConfigEntry<bool> UseFullQualityTextures { get; set; }

		internal static ConfigEntry<bool> AllowImportingCharacters { get; set; }

		internal static ConfigEntry<bool> DeleteImportedCharacters { get; set; }

		internal static ConfigEntry<bool> EnableWrestlerSearchScreen { get; set; }

		internal static ConfigEntry<bool> EnableGameUnityLog { get; set; }

		internal static ConfigEntry<string> GameUnityLogLevel { get; set; }

		internal static ConfigEntry<int> BaseFedLimit { get; set; }

		internal static ConfigEntry<int> MaxBackups { get; set; }

		internal static ConfigEntry<bool> CacheEnabled { get; set; }

		internal static ConfigEntry<bool> Debug { get; set; }

		internal static ConfigEntry<bool> DebugRender { get; set; }

		internal static ConfigEntry<string> DataSharingLevel { get; set; }

		internal static ConfigEntry<string> SaveFileName { get; set; }

		internal static ConfigEntry<string> PersistentDataOverride { get; set; }

		public static float CharactersVersion => Characters.latestVersion;

		private void Awake()
		{
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Expected O, but got Unknown
			try
			{
				Log = ((BaseUnityPlugin)this).Logger;
				Instance = this;
				PluginPath = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty;
				PersistentDataOverride = ((BaseUnityPlugin)this).Config.Bind<string>("General", "PersistentDataOverride", "", "Override the persistent data path, which is used for storing the cache and mappings. This is useful if you want to use a different drive for the cache and mappings, since they can get quite large. Note that this will not move the existing cache and mappings, so you will have to move them manually. Leave this empty to use the default persistent data path: " + Path.Combine(Application.persistentDataPath, "WECCL").Replace('/', '\\'));
				PersistentDataPath = (string.IsNullOrEmpty(PersistentDataOverride.Value) ? Path.Combine(Application.persistentDataPath, "WECCL") : PersistentDataOverride.Value);
				if (!Directory.Exists(PersistentDataPath))
				{
					Directory.CreateDirectory(PersistentDataPath);
				}
				AutoExportCharacters = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoExportCharacters", true, "Automatically export characters to /Export when the game is saved.");
				EnableOverrides = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableOverrides", true, "Enable custom content overrides from /Overrides.");
				EnableCustomContent = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableCustomContent", true, "Enable custom content loading from /Assets.");
				UseFullQualityTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseFullQualityTextures", false, "(EXPERIMENTAL) Allow WECCL to use the full resolution textures without scaling them down (the game will still change the aspect ratio to fit the texture).");
				AllowImportingCharacters = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AllowImportingCharacters", true, "Allow importing characters from /Import");
				DeleteImportedCharacters = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DeleteImportedCharacters", false, "Delete imported characters from /Import after importing them (and saving the game).");
				EnableWrestlerSearchScreen = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableWrestlerSearchScreen", true, "Enable the wrestler search screen in the roster menu.");
				EnableGameUnityLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableGameUnityLog", true, "Enable Unity log messages sent by the game itself. If you don't know what this is, leave it enabled.");
				GameUnityLogLevel = ((BaseUnityPlugin)this).Config.Bind<string>("General", "GameUnityLogLevel", "Warning", new ConfigDescription("The log level for Unity log messages sent by the game itself. If you don't know what this is, leave it at Warning.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Error", "Warning", "Info" }), Array.Empty<object>()));
				BaseFedLimit = ((BaseUnityPlugin)this).Config.Bind<int>("General", "BaseFedLimit", 48, "The base limit for the number of characters that can be fed's roster. This actual limit may be increased if characters are imported (Experimental).");
				MaxBackups = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxBackups", 100, "The maximum number of backups to keep. Set to 0 to disable backups. Set to -1 to keep all backups.");
				CacheEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "CacheEnabled", true, "Enable caching of custom content. This will speed up loading times with the downside of more disk space usage. The cache is stored in the .cache folder, which is hidden by default. Disabling this will automatically delete the cache on startup.");
				Debug = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Debug", false, "Enable debug mode. This will create debugging files in the /Debug folder.");
				DebugRender = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugRender", false, "Enable debug rendering. This will render debug information on the screen, such as collision boxes.");
				DataSharingLevel = ((BaseUnityPlugin)this).Config.Bind<string>("General", "DataSharingLevel", "Full", new ConfigDescription("The level of data to share with the developer of this plugin. This data will be used to improve the plugin. If you don't want to share any data, set this to None. All data is anonymous.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "None", "Basic", "Full" }), Array.Empty<object>()));
				SaveFileName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SaveFileName", "ModdedSave", "The name of the save file to save to. Set to 'Save' to use the vanilla save file (not recommended). If no modded save file exists, the vanilla save file contents will be copied to a new modded save file. Note that changing this would require manually renaming the save file if you want to continue using it.");
				if (!Directory.Exists(Locations.Data.FullName))
				{
					throw new DirectoryNotFoundException("Data directory not found. Please make sure you copied the Data folder to the same directory as the WECCL DLL.");
				}
				Locations.LoadData();
				AnimationActions.Initialize();
				if (CharactersVersion != 1.56f)
				{
					throw new Exception($"Unsupported game version: {CharactersVersion}");
				}
				if (GameVersion != 1.63f)
				{
					if (GameVersion > 1.63f)
					{
						LogUtils.LogWarning($"Your game version ({GameVersion}) is newer than WECCL's target version ({1.63f}). Keep in mind that it may not work as intended on this version. Check the Steam Workshop page for updates.");
					}
					else
					{
						LogUtils.LogWarning($"Your game version ({GameVersion}) is older than WECCL's target version ({1.63f}). Keep in mind that it may not work as intended on this version. Check for updates in the game's properties on Steam.");
					}
				}
				string easterEgg = Secrets.GetEasterEgg();
				if (easterEgg != null)
				{
					Log.LogInfo((object)easterEgg);
				}
				CreateBackups();
				Locations.MoveLegacyLocations();
				Locations.CreateDirectories();
				((MonoBehaviour)this).StartCoroutine(LoadContent.Load());
				((BaseUnityPlugin)(object)this).RegisterCustomButton("Reset Imported Characters", delegate
				{
					int count = CharacterMappings.CharacterMap.PreviouslyImportedCharacters.Count;
					CharacterMappings.CharacterMap.PreviouslyImportedCharacters.Clear();
					CharacterMappings.CharacterMap.PreviouslyImportedCharacterIds.Clear();
					CharacterMappings.CharacterMap.Save();
					MnHMPiKqZM.IngCVhzFZN(MnHMPiKqZM.SXiSghpMnQ);
					return (count == 0) ? "No reset needed" : string.Format("Reset {0} imported character{1}", count, (count == 1) ? "" : "s");
				}, extraConfirmation: true);
			}
			catch (Exception message)
			{
				LogUtils.LogError(message);
			}
		}

		private void OnEnable()
		{
			if (CharactersVersion != 1.56f)
			{
				return;
			}
			string fullName = Locations.SaveFile.FullName;
			if (!File.Exists(fullName))
			{
				string fullName2 = Locations.SaveFileVanilla.FullName;
				if (File.Exists(fullName2))
				{
					File.Copy(fullName2, fullName);
				}
				else
				{
					GLPGLJAJJOP.NJMFCPGCKNL();
					GLPGLJAJJOP.OIIAHNGBNIF(0);
				}
			}
			try
			{
				Harmony.PatchAll();
			}
			catch (Exception message)
			{
				LogUtils.LogError("Failed to patch with Harmony. This is likely caused by the game version being incompatible with the plugin version. The current plugin version is v" + 1.63f);
				LogUtils.LogError(message);
				Harmony.UnpatchSelf();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded WECCL!");
		}

		private void OnDisable()
		{
			if (CharactersVersion == 1.56f)
			{
				Harmony.UnpatchSelf();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Unloaded WECCL!");
			}
		}

		internal static void CreateBackups()
		{
			if (MaxBackups.Value == 0)
			{
				return;
			}
			string fullName = Locations.SaveFile.FullName;
			if (!File.Exists(fullName))
			{
				return;
			}
			string text = Path.Combine(Application.persistentDataPath, "backups", DateTime.Now.ToString("Save-yyyy-MM-dd_HH-mm-ss") + ".bytes");
			string directoryName = Path.GetDirectoryName(text);
			if (!Directory.Exists(directoryName))
			{
				Directory.CreateDirectory(directoryName);
			}
			if (Directory.GetFiles(directoryName, "Save-*.bytes").Length == 0)
			{
				File.Copy(fullName, Path.Combine(directoryName, "InitialSave.bytes"));
			}
			File.Copy(fullName, text);
			string[] files = Directory.GetFiles(directoryName, "Save-*.bytes");
			if (MaxBackups.Value >= 0 && files.Length > MaxBackups.Value)
			{
				Array.Sort(files);
				for (int i = 0; i < files.Length - MaxBackups.Value; i++)
				{
					File.Delete(files[i]);
				}
			}
		}

		public static string GetNonDefaultConfigValues()
		{
			string text = "";
			foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in ((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)((BaseUnityPlugin)Instance).Config).Select((KeyValuePair<ConfigDefinition, ConfigEntryBase> x) => new KeyValuePair<ConfigDefinition, ConfigEntryBase>(x.Key, x.Value)))
			{
				if (!(item.Value.BoxedValue.ToString() == item.Value.DefaultValue.ToString()))
				{
					text += $"{item.Key.Key}={item.Value.BoxedValue}\n";
				}
			}
			return text;
		}
	}
}
namespace WECCL.Utils
{
	public class AllMods
	{
		private static AllMods _instance;

		public static AllMods Instance => _instance ?? (_instance = new AllMods());

		public List<PluginInfo> Mods { get; private set; } = new List<PluginInfo>();


		public int NumMods => Mods.Count;

		public void LoadMods()
		{
			foreach (PluginInfo item in Chainloader.PluginInfos.Values.OrderBy((PluginInfo x) => x.Metadata.Name))
			{
				Mods.Add(item);
			}
		}

		public void ReloadMods()
		{
			Mods.Clear();
			LoadMods();
		}

		public AllMods()
		{
			LoadMods();
		}
	}
	public static class ArrayUtils
	{
		public static int[] GenerateArrayForNum(int characters)
		{
			if (characters <= 0)
			{
				return new int[1] { -1 };
			}
			int[] array = new int[characters + 1];
			for (int i = 1; i <= characters; i++)
			{
				array[i] = i;
			}
			return array;
		}

		public static IEnumerable<Character> SortBy(this IEnumerable<Character> c, int propertyId)
		{
			if (propertyId >= 3)
			{
				if (propertyId <= 8)
				{
					return c.OrderByDescending((Character x) => x.stat[propertyId - 2]);
				}
				switch (propertyId)
				{
				case 9:
					return c.OrderByDescending((Character x) => x.salary * x.contract);
				case 10:
					return c.OrderByDescending((Character x) => x.age);
				case 11:
					return c.OrderBy((Character x) => x.age);
				}
			}
			else
			{
				switch (propertyId)
				{
				case 1:
					return c.OrderBy((Character x) => x.name);
				case 2:
					return c.OrderByDescending((Character x) => x.health);
				}
			}
			return c;
		}
	}
	public class CharacterUtils
	{
		public static void SaveAsBackup(int id)
		{
			NonSavedData.DeletedCharacters.Add(Characters.c[id]);
		}

		public static void DeleteCharacter(int id)
		{
			if (id < 1 || id >= Characters.c.Length)
			{
				throw new IndexOutOfRangeException($"Character ID {id} is out of range!");
			}
			Character character = Characters.c[id];
			CharacterEvents.InvokeBeforeCharacterRemoved(id, character);
			try
			{
				SaveAsBackup(id);
				if (Characters.wrestler == id)
				{
					Characters.wrestler = 1;
				}
				else if (Characters.wrestler > id)
				{
					Characters.wrestler--;
				}
				if (Characters.booker == id)
				{
					Characters.booker = 1;
				}
				else if (Characters.booker > id)
				{
					Characters.booker--;
				}
				if (Progress.missionClient == id)
				{
					Progress.missionClient = 1;
				}
				else if (Progress.missionClient > id)
				{
					Progress.missionClient--;
				}
				if (Progress.missionTarget == id)
				{
					Progress.missionTarget = 1;
				}
				else if (Progress.missionTarget > id)
				{
					Progress.missionTarget--;
				}
				for (int i = 1; i < Progress.opponent.Length; i++)
				{
					if (Progress.opponent[i] == id)
					{
						Progress.opponent[i] = 1;
					}
					else if (Progress.opponent[i] > id)
					{
						Progress.opponent[i]--;
					}
				}
				Card[] card = Progress.card;
				foreach (Card val in card)
				{
					if (val == null)
					{
						continue;
					}
					Segment[] segment = val.segment;
					foreach (Segment val2 in segment)
					{
						if (val2 != null)
						{
							if (val2.leftChar == id)
							{
								val2.leftChar = 1;
							}
							else if (val2.leftChar > id)
							{
								val2.leftChar--;
							}
							if (val2.rightChar == id)
							{
								val2.rightChar = 1;
							}
							else if (val2.rightChar > id)
							{
								val2.rightChar--;
							}
							if (val2.winner == id)
							{
								val2.winner = 1;
							}
							else if (val2.winner > id)
							{
								val2.winner--;
							}
						}
					}
				}
				for (int l = 1; l < Progress.hiChar.Length; l++)
				{
					if (Progress.hiChar[l] == id)
					{
						Progress.hiChar[l] = 1;
					}
					else if (Progress.hiChar[l] > id)
					{
						Progress.hiChar[l]--;
					}
				}
				for (int m = 1; m < pHgYubURyX.rUJmOXjDQb.Length; m++)
				{
					if (pHgYubURyX.rUJmOXjDQb[m] != null)
					{
						if (pHgYubURyX.rUJmOXjDQb[m].owner == id)
						{
							pHgYubURyX.rUJmOXjDQb[m].owner = 1;
						}
						else if (pHgYubURyX.rUJmOXjDQb[m].owner > id)
						{
							Stock obj = pHgYubURyX.rUJmOXjDQb[m];
							obj.owner--;
						}
					}
				}
				for (int n = 1; n < ewgOQSWcRw.zEktxKOIAi.Length; n++)
				{
					if (ewgOQSWcRw.zEktxKOIAi[n] != null)
					{
						if (ewgOQSWcRw.zEktxKOIAi[n].owner == id)
						{
							ewgOQSWcRw.zEktxKOIAi[n].owner = 1;
						}
						else if (ewgOQSWcRw.zEktxKOIAi[n].owner > id)
						{
							Stock obj2 = ewgOQSWcRw.zEktxKOIAi[n];
							obj2.owner--;
						}
					}
				}
				Character[] c = Characters.c;
				foreach (Character val3 in c)
				{
					if (val3 == null)
					{
						continue;
					}
					for (int num = 1; num < val3.relationship.Length; num++)
					{
						if (val3.relationship[num] == id)
						{
							val3.relationship[num] = 1;
						}
						else if (val3.relationship[num] > id)
						{
							val3.relationship[num]--;
						}
					}
					for (int num2 = 1; num2 < val3.costume.Length; num2++)
					{
						if (val3.costume[num2] != null && val3.costume[num2].charID > id)
						{
							Costume obj3 = val3.costume[num2];
							obj3.charID--;
						}
					}
					if (val3.grudge == id)
					{
						val3.grudge = 1;
					}
					else if (val3.grudge > id)
					{
						val3.grudge--;
					}
				}
				Roster[] fedData = Characters.fedData;
				for (int j = 0; j < fedData.Length; j++)
				{
					DQQzmHCrQG dQQzmHCrQG = DQQzmHCrQG.pEDQSDPEFY(fedData[j]);
					if (dQQzmHCrQG == null)
					{
						continue;
					}
					if (dQQzmHCrQG.ONmBZKBHte == id)
					{
						dQQzmHCrQG.ONmBZKBHte = ((dQQzmHCrQG.ACBHgKnQbH <= 0) ? 1 : dQQzmHCrQG.xqUucKUhmQ());
					}
					else if (dQQzmHCrQG.ONmBZKBHte > id)
					{
						dQQzmHCrQG.ONmBZKBHte--;
					}
					if (dQQzmHCrQG.aejQuOowfO == id)
					{
						dQQzmHCrQG.aejQuOowfO = ((dQQzmHCrQG.ACBHgKnQbH <= 0) ? 1 : dQQzmHCrQG.xqUucKUhmQ());
					}
					else if (dQQzmHCrQG.aejQuOowfO > id)
					{
						dQQzmHCrQG.aejQuOowfO--;
					}
					for (int num3 = 1; num3 < dQQzmHCrQG.blhxRGlsOU.Length; num3++)
					{
						if (dQQzmHCrQG.blhxRGlsOU[num3] > id)
						{
							dQQzmHCrQG.blhxRGlsOU[num3]--;
						}
					}
					for (int num4 = 1; num4 < dQQzmHCrQG.YIITWWzahq.GetLength(0); num4++)
					{
						for (int num5 = 1; num5 < dQQzmHCrQG.YIITWWzahq.GetLength(1); num5++)
						{
							if (dQQzmHCrQG.YIITWWzahq[num4, num5] == id)
							{
								dQQzmHCrQG.YIITWWzahq[num4, num5] = ((dQQzmHCrQG.ACBHgKnQbH <= 0) ? 1 : dQQzmHCrQG.XJLbuseEeI(num4));
							}
							else if (dQQzmHCrQG.YIITWWzahq[num4, num5] > id)
							{
								dQQzmHCrQG.YIITWWzahq[num4, num5]--;
							}
						}
					}
				}
				DQQzmHCrQG.pEDQSDPEFY(Characters.fedData[Characters.c[id].fed]).ZBxVgrUIpZ(id);
				for (int num6 = id; num6 < Characters.c.Length - 1; num6++)
				{
					Characters.c[num6] = Characters.c[num6 + 1];
					Characters.c[num6].id = num6;
				}
				for (int num7 = id; num7 < Progress.charUnlock.Length - 1; num7++)
				{
					Progress.charUnlock[num7] = Progress.charUnlock[num7 + 1];
				}
				Characters.no_chars--;
				Array.Resize(ref Characters.c, Characters.no_chars + 1);
				Array.Resize(ref Progress.charUnlock, Characters.no_chars + 1);
				Array.Resize(ref GLPGLJAJJOP.APPDIBENDAH.savedChars, Characters.no_chars + 1);
				Array.Resize(ref GLPGLJAJJOP.APPDIBENDAH.charUnlock, Characters.no_chars + 1);
				CharacterEvents.InvokeAfterCharacterRemoved(id, character);
			}
			catch (Exception innerException)
			{
				CharacterEvents.InvokeAfterCharacterRemovedFailure(id, Characters.c[id]);
				throw new Exception($"Failed to delete character {id} ({Characters.c[id].name})!", innerException);
			}
		}

		public static void CreateRandomCharacter()
		{
			try
			{
				Character val = RKNjkgQube.otqpiLaMdi<Character>(Characters.c[1]);
				CharacterEvents.InvokeBeforeCharacterAdded(Characters.no_chars + 1, val);
				Characters.no_chars++;
				Array.Resize(ref Characters.c, Characters.no_chars + 1);
				Array.Resize(ref Progress.charUnlock, Characters.no_chars + 1);
				Array.Resize(ref GLPGLJAJJOP.APPDIBENDAH.savedChars, Characters.no_chars + 1);
				Array.Resize(ref GLPGLJAJJOP.APPDIBENDAH.charUnlock, Characters.no_chars + 1);
				Progress.charUnlock[Characters.no_chars] = 1;
				Characters.c[Characters.no_chars] = val;
				sBOSncgVDe.EkbepNLAcg(Characters.c[Characters.no_chars]).TJmwTqgDKq(Characters.no_chars);
				sBOSncgVDe.EkbepNLAcg(Characters.c[Characters.no_chars]).BCUTLHlsfT = -1;
				if (Characters.fedData[9].size + 1 == Characters.fedData[9].roster.Length)
				{
					Array.Resize(ref Characters.fedData[9].roster, Characters.fedData[9].roster.Length + 1);
					if (Characters.fedData[9].roster.Length > Characters.fedLimit)
					{
						Characters.fedLimit++;
						for (int i = 0; i <= Characters.no_feds; i++)
						{
							Array.Resize(ref Characters.fedData[i].roster, Characters.fedLimit + 1);
						}
					}
				}
				sBOSncgVDe.EkbepNLAcg(Characters.c[Characters.no_chars]).FPPvZPsLix(9);
				sBOSncgVDe.EkbepNLAcg(Characters.c[Characters.no_chars]).WVcJiRjTZM = "";
				CharacterEvents.InvokeAfterCharacterAdded(Characters.no_chars, Characters.c[Characters.no_chars]);
			}
			catch (Exception innerException)
			{
				CharacterEvents.InvokeAfterCharacterAddedFailure(Characters.no_chars, Characters.c[Characters.no_chars]);
				throw new Exception($"Failed to create random character {Characters.no_chars}!", innerException);
			}
		}
	}
	public class Checksum
	{
		public static string GetChecksum(byte[] bytes)
		{
			return BitConverter.ToString(MD5.Create().ComputeHash(bytes));
		}
	}
	public class ContentList : List<string>
	{
		public new string this[int index]
		{
			get
			{
				return base[index];
			}
			set
			{
				if (Aliases.AliasMap.TryGetValue(value, out var value2))
				{
					base[index] = value2;
				}
				else
				{
					base[index] = value;
				}
			}
		}

		public new void Add(string item)
		{
			if (Aliases.AliasMap.TryGetValue(item, out var value))
			{
				base.Add(value);
			}
			else
			{
				base.Add(item);
			}
		}

		public new void AddRange(IEnumerable<string> collection)
		{
			foreach (string item in collection)
			{
				if (Aliases.AliasMap.TryGetValue(item, out var value))
				{
					base.Add(value);
				}
				else
				{
					base.Add(item);
				}
			}
		}

		public new void Insert(int index, string item)
		{
			if (Aliases.AliasMap.TryGetValue(item, out var value))
			{
				base.Insert(index, value);
			}
			else
			{
				base.Insert(index, item);
			}
		}

		public new void InsertRange(int index, IEnumerable<string> collection)
		{
			foreach (string item in collection)
			{
				if (Aliases.AliasMap.TryGetValue(item, out var value))
				{
					base.Insert(index, value);
				}
				else
				{
					base.Insert(index, item);
				}
			}
		}

		public new bool Remove(string item)
		{
			if (Aliases.AliasMap.TryGetValue(item, out var value))
			{
				return base.Remove(value);
			}
			return base.Remove(item);
		}
	}
	internal static class DataSharing
	{
		private const string URL = "https://ingoh.net/weccl/data.php";

		private static string _uuid;

		private const string PATH_PATTERN = "([A-Z]:[\\\\/](?:[^\\\\/:\\n]*[\\\\/])*)([^\\\\/:\\n]*)";

		private static string DataUUID
		{
			get
			{
				object obj = _uuid;
				if (obj == null)
				{
					obj = LoadUUID() ?? GenerateUUID();
					_uuid = (string)obj;
				}
				return (string)obj;
			}
		}

		private static string GenerateUUID()
		{
			string text = Guid.NewGuid().ToString();
			LogUtils.LogDebug("Generated Data UUID: " + text);
			File.WriteAllText(Path.Combine(Plugin.PersistentDataPath, "uuid.txt"), text, Encoding.UTF8);
			return text;
		}

		private static string LoadUUID()
		{
			if (!File.Exists(Path.Combine(Plugin.PersistentDataPath, "uuid.txt")))
			{
				return null;
			}
			string text = File.ReadAllText(Path.Combine(Plugin.PersistentDataPath, "uuid.txt"), Encoding.UTF8);
			LogUtils.LogDebug("Loaded Data UUID: " + text);
			return text;
		}

		public static void SendExceptionToServer(string message, string stackTrace, string dataSharingLevel)
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			message = Regex.Replace(message, "([A-Z]:[\\\\/](?:[^\\\\/:\\n]*[\\\\/])*)([^\\\\/:\\n]*)", "#:$2");
			stackTrace = Regex.Replace(stackTrace, "([A-Z]:[\\\\/](?:[^\\\\/:\\n]*[\\\\/])*)([^\\\\/:\\n]*)", "#:$2");
			if (dataSharingLevel == "None")
			{
				return;
			}
			Dictionary<string, string> data;
			if (dataSharingLevel == "Full")
			{
				Dictionary<string, string> obj = new Dictionary<string, string>
				{
					{ "_uuid", DataUUID },
					{ "type", "exception" },
					{ "message", message },
					{ "stackTrace", stackTrace },
					{ "wecclVersion", "1.9.0" },
					{
						"installedMods",
						string.Join(",", Chainloader.PluginInfos.Select((KeyValuePair<string, PluginInfo> x) => x.Key))
					},
					{
						"prefixes",
						string.Join(",", CustomContent.Prefixes)
					},
					{
						"nonDefaultConfigValues",
						Plugin.GetNonDefaultConfigValues()
					}
				};
				Scene activeScene = SceneManager.GetActiveScene();
				obj.Add("currentScene", ((Scene)(ref activeScene)).name);
				obj.Add("numberOfCharacters", (Characters.c.Length - 1).ToString());
				data = obj;
			}
			else
			{
				data = new Dictionary<string, string>
				{
					{ "type", "exception" },
					{ "message", message },
					{ "stackTrace", stackTrace },
					{ "wecclVersion", "1.9.0" }
				};
			}
			new Thread((ThreadStart)delegate
			{
				try
				{
					HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("https://ingoh.net/weccl/data.php");
					httpWebRequest.Method = "POST";
					httpWebRequest.ContentType = "application/json";
					using (StreamWriter streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
					{
						string value = JsonConvert.SerializeObject((object)data);
						streamWriter.Write(value);
					}
					HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
					LogUtils.LogDebug("Data sent! Server response: " + httpWebResponse.StatusCode);
				}
				catch (Exception ex)
				{
					LogUtils.LogDebug("Error sending data to server: " + ex);
				}
			}).Start();
		}
	}
	public static class FileNameUtils
	{
		public static string Escape(string fileName)
		{
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			foreach (char oldChar in invalidFileNameChars)
			{
				fileName = fileName.Replace(oldChar, '_');
			}
			return fileName;
		}

		public static string FindPluginName(DirectoryInfo source)
		{
			while (source.Name != "plugins" && source.Parent != null)
			{
				source = source.Parent;
			}
			if (source.Parent?.Name == "BepInEx")
			{
				return "Assets";
			}
			return source.Parent?.Name ?? "Assets";
		}
	}
	public static class GoogleTranslate
	{
		public static string Translate(string text, string from, string to)
		{
			string address = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=" + from + "&tl=" + to + "&dt=t&q=" + Uri.EscapeUriString(text);
			return ToText(new WebClient().DownloadString(address));
		}

		private static string ToText(string result)
		{
			int num = result.IndexOf("\"", StringComparison.Ordinal) + 1;
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			for (int i = num; i < result.Length; i++)
			{
				char c = result[i];
				switch (c)
				{
				case '"':
					if (flag)
					{
						flag = false;
						continue;
					}
					break;
				case '\\':
					if (flag)
					{
						stringBuilder.Append('\\');
						flag = false;
					}
					else
					{
						flag = true;
					}
					continue;
				default:
					stringBuilder.Append(c);
					continue;
				}
				break;
			}
			return stringBuilder.ToString();
		}
	}
	public class Indices
	{
		public static Dictionary<string, int> CrowdAudio = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
		{
			{ "Train", 0 },
			{ "Oh", 1 },
			{ "Cheer", 2 },
			{ "Boo", 3 },
			{ "Yay", 4 },
			{ "Groan", 5 },
			{ "Excitement", 6 },
			{ "Murmur", 7 },
			{ "Laughter", 8 },
			{ "Applause", 9 },
			{ "Chant_Generic", 10 },
			{ "Stomping", 11 },
			{ "Chant_Yes", 12 },
			{ "Chant_Sucks", 13 },
			{ "Chant_Got", 14 },
			{ "Chant_Awesome", 15 },
			{ "Chant_CW", 16 },
			{ "Chant_Holy", 17 },
			{ "Chant_Fucked", 18 },
			{ "Chant_Wrestle", 19 },
			{ "Chant_Bullshit", 20 },
			{ "Chant_Boring", 21 },
			{ "Chant_USA", 22 },
			{ "Countdown", 30 },
			{ "Chant_Count01", 31 },
			{ "Chant_Count02", 32 },
			{ "Chant_Count03", 33 },
			{ "Chant_Count04", 34 },
			{ "Chant_Count05", 35 },
			{ "Chant_Count06", 36 },
			{ "Chant_Count07", 37 },
			{ "Chant_Count08", 38 },
			{ "Chant_Count09", 39 },
			{ "Chant_Count10", 40 },
			{ "Oh02", 41 },
			{ "Cheer02", 42 },
			{ "Boo02", 43 },
			{ "Yay02", 44 },
			{ "Groan02", 45 },
			{ "Excitement02", 46 },
			{ "Murmur02", 47 },
			{ "Laughter02", 48 },
			{ "Applause02", 49 },
			{ "Oh03", 51 },
			{ "Cheer03", 52 },
			{ "Boo03", 53 },
			{ "Yay03", 54 },
			{ "Groan03", 55 },
			{ "Excitement03", 56 },
			{ "Murmur03", 57 },
			{ "Laughter03", 58 },
			{ "Applause03", 59 }
		};

		public static Dictionary<string, int> TauntAnims = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
		{
			{ "[None]", 0 },
			{ "Wave", 1 },
			{ "Fist Palm", 2 },
			{ "Bring It", 3 },
			{ "Footwork", 4 },
			{ "Come Here", 5 },
			{ "Bicep Flex", 6 },
			{ "Wrist Fiddle", 7 },
			{ "Prayer", 8 },
			{ "Calm Down", 9 },
			{ "Fist Palm Down", 10 },
			{ "Rule Out", 11 },
			{ "Point At Ground", 12 },
			{ "Get Out Of My Face", 13 },
			{ "Single Count", 14 },
			{ "Double Count", 15 },
			{ "Disqualify", 16 },
			{ "Separate", 17 },
			{ "Resume", 18 },
			{ "Punch Air", 19 },
			{ "Make Decision", 20 },
			{ "Go Ahead", 21 },
			{ "Shake Raised Arms", 22 },
			{ "Pat Chest", 23 },
			{ "Go Away", 24 },
			{ "Folded Arms", 25 },
			{ "Can't See Me", 26 },
			{ "Invite Applause", 27 },
			{ "Ask The Question", 28 },
			{ "Speech Loop", 29 },
			{ "Self Abuse", 30 },
			{ "Wind Up", 31 },
			{ "Hands On Hips", 32 },
			{ "Disappointment", 33 },
			{ "Shake Fist", 34 },
			{ "Shake Trophy", 35 },
			{ "Shake Finger", 36 },
			{ "Point Forwards", 37 },
			{ "Point To Side", 38 },
			{ "Clap", 39 },
			{ "Raise Arm", 40 },
			{ "Raised Arms", 41 },
			{ "Outstretched Arms", 42 },
			{ "Dare To Hit", 43 },
			{ "Middle Fingers", 44 },
			{ "Gun Fingers", 45 },
			{ "Fancy Cupped Ear", 46 },
			{ "Crotch Chop", 47 },
			{ "X Sign", 48 },
			{ "Diamond Sign", 49 },
			{ "Power From Above", 50 },
			{ "Raise The Roof", 51 },
			{ "Fist Pump", 52 },
			{ "Overhead Fist Pump", 53 },
			{ "Throat Slice", 54 },
			{ "Beat Chest", 55 },
			{ "Emotional", 56 },
			{ "Salute", 57 },
			{ "Surrender", 58 },
			{ "Go To Sleep", 59 },
			{ "Belt Around Waist", 60 },
			{ "Waist Fiddle", 61 },
			{ "Pat Stomach", 62 },
			{ "Belt Over Shoulder", 63 },
			{ "Pat Shoulder", 64 },
			{ "Powerful Stance", 65 },
			{ "Speech B", 66 },
			{ "Thinking", 67 },
			{ "Hand On Chest", 68 },
			{ "Shrug Shoulders", 69 },
			{ "Stay Back", 70 },
			{ "Present", 71 },
			{ "Raise Hand", 72 },
			{ "Fist In Palm", 73 },
			{ "Fist On Palm", 74 },
			{ "Static Bicep Flex", 75 },
			{ "Pray Down", 76 },
			{ "Pray Up", 77 },
			{ "No Problem", 78 },
			{ "Yes Movement", 79 },
			{ "Pointed Fingers", 80 },
			{ "Point Upward", 81 },
			{ "Stay Separate", 82 },
			{ "Crossed Fingers", 83 },
			{ "Receive Applause", 84 },
			{ "Constant Disappointment", 85 },
			{ "Hold Trophy", 86 },
			{ "Raised Finger", 87 },
			{ "Point Straight Forwards", 88 },
			{ "Point Straight To Side", 89 },
			{ "Hands Together", 90 },
			{ "Middle Finger", 91 },
			{ "Cupped Ear", 92 },
			{ "Crotch Cross", 93 },
			{ "Clenched Fists", 94 },
			{ "Clenched Fist", 95 },
			{ "Raised Fist", 96 },
			{ "Head In Hands", 97 },
			{ "Microphone Speech", 98 },
			{ "Hold Camera (Right)", 99 },
			{ "Hold Camera (Left)", 100 },
			{ "Make Point", 101 },
			{ "Point At Chest", 102 },
			{ "Here Or There (Left)", 103 },
			{ "Point At Face", 104 },
			{ "Point At Head", 105 },
			{ "Thumb Shoulders", 106 },
			{ "Thumb Chest", 107 },
			{ "Thumb Raised", 108 },
			{ "Thumbs Up", 109 },
			{ "Thumb Outstretched", 110 },
			{ "Thumbs Down", 111 },
			{ "Here Or There (Right)", 112 },
			{ "Rub Fingers", 113 },
			{ "Roar", 114 },
			{ "Woo", 115 },
			{ "Unbelievable", 116 },
			{ "Grind Hips", 117 },
			{ "Grind Hip", 118 },
			{ "Grind Side To Side", 119 },
			{ "Muscle Pose A", 120 },
			{ "Muscle Pose B", 121 },
			{ "Muscle Pose C", 122 },
			{ "Muscle Pose Combo", 123 },
			{ "Cover Up", 124 },
			{ "Drink (Right)", 125 },
			{ "Drink (Left)", 126 },
			{ "Title Celebration (Rear Right)", 127 },
			{ "Title Celebration (Front Right)", 128 },
			{ "Title Celebration (Low Right)", 129 },
			{ "Clenched Titles", 130 },
			{ "Title Celebration (Rear Left)", 131 },
			{ "Title Celebration (Front Left)", 132 },
			{ "Hold Sign", 133 },
			{ "Point At Prop", 134 },
			{ "Bicep Curl (Right)", 135 },
			{ "Bicep Curl (Left)", 136 },
			{ "Need To Pee", 137 },
			{ "Need To Crap", 138 },
			{ "Style Hair", 139 },
			{ "Cue Action", 140 },
			{ "Polish Cue", 141 },
			{ "Pocket Right", 142 },
			{ "Pocket Left", 143 },
			{ "Pockets", 144 },
			{ "Pocket Loop", 145 },
			{ "Solemn", 146 },
			{ "Thumb Stampede", 147 },
			{ "Outstretched Edge", 148 },
			{ "Slide Through", 149 },
			{ "Slide Through Loop", 150 },
			{ "Too Sweet", 151 },
			{ "V Sign", 152 },
			{ "Puppetry", 153 },
			{ "Trembling Fingers", 154 },
			{ "Thumbs Into Outstretched", 155 },
			{ "Double Point", 156 },
			{ "Monster Claws", 157 },
			{ "Double Ring Burst", 158 },
			{ "Double Ring Loop", 159 },
			{ "OK Sign", 160 },
			{ "Double V Signs", 161 },
			{ "Two Sweet", 162 },
			{ "3 Fingers", 163 },
			{ "4 Fingers", 164 },
			{ "2 Fingers", 165 },
			{ "Count Fingers", 166 },
			{ "Eat (Left)", 167 },
			{ "Eat (Right)", 168 },
			{ "Examine (Left)", 169 },
			{ "Examine (Right)", 170 },
			{ "Examine Stick (Left)", 171 },
			{ "Examine Stick (Right)", 172 },
			{ "Selfie (Right)", 173 },
			{ "Phone Fiddle (Right)", 174 },
			{ "Selfie (Left)", 175 },
			{ "Phone Fiddle (Left)", 176 },
			{ "Quick Wave (Right)", 177 },
			{ "Quick Wave (Left)", 178 },
			{ "Guitar Strum", 179 },
			{ "Guitar Thrash", 180 },
			{ "Read Book (Right)", 181 },
			{ "Read Book (Left)", 182 },
			{ "Read Tablet (Right)", 183 },
			{ "Read Tablet (Left)", 184 }
		};

		public static int ParseCrowdAudio(string audio)
		{
			if (int.TryParse(audio, out var result))
			{
				if (result >= CrowdAudio.Count)
				{
					throw new Exception($"Crowd audio index out of range: {audio}, max: {CrowdAudio.Count - 1}");
				}
				return result;
			}
			if (CrowdAudio.TryGetValue(audio, out result))
			{
				return result;
			}
			throw new Exception("Unknown crowd audio: " + audio);
		}

		public static int ParseTauntAnim(string anim)
		{
			if (int.TryParse(anim, out var result))
			{
				if (result >= TauntAnims.Count)
				{
					throw new Exception($"Taunt animation index out of range: {anim}, max: {TauntAnims.Count - 1}");
				}
				return result;
			}
			if (TauntAnims.TryGetValue(anim.Replace("_", " "), out result))
			{
				return result;
			}
			throw new Exception("Unknown taunt animation: " + anim);
		}
	}
	public class LimitedDictionary<TKey, TValue> : SortedDictionary<TKey, TValue>
	{
		private readonly int _limit;

		public LimitedDictionary(int limit)
		{
			_limit = limit;
		}

		public new void Add(TKey key, TValue value)
		{
			if (base.Count >= _limit)
			{
				Remove(this.First().Key);
			}
			base.Add(key, value);
		}
	}
	public static class LogUtils
	{
		public static void LogInfo(object message)
		{
			string source = GetSource();
			if (source != null)
			{
				Plugin.Log.LogInfo((object)string.Format("[{1}] {0}", message, source));
			}
			else
			{
				Plugin.Log.LogInfo(message);
			}
		}

		public static void LogWarning(object message)
		{
			string source = GetSource();
			if (source != null)
			{
				Plugin.Log.LogWarning((object)string.Format("[{1}] {0}", message, source));
			}
			else
			{
				Plugin.Log.LogWarning(message);
			}
		}

		public static void LogError(object message)
		{
			string source = GetSource();
			if (source != null)
			{
				Plugin.Log.LogError((object)string.Format("[{1}] {0}", message, source));
			}
			else
			{
				Plugin.Log.LogError(message);
			}
		}

		public static void LogDebug(object message)
		{
			string source = GetSource();
			if (source != null)
			{
				Plugin.Log.LogDebug((object)string.Format("[{1}] {0}", message, source));
			}
			else
			{
				Plugin.Log.LogDebug(message);
			}
		}

		public static void LogFatal(object message)
		{
			string source = GetSource();
			if (source != null)
			{
				Plugin.Log.LogFatal((object)string.Format("[{1}] {0}", message, source));
			}
			else
			{
				Plugin.Log.LogFatal(message);
			}
		}

		private static string GetSource()
		{
			StackFrame[] frames = new StackTrace().GetFrames();
			if (frames == null)
			{
				return null;
			}
			StackFrame[] array = frames;
			for (int i = 0; i < array.Length; i++)
			{
				MethodBase method = array[i].GetMethod();
				if (method == null)
				{
					continue;
				}
				Type declaringType = method.DeclaringType;
				if (declaringType == null)
				{
					continue;
				}
				string name = declaringType.Name;
				if (name != null && !(name == "LogUtils"))
				{
					while (name.StartsWith("<") && declaringType.DeclaringType != null)
					{
						declaringType = declaringType.DeclaringType;
						name = declaringType.Name;
					}
					if (!name.StartsWith("<"))
					{
						return name;
					}
				}
			}
			return null;
		}

		public static T Linfo<T>(T message)
		{
			LogInfo(message.ToString());
			return message;
		}

		public static T Lwarn<T>(T message)
		{
			LogWarning(message.ToString());
			return message;
		}

		public static T Lerr<T>(T message)
		{
			LogError(message.ToString());
			return message;
		}

		public static T Ldbg<T>(T message)
		{
			LogDebug(message.ToString());
			return message;
		}

		public static T Lfat<T>(T message)
		{
			LogFatal(message.ToString());
			return message;
		}
	}
	public static class MenuUtils
	{
		internal static float PrevScale = 1f;

		internal static readonly Dictionary<int, Tuple<int, int, float, int, int>> _optimalLayouts = new Dictionary<int, Tuple<int, int, float, int, int>>();

		public static void FindBestFit(int size, int minX, int minY, int maxX, int maxY, out int rows, out int columns, out float scale, out int startX, out int startY)
		{
			if (_optimalLayouts.TryGetValue(size, out var value))
			{
				rows = value.Item1;
				columns = value.Item2;
				scale = value.Item3;
				startX = value.Item4;
				startY = value.Item5;
				PrevScale = scale;
				return;
			}
			int num = ((size > 35) ? 210 : 245);
			int num2 = ((size > 48) ? 50 : 60);
			int num3 = maxX - minX;
			int num4 = maxY - minY;
			float num5 = 1.25f;
			if (size > 48)
			{
				num5 = 1f;
			}
			int num6;
			int num7;
			int num8;
			int num9;
			int num10;
			int num11;
			while (true)
			{
				num6 = num3 + (int)((float)num * num5);
				num7 = num4 + (int)((float)num2 * num5);
				num8 = (int)((float)num * num5);
				num9 = (int)((float)num2 * num5);
				num10 = num6 / num8;
				num11 = num7 / num9;
				if (num10 * num11 >= size)
				{
					break;
				}
				num5 /= 1.05f;
			}
			rows = num11;
			columns = num10;
			scale = num5;
			int num12 = num10 * num8;
			startX = minX + (num6 - num12) / 2;
			int num13 = num11 * num9;
			startY = maxY - (num7 - num13) / 2;
			LogUtils.LogDebug($"Found best fit for {size} items: {rows} rows, {columns} columns, {scale} scale, {startX} startX, {startY} startY");
			_optimalLayouts.Add(size, new Tuple<int, int, float, int, int>(rows, columns, scale, startX, startY));
			PrevScale = num5;
		}

		public static float Scale(float size)
		{
			return size * PrevScale;
		}
	}
	public static class NumberFormatUtils
	{
		public static NumberFormatInfo Nfi = new NumberFormatInfo
		{
			NumberDecimalSeparator = "."
		};
	}
	public static class OS
	{
		public static OperatingSystemFamily Os => SystemInfo.operatingSystemFamily;

		public static string GetOSString(string def = "other", bool lowercase = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected I4, but got Unknown
			OperatingSystemFamily os = Os;
			return (os - 1) switch
			{
				0 => lowercase ? "macos" : "MacOS", 
				1 => lowercase ? "windows" : "Windows", 
				2 => lowercase ? "linux" : "Linux", 
				_ => lowercase ? def.ToLower() : def, 
			};
		}
	}
	internal class SaveRemapper
	{
		internal static void PatchCustomContent(ref SaveData saveData)
		{
			ContentMappings contentMap = ContentMappings.ContentMap;
			ContentMappings contentMappings = SaveFilePatch.LoadPreviousMap();
			if (!VanillaCounts.Data.IsInitialized)
			{
				LogUtils.LogError("Vanilla counts not initialized. Skipping custom content patch.");
				return;
			}
			int num = Mathf.RoundToInt(ContentMappings.ContentMap.GameVersion * 100f);
			int num2 = Mathf.RoundToInt(163f);
			VersionDiff versionDiff = null;
			if (num != num2)
			{
				LogUtils.LogInfo($"Game version changed from {num} to {num2}. Updating custom content map.");
				if (ContentMappings.ContentMap.VanillaCounts == null)
				{
					List<VersionDiff> list = new List<VersionDiff>();
					if (num < 156 && num2 >= 156)
					{
						list.Add(new V155toV156());
					}
					if (num < 159 && num2 >= 159)
					{
						list.Add(new V158toV159());
					}
					if (num < 160 && num2 >= 160)
					{
						list.Add(new V159toV160());
					}
					if (num < 161 && num2 >= 161)
					{
						list.Add(new V160toV161());
					}
					versionDiff = new VersionDiffGroup(list.ToArray());
				}
				else
				{
					versionDiff = VersionDiff.GetVersionDiff(ContentMappings.ContentMap.VanillaCounts);
				}
			}
			ContentMappings.ContentMap.VanillaCounts = VanillaCounts.Data;
			try
			{
				Character[] savedChars = saveData.savedChars;
				foreach (Character val in savedChars)
				{
					if (val == null)
					{
						continue;
					}
					Costume[] costume = val.costume;
					foreach (Costume val2 in costume)
					{
						if (val2 == null)
						{
							continue;
						}
						for (int k = 0; k < val2.texture.Length; k++)
						{
							if (VanillaCounts.Data.MaterialCounts[k] == 0)
							{
								continue;
							}
							if (versionDiff != null)
							{
								if (versionDiff.MaterialCountsDiff[k] != 0 && val2.texture[k] > VanillaCounts.Data.MaterialCounts[k] - versionDiff.MaterialCountsDiff[k])
								{
									val2.texture[k] += versionDiff.MaterialCountsDiff[k];
								}
								else if (k == 3 && versionDiff.FaceFemaleCountDiff != 0 && val2.texture[k] < -VanillaCounts.Data.FaceFemaleCount + versionDiff.FaceFemaleCountDiff)
								{
									val2.texture[k] -= versionDiff.FaceFemaleCountDiff;
								}
								else if (k == 14 && versionDiff.SpecialFootwearCountDiff != 0 && val2.texture[k] < -VanillaCounts.Data.SpecialFootwearCount + versionDiff.SpecialFootwearCountDiff)
								{
									val2.texture[k] -= versionDiff.SpecialFootwearCountDiff;
								}
								else if (k == 15 && versionDiff.SpecialFootwearCountDiff != 0 && val2.texture[k] < -VanillaCounts.Data.SpecialFootwearCount + versionDiff.SpecialFootwearCountDiff)
								{
									val2.texture[k] -= versionDiff.SpecialFootwearCountDiff;
								}
								else if (k == 17 && versionDiff.TransparentHairMaterialCountDiff != 0 && val2.texture[k] < -VanillaCounts.Data.TransparentHairMaterialCount + versionDiff.TransparentHairMaterialCountDiff)
								{
									val2.texture[k] -= versionDiff.TransparentHairMaterialCountDiff;
								}
								else if (k == 24 && versionDiff.KneepadCountDiff != 0 && val2.texture[k] < -VanillaCounts.Data.KneepadCount + versionDiff.KneepadCountDiff)
								{
									val2.texture[k] -= versionDiff.KneepadCountDiff;
								}
								else if (k == 25 && versionDiff.KneepadCountDiff != 0 && val2.texture[k] < -VanillaCounts.Data.KneepadCount + versionDiff.KneepadCountDiff)
								{
									val2.texture[k] -= versionDiff.KneepadCountDiff;
								}
							}
							if (val2.texture[k] > VanillaCounts.Data.MaterialCounts[k])
							{
								int num3 = val2.texture[k] - VanillaCounts.Data.MaterialCounts[k] - 1;
								if (num3 >= contentMappings.MaterialNameMap[k].Count)
								{
									LogUtils.LogWarning($"Custom material {k} index {num3} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.texture[k] = VanillaCounts.Data.MaterialCounts[k];
									continue;
								}
								string text = contentMappings.MaterialNameMap[k][num3];
								int num4 = contentMap.MaterialNameMap[k].IndexOf(text);
								int num5 = num4 + VanillaCounts.Data.MaterialCounts[k] + 1;
								if (val2.texture[k] != num5)
								{
									LogUtils.LogInfo($"Custom material {text} at index {num3} was remapped to index {num4} (internal index {num5}) for material {k} of character {val.name} ({val.id}).");
									val2.texture[k] = num5;
								}
							}
							else if (k == 3 && val2.texture[k] < -VanillaCounts.Data.FaceFemaleCount)
							{
								int num6 = -val2.texture[k] - VanillaCounts.Data.FaceFemaleCount - 1;
								if (num6 >= contentMappings.FaceFemaleNameMap.Count)
								{
									LogUtils.LogWarning($"Custom material {k} index {num6} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.texture[k] = VanillaCounts.Data.MaterialCounts[k];
									continue;
								}
								string text2 = contentMappings.FaceFemaleNameMap[num6];
								int num7 = contentMap.FaceFemaleNameMap.IndexOf(text2);
								int num8 = -num7 - VanillaCounts.Data.FaceFemaleCount - 1;
								if (val2.texture[k] != num8)
								{
									LogUtils.LogInfo($"Custom material {text2} at index {num6} was remapped to index {num7} (internal index {num8}) for material {k} of character {val.name} ({val.id}).");
									val2.texture[k] = num8;
								}
							}
							else if (k == 14 && val2.texture[k] < -VanillaCounts.Data.SpecialFootwearCount)
							{
								int num9 = -val2.texture[k] - VanillaCounts.Data.SpecialFootwearCount - 1;
								if (num9 >= contentMappings.SpecialFootwearNameMap.Count)
								{
									LogUtils.LogWarning($"Custom material {k} index {num9} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.texture[k] = VanillaCounts.Data.MaterialCounts[k];
									continue;
								}
								string text3 = contentMappings.SpecialFootwearNameMap[num9];
								int num10 = contentMap.SpecialFootwearNameMap.IndexOf(text3);
								int num11 = -num10 - VanillaCounts.Data.SpecialFootwearCount - 1;
								if (val2.texture[k] != num11)
								{
									LogUtils.LogInfo($"Custom material {text3} at index {num9} was remapped to index {num10} (internal index {num11}) for material {k} of character {val.name} ({val.id}).");
									val2.texture[k] = num11;
								}
							}
							else if (k == 15 && val2.texture[k] < -VanillaCounts.Data.SpecialFootwearCount)
							{
								int num12 = -val2.texture[k] - VanillaCounts.Data.SpecialFootwearCount - 1;
								if (num12 >= contentMappings.SpecialFootwearNameMap.Count)
								{
									LogUtils.LogWarning($"Custom material {k} index {num12} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.texture[k] = VanillaCounts.Data.MaterialCounts[k];
									continue;
								}
								string text4 = contentMappings.SpecialFootwearNameMap[num12];
								int num13 = contentMap.SpecialFootwearNameMap.IndexOf(text4);
								int num14 = -num13 - VanillaCounts.Data.SpecialFootwearCount - 1;
								if (val2.texture[k] != num14)
								{
									LogUtils.LogInfo($"Custom material {text4} at index {num12} was remapped to index {num13} (internal index {num14}) for material {k} of character {val.name} ({val.id}).");
									val2.texture[k] = num14;
								}
							}
							else if (k == 17 && val2.texture[k] < -VanillaCounts.Data.TransparentHairMaterialCount)
							{
								int num15 = -val2.texture[k] - VanillaCounts.Data.TransparentHairMaterialCount - 1;
								if (num15 >= contentMappings.TransparentHairMaterialNameMap.Count)
								{
									LogUtils.LogWarning($"Custom material {k} index {num15} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.texture[k] = VanillaCounts.Data.MaterialCounts[k];
									continue;
								}
								string text5 = contentMappings.TransparentHairMaterialNameMap[num15];
								int num16 = contentMap.TransparentHairMaterialNameMap.IndexOf(text5);
								int num17 = -num16 - VanillaCounts.Data.TransparentHairMaterialCount - 1;
								if (val2.texture[k] != num17)
								{
									LogUtils.LogInfo($"Custom material {text5} at index {num15} was remapped to index {num16} (internal index {num17}) for material {k} of character {val.name} ({val.id}).");
									val2.texture[k] = num17;
								}
							}
							else if (k == 24 && val2.texture[k] < -VanillaCounts.Data.KneepadCount)
							{
								int num18 = -val2.texture[k] - VanillaCounts.Data.KneepadCount - 1;
								if (num18 >= contentMappings.KneepadNameMap.Count)
								{
									LogUtils.LogWarning($"Custom material {k} index {num18} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.texture[k] = VanillaCounts.Data.MaterialCounts[k];
									continue;
								}
								string text6 = contentMappings.KneepadNameMap[num18];
								int num19 = contentMap.KneepadNameMap.IndexOf(text6);
								int num20 = -num19 - VanillaCounts.Data.KneepadCount - 1;
								if (val2.texture[k] != num20)
								{
									LogUtils.LogInfo($"Custom material {text6} at index {num18} was remapped to index {num19} (internal index {num20}) for material {k} of character {val.name} ({val.id}).");
									val2.texture[k] = num20;
								}
							}
							else
							{
								if (k != 25 || val2.texture[k] >= -VanillaCounts.Data.KneepadCount)
								{
									continue;
								}
								int num21 = -val2.texture[k] - VanillaCounts.Data.KneepadCount - 1;
								if (num21 >= contentMappings.KneepadNameMap.Count)
								{
									LogUtils.LogWarning($"Custom material {k} index {num21} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.texture[k] = VanillaCounts.Data.MaterialCounts[k];
									continue;
								}
								string text7 = contentMappings.KneepadNameMap[num21];
								int num22 = contentMap.KneepadNameMap.IndexOf(text7);
								int num23 = -num22 - VanillaCounts.Data.KneepadCount - 1;
								if (val2.texture[k] != num23)
								{
									LogUtils.LogInfo($"Custom material {text7} at index {num21} was remapped to index {num22} (internal index {num23}) for material {k} of character {val.name} ({val.id}).");
									val2.texture[k] = num23;
								}
							}
						}
						for (int l = 0; l < val2.flesh.Length; l++)
						{
							if (VanillaCounts.Data.FleshCounts[l] == 0)
							{
								continue;
							}
							if (versionDiff != null)
							{
								if (versionDiff.FleshCountsDiff[l] != 0 && val2.flesh[l] > VanillaCounts.Data.FleshCounts[l] - versionDiff.FleshCountsDiff[l])
								{
									val2.flesh[l] += versionDiff.FleshCountsDiff[l];
								}
								else if (l == 2 && versionDiff.BodyFemaleCountDiff != 0 && val2.flesh[l] < -VanillaCounts.Data.BodyFemaleCount + versionDiff.BodyFemaleCountDiff)
								{
									val2.flesh[l] -= versionDiff.BodyFemaleCountDiff;
								}
							}
							if (val2.flesh[l] > VanillaCounts.Data.FleshCounts[l])
							{
								int num24 = val2.flesh[l] - VanillaCounts.Data.FleshCounts[l] - 1;
								if (num24 >= contentMappings.FleshNameMap[l].Count)
								{
									LogUtils.LogWarning($"Custom flesh index {num24} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.flesh[l] = VanillaCounts.Data.FleshCounts[l];
									continue;
								}
								string text8 = contentMappings.FleshNameMap[l][num24];
								int num25 = contentMap.FleshNameMap[l].IndexOf(text8);
								int num26 = num25 + VanillaCounts.Data.FleshCounts[l] + 1;
								if (val2.flesh[l] != num26)
								{
									LogUtils.LogInfo($"Custom flesh {text8} at index {num24} was remapped to index {num25} (internal index {num26}) for flesh {l} of character {val.name} ({val.id}).");
									val2.flesh[l] = num26;
								}
							}
							else
							{
								if (l != 2 || val2.flesh[l] >= -VanillaCounts.Data.BodyFemaleCount)
								{
									continue;
								}
								int num27 = -val2.flesh[l] - VanillaCounts.Data.BodyFemaleCount - 1;
								if (num27 >= contentMappings.BodyFemaleNameMap.Count)
								{
									LogUtils.LogWarning($"Custom flesh index {num27} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.flesh[l] = VanillaCounts.Data.FleshCounts[l];
									continue;
								}
								string text9 = contentMappings.BodyFemaleNameMap[num27];
								int num28 = contentMap.BodyFemaleNameMap.IndexOf(text9);
								int num29 = -num28 - VanillaCounts.Data.BodyFemaleCount - 1;
								if (val2.flesh[l] != num29)
								{
									LogUtils.LogInfo($"Custom flesh {text9} at index {num27} was remapped to index {num28} (internal index {num29}) for flesh {l} of character {val.name} ({val.id}).");
									val2.flesh[l] = num29;
								}
							}
						}
						for (int m = 0; m < val2.shape.Length; m++)
						{
							if (VanillaCounts.Data.ShapeCounts[m] == 0)
							{
								continue;
							}
							if (versionDiff != null)
							{
								if (versionDiff.ShapeCountsDiff[m] != 0 && val2.shape[m] > VanillaCounts.Data.ShapeCounts[m] - versionDiff.ShapeCountsDiff[m])
								{
									val2.shape[m] += versionDiff.ShapeCountsDiff[m];
								}
								else if (m == 17 && versionDiff.TransparentHairHairstyleCountDiff != 0 && val2.shape[m] < -VanillaCounts.Data.TransparentHairHairstyleCount + versionDiff.TransparentHairHairstyleCountDiff)
								{
									val2.shape[m] -= versionDiff.TransparentHairHairstyleCountDiff;
								}
							}
							if (val2.shape[m] > VanillaCounts.Data.ShapeCounts[m])
							{
								int num30 = val2.shape[m] - VanillaCounts.Data.ShapeCounts[m] - 1;
								if (num30 >= contentMappings.ShapeNameMap[m].Count)
								{
									LogUtils.LogWarning($"Custom shape index {num30} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.shape[m] = VanillaCounts.Data.ShapeCounts[m];
									continue;
								}
								string text10 = contentMappings.ShapeNameMap[m][num30];
								int num31 = contentMap.ShapeNameMap[m].IndexOf(text10);
								int num32 = num31 + VanillaCounts.Data.ShapeCounts[m] + 1;
								if (val2.shape[m] != num32)
								{
									LogUtils.LogInfo($"Custom shape {text10} at index {num30} was remapped to index {num31} (internal index {num32}) for shape {m} of character {val.name} ({val.id}).");
									val2.shape[m] = num32;
								}
							}
							else
							{
								if (m != 17 || val2.shape[m] >= -VanillaCounts.Data.TransparentHairHairstyleCount)
								{
									continue;
								}
								int num33 = -val2.shape[m] - VanillaCounts.Data.TransparentHairHairstyleCount - 1;
								if (num33 >= contentMappings.TransparentHairHairstyleNameMap.Count)
								{
									LogUtils.LogWarning($"Custom shape index {num33} is out of bounds for character {val.name} ({val.id}). Resetting.");
									val2.shape[m] = VanillaCounts.Data.ShapeCounts[m];
									continue;
								}
								string text11 = contentMappings.TransparentHairHairstyleNameMap[num33];
								int num34 = contentMap.TransparentHairHairstyleNameMap.IndexOf(text11);
								int num35 = -num34 - VanillaCounts.Data.TransparentHairHairstyleCount - 1;
								if (val2.shape[m] != num35)
								{
									LogUtils.LogInfo($"Custom shape {text11} at index {num33} was remapped to index {num34} (internal index {num35}) for shape {m} of character {val.name} ({val.id}).");
									val2.shape[m] = num35;
								}
							}
						}
					}
					if (versionDiff != null && versionDiff.MusicCountDiff != 0 && val.music > VanillaCounts.Data.MusicCount - versionDiff.MusicCountDiff)
					{
						val.music += versionDiff.MusicCountDiff;
					}
					if (val.music <= VanillaCounts.Data.MusicCount)
					{
						continue;
					}
					int num36 = val.music - VanillaCounts.Data.MusicCount - 1;
					if (num36 >= contentMappings.MusicNameMap.Count)
					{
						LogUtils.LogWarning($"Custom music index {num36} is out of bounds for character {val.name} ({val.id}). Resetting.");
						val.music = VanillaCounts.Data.MusicCount;
						continue;
					}
					string text12 = contentMappings.MusicNameMap[num36];
					int num37 = contentMap.MusicNameMap.IndexOf(text12);
					int num38 = num37 + VanillaCounts.Data.MusicCount + 1;
					if (val.music != num38)
					{
						LogUtils.LogInfo($"Custom music {text12} at index {num36} was remapped to index {num37} (internal index {num38}) for character {val.name} ({val.id}).");
						val.music = num38;
					}
				}
			}
			catch (Exception message)
			{
				LogUtils.LogError("Failed to remap custom content!");
				LogUtils.LogError(message);
			}
			ContentList animationNameMap = contentMappings.AnimationNameMap;
			ContentList animationNameMap2 = contentMap.AnimationNameMap;
			for (int n = 0; n < animationNameMap.Count; n++)
			{
				if (n < animationNameMap2.Count && animationNameMap[n] == animationNameMap2[n])
				{
					continue;
				}
				int num39 = animationNameMap2.IndexOf(animationNameMap[n]);
				if (num39 == -1)
				{
					LogUtils.LogWarning("Animation " + animationNameMap[n] + " not found in new map. Resetting to default.");
				}
				else
				{
					LogUtils.LogInfo("Animation " + animationNameMap[n] + " remapped to " + animationNameMap2[num39] + ".");
				}
				for (int num40 = 1; num40 < saveData.savedChars.Length; num40++)
				{
					if (saveData.savedChars[num40] == null)
					{
						continue;
					}
					for (int num41 = 0; num41 < saveData.savedChars[num40].moveAttack.Length; num41++)
					{
						if (saveData.savedChars[num40].moveAttack[num41] == n + 1000000)
						{
							saveData.savedChars[num40].moveAttack[num41] = ((num39 == -1) ? DefaultMove('a', num41) : (num39 + 1000000));
						}
					}
					for (int num42 = 0; num42 < saveData.savedChars[num40].moveCrush.Length; num42++)
					{
						if (saveData.savedChars[num40].moveCrush[num42] == n + 1000000)
						{
							saveData.savedChars[num40].moveCrush[num42] = ((num39 == -1) ? DefaultMove('c', num42) : (num39 + 1000000));
						}
					}
					for (int num43 = 0; num43 < saveData.savedChars[num40].moveFront.Length; num43++)
					{
						if (saveData.savedChars[num40].moveFront[num43] == n + 1000000)
						{
							saveData.savedChars[num40].moveFront[num43] = ((num39 == -1) ? DefaultMove('f', num43) : (num39 + 1000000));
						}
					}
					for (int num44 = 0; num44 < saveData.savedChars[num40].moveBack.Length; num44++)
					{
						if (saveData.savedChars[num40].moveBack[num44] == n + 1000000)
						{
							saveData.savedChars[num40].moveBack[num44] = ((num39 == -1) ? DefaultMove('b', num44) : (num39 + 1000000));
						}
					}
					for (int num45 = 0; num45 < saveData.savedChars[num40].moveGround.Length; num45++)
					{
						if (saveData.savedChars[num40].moveGround[num45] == n + 1000000)
						{
							saveData.savedChars[num40].moveGround[num45] = ((num39 == -1) ? DefaultMove('g', num45) : (num39 + 1000000));
						}
					}
					for (int num46 = 0; num46 < saveData.savedChars[num40].taunt.Length; num46++)
					{
						if (saveData.savedChars[num40].taunt[num46] == n + 1000000)
						{
							saveData.savedChars[num40].taunt[num46] = ((num39 == -1) ? DefaultMove('t', num46) : (num39 + 1000000));
						}
					}
				}
			}
		}

		private static int DefaultMove(char type, int index)
		{
			switch (type)
			{
			case 'a':
				switch (index)
				{
				case 0:
					return 0;
				case 1:
					return 1002;
				case 2:
					return 1061;
				case 3:
					return 1124;
				case 4:
					return 1111;
				case 5:
					return 1306;
				case 6:
					return 1304;
				case 7:
					return 1302;
				case 8:
					return 1350;
				}
				break;
			case 'c':
				switch (index)
				{
				case 0:
					return 0;
				case 1:
					return 1205;
				case 2:
					return 1201;
				case 3:
					return 1211;
				case 4:
					return 1211;
				case 5:
					return 1350;
				case 6:
					return 1353;
				case 7:
					return 1350;
				case 8:
					return 1350;
				}
				break;
			case 'f':
				switch (index)
				{
				case 0:
					return 291;
				case 1:
					return 278;
				case 2:
					return 603;
				case 3:
					return 272;
				case 4:
					return 257;
				case 5:
					return 281;
				case 6:
					return 235;
				case 7:
					return 253;
				case 8:
					return 298;
				case 9:
					return 280;
				case 10:
					return 299;
				case 11:
					return 604;
				case 12:
					return 219;
				case 13:
					return 299;
				case 14:
					return 280;
				case 15:
					return 280;
				case 16:
					return 512;
				}
				break;
			case 'b':
				switch (index)
				{
				case 0:
					return 328;
				case 1:
					return 325;
				case 2:
					return 320;
				case 3:
					return 313;
				case 4:
					return 311;
				case 5:
					return 337;
				case 6:
					return 327;
				case 7:
					return 334;
				case 8:
					return 334;
				}
				break;
			case 'g':
				switch (index)
				{
				case 0:
					return 0;
				case 1:
					return 412;
				case 2:
					return 417;
				case 3:
					return 413;
				case 4:
					return 471;
				case 5:
					return 464;
				case 6:
					return 456;
				}
				break;
			case 't':
				switch (index)
				{
				case 0:
					return 15;
				case 1:
					return 5;
				case 2:
					return 94;
				case 3:
					return 15;
				}
				break;
			}
			return 0;
		}

		public static void FixBrokenSaveData()
		{
			LogUtils.LogInfo("Validating save data...");
			SaveData aPPDIBENDAH = GLPGLJAJJOP.APPDIBENDAH;
			int num = aPPDIBENDAH.savedChars.Length;
			for (int num2 = aPPDIBENDAH.savedChars.Length - 1; num2 >= 1; num2--)
			{
				if (aPPDIBENDAH.savedChars[num2].id != num2)
				{
					LogUtils.LogWarning($"Character index {num2} does not match ID {aPPDIBENDAH.savedChars[num2].id}. Fixing.");
					aPPDIBENDAH.savedChars[num2].id = num2;
				}
				for (int i = 1; i < aPPDIBENDAH.savedChars[num2].costume.Length; i++)
				{
					if (aPPDIBENDAH.savedChars[num2].costume[i].charID > num)
					{
						LogUtils.LogWarning($"Costume index {i} of character index {num2} has character ID {aPPDIBENDAH.savedChars[num2].costume[i].charID} out of bounds. Resetting to id.");
						aPPDIBENDAH.savedChars[num2].costume[i].charID = num2;
					}
				}
			}
			List<int> list = new List<int>();
			for (int j = 0; j < aPPDIBENDAH.savedFeds.Length; j++)
			{
				if (aPPDIBENDAH.savedFeds[j] == null)
				{
					LogUtils.LogError($"Fed index {j} is null!");
				}
				if (aPPDIBENDAH.savedFeds[j].size > aPPDIBENDAH.savedFeds[j].roster.Length - 1)
				{
					LogUtils.LogWarning($"Fed index {j} has roster size {aPPDIBENDAH.savedFeds[j].size} but only {aPPDIBENDAH.savedFeds[j].roster.Length - 1} characters. Fixing.");
					aPPDIBENDAH.savedFeds[j].size = aPPDIBENDAH.savedFeds[j].roster.Length - 1;
				}
				for (int k = 1; k <= aPPDIBENDAH.savedFeds[j].size; k++)
				{
					int num3 = aPPDIBENDAH.savedFeds[j].roster[k];
					if (list.Contains(num3))
					{
						LogUtils.LogWarning($"Character index {num3} ({aPPDIBENDAH.savedChars[num3].name}) is used multiple times.");
					}
					else
					{
						list.Add(num3);
					}
				}
			}
			for (int l = 1; l < aPPDIBENDAH.savedChars.Length; l++)
			{
				if (!list.Contains(l) && aPPDIBENDAH.savedChars[l].fed != -1)
				{
					LogUtils.LogWarning($"Character index {l} is not used in any roster. Adding to free agents.");
					Roster obj = aPPDIBENDAH.savedFeds[9];
					obj.size++;
					if (aPPDIBENDAH.savedFeds[9].roster.Length <= aPPDIBENDAH.savedFeds[9].size)
					{
						Array.Resize(ref aPPDIBENDAH.savedFeds[9].roster, aPPDIBENDAH.savedFeds[9].size + 1);
					}
					aPPDIBENDAH.savedFeds[9].roster[aPPDIBENDAH.savedFeds[9].size] = l;
					aPPDIBENDAH.savedChars[l].fed = 9;
					sBOSncgVDe.EkbepNLAcg(aPPDIBENDAH.savedChars[l]).xWCRtFrbvK();
				}
			}
			if (aPPDIBENDAH.wrestler > num)
			{
				LogUtils.LogWarning($"Wrestler index {aPPDIBENDAH.wrestler} is out of bounds. Resetting to 1.");
				aPPDIBENDAH.wrestler = 1;
			}
			if (aPPDIBENDAH.booker > num)
			{
				LogUtils.LogWarning($"Booker index {aPPDIBENDAH.booker} is out of bounds. Resetting to 1.");
				aPPDIBENDAH.booker = 1;
			}
			if (aPPDIBENDAH.missionClient > num)
			{
				LogUtils.LogWarning($"Mission client index {aPPDIBENDAH.missionClient} is out of bounds. Resetting to 1.");
				aPPDIBENDAH.missionClient = 1;
			}
			if (aPPDIBENDAH.missionTarget > num)
			{
				LogUtils.LogWarning($"Mission target index {aPPDIBENDAH.missionTarget} is out of bounds. Resetting to 1.");
				aPPDIBENDAH.missionTarget = 1;
			}
			if (aPPDIBENDAH.bookingMissionClient > num)
			{
				LogUtils.LogWarning($"Booking mission client index {aPPDIBENDAH.bookingMissionClient} is out of bounds. Resetting to 1.");
				aPPDIBENDAH.bookingMissionClient = 1;
			}
			if (aPPDIBENDAH.bookingMissionTarget > num)
			{
				LogUtils.LogWarning($"Booking mission target index {aPPDIBENDAH.bookingMissionTarget} is out of bounds. Resetting to 1.");
				aPPDIBENDAH.bookingMissionTarget = 1;
			}
			if (aPPDIBENDAH.charUnlock.Length != num)
			{
				LogUtils.LogWarning($"Character unlock array length {aPPDIBENDAH.charUnlock.Length} does not match number of characters {num}. Fixing.");
				int num4 = aPPDIBENDAH.charUnlock.Length;
				Array.Resize(ref aPPDIBENDAH.charUnlock, num);
				if (num4 < num)
				{
					for (int m = num4; m < num; m++)
					{
						aPPDIBENDAH.charUnlock[m] = 1;
					}
				}
			}
			for (int n = 1; n < aPPDIBENDAH.opponent.Length; n++)
			{
				int num5 = aPPDIBENDAH.opponent[n];
				if (num5 > num)
				{
					LogUtils.LogWarning($"Opponent index {num5} is out of bounds. Resetting to 1.");
					aPPDIBENDAH.opponent[n] = 1;
				}
			}
			for (int num6 = 1; num6 < aPPDIBENDAH.bookingOpponent.Length; num6++)
			{
				int num7 = aPPDIBENDAH.bookingOpponent[num6];
				if (num7 > num)
				{
					LogUtils.LogWarning($"Booking opponent index {num7} is out of bounds. Resetting to 1.");
					aPPDIBENDAH.bookingOpponent[num6] = 1;
				}
			}
			Card[] card = aPPDIBENDAH.card;
			foreach (Card val in card)
			{
				if (val == null)
				{
					continue;
				}
				Segment[] segment = val.segment;
				foreach (Segment val2 in segment)
				{
					if (val2 != null)
					{
						if (val2.leftChar > num)
						{
							LogUtils.LogWarning($"Left character index {val2.leftChar} is out of bounds. Resetting to 1.");
							val2.leftChar = 1;
						}
						if (val2.rightChar > num)
						{
							LogUtils.LogWarning($"Right character index {val2.rightChar} is out of bounds. Resetting to 1.");
							val2.rightChar = 1;
						}
						if (val2.winner > num)
						{
							LogUtils.LogWarning($"Winner index {val2.winner} is out of bounds. Resetting to 1.");
							val2.winner = 1;
						}
					}
				}
			}
			for (int num10 = 1; num10 < aPPDIBENDAH.hiChar.Length; num10++)
			{
				int num11 = aPPDIBENDAH.hiChar[num10];
				if (num11 > num)
				{
					LogUtils.LogWarning($"Hi character index {num11} is out of bounds. Resetting to 1.");
					aPPDIBENDAH.hiChar[num10] = 1;
				}
			}
			Stock[] stockFurniture = aPPDIBENDAH.stockFurniture;
			foreach (Stock val3 in stockFurniture)
			{
				if (val3 != null && val3.owner > num)
				{
					LogUtils.LogWarning($"Furniture owner index {val3.owner} is out of bounds. Resetting to 1.");
					val3.owner = 1;
				}
			}
			stockFurniture = aPPDIBENDAH.stockWeapons;
			foreach (Stock val4 in stockFurniture)
			{
				if (val4 != null && val4.owner > num)
				{
					LogUtils.LogWarning($"Weapon owner index {val4.owner} is out of bounds. Resetting to 1.");
					val4.owner = 1;
				}
			}
			Character[] savedChars = aPPDIBENDAH.savedChars;
			foreach (Character val5 in savedChars)
			{
				if (val5 == null)
				{
					continue;
				}
				for (int num12 = 1; num12 < val5.relationship.Length; num12++)
				{
					if (val5.relationship[num12] > num)
					{
						LogUtils.LogWarning($"Relationship character index {val5.relationship[num12]} is out of bounds. Resetting to 1.");
						val5.relationship[num12] = 1;
					}
				}
				if (val5.grudge > num)
				{
					LogUtils.LogWarning($"Grudge character index {val5.grudge} is out of bounds. Resetting to 1.");
					val5.grudge = 1;
				}
			}
			Roster[] savedFeds = aPPDIBENDAH.savedFeds;
			foreach (Roster val6 in savedFeds)
			{
				if (val6 == null)
				{
					continue;
				}
				if (val6.owner > num)
				{
					LogUtils.LogWarning($"Fed owner index {val6.owner} is out of bounds. Resetting to 1.");
					val6.owner = 1;
				}
				if (val6.booker > num)
				{
					LogUtils.LogWarning($"Fed booker index {val6.booker} is out of bounds. Resetting to 1.");
					val6.booker = 1;
				}
				for (int num13 = 1; num13 < val6.roster.Length; num13++)
				{
					int num14 = val6.roster[num13];
					if (num14 > num)
					{
						LogUtils.LogWarning($"Fed roster index {num14} is out of bounds. Removing.");
						for (int num15 = num13; num15 < val6.roster.Length - 1; num15++)
						{
							val6.roster[num15] = val6.roster[num15 + 1];
						}
						val6.size--;
					}
				}
				for (int num16 = 1; num16 < val6.champ.GetLength(0); num16++)
				{
					for (int num17 = 1; num17 < val6.champ.GetLength(1); num17++)
					{
						int num18 = val6.champ[num16, num17];
						if (num18 > num)
						{
							LogUtils.LogWarning($"Fed champ index {num18} is out of bounds. Resetting to 1.");
							val6.champ[num16, num17] = 1;
						}
					}
				}
			}
			LogUtils.LogInfo("Save data validation complete.");
		}
	}
	public static class TextureUtils
	{
		public static Texture2D ResizeTexture(Texture2D original, int width, int height)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			RenderTexture val = (RenderTexture.active = RenderTexture.GetTemporary(width, height));
			Graphics.Blit((Texture)(object)original, val);
			Texture2D val2 = new Texture2D(width, height);
			val2.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0);
			val2.Apply();
			RenderTexture.active = null;
			RenderTexture.ReleaseTemporary(val);
			return val2;
		}
	}
	public static class TypeUtils
	{
		public static bool IsValid(Type type, string value)
		{
			switch (Type.GetTypeCode(type))
			{
			case TypeCode.Boolean:
				return AnimationParser.ParseBool(value).Item2;
			case TypeCode.Byte:
			{
				byte result8;
				return byte.TryParse(value, out result8);
			}
			case TypeCode.Char:
			{
				char result9;
				return char.TryParse(value, out result9);
			}
			case TypeCode.DateTime:
			{
				DateTime result10;
				return DateTime.TryParse(value, out result10);
			}
			case TypeCode.Decimal:
			{
				decimal result7;
				return decimal.TryParse(value, out result7);
			}
			case TypeCode.Double:
			{
				double result12;
				return double.TryParse(value, out result12);
			}
			case TypeCode.Int16:
			{
				short result11;
				return short.TryParse(value, out result11);
			}
			case TypeCode.Int32:
				if (type.IsEnum)
				{
					bool num = Enum.GetNames(type).Any((string x) => x.Equals(value, StringComparison.OrdinalIgnoreCase));
					int result6;
					bool flag = int.TryParse(value, out result6) && Enum.IsDefined(type, result6);
					return num || flag;
				}
				return AnimationParser.ParseInt(value).Item2;
			case TypeCode.Int64:
			{
				long result5;
				return long.TryParse(value, out result5);
			}
			case TypeCode.SByte:
			{
				sbyte result4;
				return sbyte.TryParse(value, out result4);
			}
			case TypeCode.Single:
				return AnimationParser.ParseFloat(value).Item2;
			case TypeCode.String:
				return true;
			case TypeCode.UInt16:
			{
				ushort result3;
				return ushort.TryParse(value, out result3);
			}
			case TypeCode.UInt32:
			{
				uint result2;
				return uint.TryParse(value, out result2);
			}
			case TypeCode.UInt64:
			{
				ulong result;
				return ulong.TryParse(value, out result);
			}
			case TypeCode.Object:
				return false;
			default:
				return false;
			}
		}
	}
	public static class VectorUtils
	{
		public static Vector3 Round(this Vector3 vector, int decimals)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3((float)Math.Round(vector.x, decimals), (float)Math.Round(vector.y, decimals), (float)Math.Round(vector.z, decimals));
		}
	}
}
namespace WECCL.Updates
{
	internal class GeneratedVersionDiff : VersionDiff
	{
	}
	internal class V155toV156 : VersionDiff
	{
		public V155toV156()
		{
			MaterialCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			FleshCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			ShapeCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			BodyFemaleCountDiff = 0;
			FaceFemaleCountDiff = 0;
			SpecialFootwearCountDiff = 0;
			TransparentHairMaterialCountDiff = 0;
			TransparentHairHairstyleCountDiff = 0;
			KneepadCountDiff = 0;
			MusicCountDiff = 4;
		}
	}
	internal class V158toV159 : VersionDiff
	{
		public V158toV159()
		{
			MaterialCountsDiff = new List<int>
			{
				0, 2, 0, 0, 2, 2, 2, 2, 1, 1,
				0, 1, 1, 0, 3, 3, 1, 0, 0, 0,
				0, 0, 0, 11, 11, 2, 2, 1, 0, 1,
				1, 0, 1, 1, 0, 0, 0, 0, 0, 0
			};
			FleshCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			ShapeCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			BodyFemaleCountDiff = 0;
			FaceFemaleCountDiff = 0;
			SpecialFootwearCountDiff = 0;
			TransparentHairMaterialCountDiff = 0;
			TransparentHairHairstyleCountDiff = 1;
			KneepadCountDiff = 0;
			MusicCountDiff = 0;
		}
	}
	internal class V159toV160 : VersionDiff
	{
		public V159toV160()
		{
			MaterialCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			FleshCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			ShapeCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			BodyFemaleCountDiff = 0;
			FaceFemaleCountDiff = 0;
			SpecialFootwearCountDiff = 0;
			TransparentHairMaterialCountDiff = 0;
			TransparentHairHairstyleCountDiff = 1;
			KneepadCountDiff = 0;
			MusicCountDiff = 0;
		}
	}
	internal class V160toV161 : VersionDiff
	{
		public V160toV161()
		{
			MaterialCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
				0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 5, 5, 0, 0, 0, 0, 1,
				0, 0, 1, 0, 0, 0, 0, 0, 0, 0
			};
			FleshCountsDiff = new List<int>
			{
				0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			ShapeCountsDiff = new List<int>
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0
			};
			BodyFemaleCountDiff = 2;
			FaceFemaleCountDiff = 0;
			SpecialFootwearCountDiff = 0;
			TransparentHairMaterialCountDiff = 0;
			TransparentHairHairstyleCountDiff = 1;
			KneepadCountDiff = 0;
			MusicCountDiff = 0;
		}
	}
	internal class VersionData
	{
		public static void WriteVersionData()
		{
			string contents = JsonConvert.SerializeObject((object)new VanillaCounts());
			if (!Directory.Exists(Locations.Debug.FullName))
			{
				Directory.CreateDirectory(Locations.Debug.FullName);
			}
			File.WriteAllText(Path.Combine(Locations.Debug.FullName, "VanillaCounts.Data.json"), contents);
		}
	}
	internal abstract class VersionDiff
	{
		public int BodyFemaleCountDiff;

		public int FaceFemaleCountDiff;

		public List<int> FleshCountsDiff = new List<int>
		{
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0
		};

		public int KneepadCountDiff;

		public List<int> MaterialCountsDiff = new List<int>
		{
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0
		};

		public int MusicCountDiff;

		public List<int> ShapeCountsDiff = new List<int>
		{
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0
		};

		public int SpecialFootwearCountDiff;

		public int TransparentHairHairstyleCountDiff;

		public int TransparentHairMaterialCountDiff;

		public static VersionDiff GetVersionDiff(VanillaCounts contentMapVanillaCounts)
		{
			GeneratedVersionDiff generatedVersionDiff = new GeneratedVersionDiff();
			generatedVersionDiff.MaterialCountsDiff = new List<int>();
			generatedVersionDiff.FleshCountsDiff = new List<int>();
			generatedVersionDiff.ShapeCountsDiff = new List<int>();
			for (int i = 0; i < 40; i++)
			{
				generatedVersionDiff.MaterialCountsDiff.Add(VanillaCounts.Data.MaterialCounts[i] - contentMapVanillaCounts.MaterialCounts[i]);
				generatedVersionDiff.FleshCountsDiff.Add(VanillaCounts.Data.FleshCounts[i] - contentMapVanillaCounts.FleshCounts[i]);
				generatedVersionDiff.ShapeCountsDiff.Add(VanillaCounts.Data.ShapeCounts[i] - contentMapVanillaCounts.ShapeCounts[i]);
			}
			generatedVersionDiff.BodyFemaleCountDiff = VanillaCounts.Data.BodyFemaleCount - contentMapVanillaCounts.BodyFemaleCount;
			generatedVersionDiff.FaceFemaleCountDiff = VanillaCounts.Data.FaceFemaleCount - contentMapVanillaCounts.FaceFemaleCount;
			generatedVersionDiff.SpecialFootwearCountDiff = VanillaCounts.Data.SpecialFootwearCount - contentMapVanillaCounts.SpecialFootwearCount;
			generatedVersionDiff.TransparentHairMaterialCountDiff = VanillaCounts.Data.TransparentHairMaterialCount - contentMapVanillaCounts.TransparentHairMaterialCount;
			generatedVersionDiff.TransparentHairHairstyleCountDiff = VanillaCounts.Data.TransparentHairHairstyleCount - contentMapVanillaCounts.TransparentHairHairstyleCount;
			generatedVersionDiff.KneepadCountDiff = VanillaCounts.Data.KneepadCount - contentMapVanillaCounts.KneepadCount;
			generatedVersionDiff.MusicCountDiff = VanillaCounts.Data.MusicCount - contentMapVanillaCounts.MusicCount;
			return generatedVersionDiff;
		}
	}
	internal class VersionDiffGroup : VersionDiff
	{
		public VersionDiffGroup(params VersionDiff[] diffs)
		{
			foreach (VersionDiff versionDiff in diffs)
			{
				MaterialCountsDiff = MaterialCountsDiff.Zip(versionDiff.MaterialCountsDiff, (int a, int b) => a + b).ToList();
				FleshCountsDiff = FleshCountsDiff.Zip(versionDiff.FleshCountsDiff, (int a, int b) => a + b).ToList();
				ShapeCountsDiff = ShapeCountsDiff.Zip(versionDiff.ShapeCountsDiff, (int a, int b) => a + b).ToList();
				BodyFemaleCountDiff += versionDiff.BodyFemaleCountDiff;
				FaceFemaleCountDiff += versionDiff.FaceFemaleCountDiff;
				SpecialFootwearCountDiff += versionDiff.SpecialFootwearCountDiff;
				TransparentHairMaterialCountDiff += versionDiff.TransparentHairMaterialCountDiff;
				TransparentHairHairstyleCountDiff += versionDiff.TransparentHairHairstyleCountDiff;
				KneepadCountDiff += versionDiff.KneepadCountDiff;
				MusicCountDiff += versionDiff.MusicCountDiff;
			}
		}
	}
}
namespace WECCL.Saves
{
	internal class BetterCharacterData
	{
		public int? absent;

		public int? age;

		public int? agreement;

		public float? angle;

		public int? anim;

		public float? armMass;

		public float? bodyMass;

		public int? clause;

		public int? contract;

		public BetterCostumeData[] costumeC;

		public int? cuffed;

		public int? dead;

		public int?[] experience = new int?[11];

		public int? fed;

		public int? gender;

		public int? grudge;

		public float? headSize;

		public float? health;

		public int? heel;

		public float? height;

		public int? home;

		public int? id;

		public int? injury;

		public int? injuryTime;

		public float? legMass;

		public int? light;

		public int? location;

		public int?[] moveAttack = new int?[9];

		public int?[] moveBack = new int?[9];

		public int?[] moveCrush = new int?[9];

		public int?[] moveFront = new int?[17];

		public int?[] moveGround = new int?[7];

		public float? muscleMass;

		public string musicC;

		public float? musicSpeed;

		public string name;

		public int? negotiated;

		public int? news;

		public float?[] newStat = new float?[7];

		public int? oldFed;

		public float?[] oldStat = new float?[7];

		public int? player;

		public int? platform;

		public int? possessive;

		public int? promo;

		public int? promoVariable;

		public int? prop;

		public int? pyro;

		public string[] relationshipC = new string[7];

		public int? role;

		public int? salary;

		public int?[] scar = new int?[17];

		public int? seat;

		public float? spirit;

		public int? stance;

		public float?[] stat = new float?[7];

		public int?[] taunt = new int?[4];

		public int? team;

		public string teamName;

		public int? toilet;

		public float? voice;

		public int? worked;

		public int? worth;

		public float? x;

		public float? y;

		public float? z;

		public string VERSION = "1.0.1";

		public static BetterCharacterData FromRegularCharacter(Character character, Character[] allCharacters)
		{
			BetterCharacterData betterCharacterData = JsonConvert.DeserializeObject<BetterCharacterData>(JsonConvert.SerializeObject((object)character));
			betterCharacterData.costumeC = new BetterCostumeData[character.costume.Length];
			for (int i = 0; i < character.costume.Length; i++)
			{
				betterCharacterData.costumeC[i] = BetterCostumeData.FromRegularCostumeData(character.costume[i]);
			}
			betterCharacterData.relationshipC = new string[character.relationship.Length];
			for (int j = 0; j < character.relationship.Length; j++)
			{
				if (character.relationship[j] >= allCharacters.Length)
				{
					betterCharacterData.relationshipC[j] = "0";
				}
				else
				{
					betterCharacterData.relationshipC[j] = ((character.relationship[j] == 0) ? "0" : (allCharacters[character.relationship[j]].name + "@" + character.relationship[j]));
				}
			}
			if (character.music > VanillaCounts.Data.MusicCount)
			{
				int index = character.music - VanillaCounts.Data.MusicCount - 1;
				string text = ContentMappings.ContentMap.MusicNameMap[index];
				betterCharacterData.musicC = "Custom/" + text;
			}
			else
			{
				betterCharacterData.musicC = "Vanilla/" + character.music;
			}
			betterCharacterData.grudge = 0;
			return betterCharacterData;
		}

		public Character ToRegularCharacter(Character[] allCharacters)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Character val = JsonConvert.DeserializeObject<Character>(JsonConvert.SerializeObject((object)this), new JsonSerializerSettings
			{
				NullValueHandling = (NullValueHandling)1
			});
			val.costume = (Costume[])(object)new Costume[costumeC.Length];
			for (int i = 0; i < costumeC.Length; i++)
			{
				if (costumeC[i] == null)
				{
					val.costume[i] = null;
					continue;
				}
				costumeC[i].charID = val.id;
				val.costume[i] = costumeC[i].ToRegularCostume();
			}
			val.relationship = new int[relationshipC.Length];
			for (int j = 0; j < relationshipC.Length; j++)
			{
				if (relationshipC[j] == "0")
				{
					val.relationship[j] = 0;
					continue;
				}
				string[] array = relationshipC[j].Split(new char[1] { '@' });
				string name = array[0];
				try
				{
					val.relationship[j] = allCharacters.Single((Character c) => c != null && c.name != null && c.name == name).id;
				}
				catch (Exception)
				{
					val.relationship[j] = int.Parse(array[1]);
					LogUtils.LogWarning("Failed to find character with name " + name + ", using id instead.");
				}
			}
			if (musicC.StartsWith("Custom/"))
			{
				try
				{
					string item = musicC.Substring(7);
					int num = ContentMappings.ContentMap.MusicNameMap.IndexOf(item);
					val.music = num + VanillaCounts.Data.MusicCount + 1;
				}
				catch (Exception)
				{
					LogUtils.LogWarning("Failed to find music from name " + musicC + ", setting to 0.");
					val.music = 0;
				}
			}
			else
			{
				val.music = int.Parse(musicC.Substring(8));
			}
			val.grudge = 0;
			val.team = 0;
			return val;
		}

		public void MergeIntoCharacter(Character character)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			FieldInfo[] fields = typeof(BetterCharacterData).GetFields();
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!fieldInfo.FieldType.IsArray)
				{
					continue;
				}
				Array array = (Array)fieldInfo.GetValue(this);
				if (array == null)
				{
					continue;
				}
				bool flag = true;
				bool flag2 = true;
				foreach (object item in array)
				{
					if (item != null)
					{
						flag = false;
					}
					else
					{
						flag2 = false;
					}
				}
				if (flag)
				{
					fieldInfo.SetValue(this, null);
				}
				else if (!flag2)
				{
					throw new Exception("It is not possible to merge arrays with both null and non-null elements.");
				}
			}
			JsonConvert.PopulateObject(JsonConvert.SerializeObject((object)this), (object)character, new JsonSerializerSettings
			{
				NullValueHandling = (NullValueHandling)1
			});
			character.grudge = 0;
			character.team = 0;
		}
	}
	internal class BetterCharacterDataFile
	{
		internal string _guid;

		public BetterCharacterData characterData;

		public string findMode;

		public string findName;

		public string overrideMode;

		[JsonIgnore]
		public BetterCharacterData CharacterData
		{
			get
			{
				if (characterData == null)
				{
					return new BetterCharacterData();
				}
				return characterData;
			}
		}

		[JsonIgnore]
		public string OverrideMode
		{
			get
			{
				if (overrideMode == null)
				{
					return "append";
				}
				return overrideMode;
			}
		}

		[JsonIgnore]
		public string FindMode
		{
			get
			{
				if (findMode == null)
				{
					if (!(overrideMode == "append"))
					{
						return "name_then_id";
					}
					return "";
				}
				return findMode;
			}
		}

		[JsonIgnore]
		public string FindName => findName;
	}
	internal class BetterCostumeData
	{
		public float[] b = new float[40];

		public int charID;

		public string[] fleshC = new string[40];

		public float[] g = new float[40];

		public int id;

		public int limb;

		public float[] r = new float[40];

		public string[] shapeC = new string[40];

		public string[] textureC = new string[40];

		public static BetterCostumeData FromRegularCostumeData(Costume costume)
		{
			if (costume == null)
			{
				return null;
			}
			BetterCostumeData betterCostumeData = JsonConvert.DeserializeObject<BetterCostumeData>(JsonConvert.SerializeObject((object)costume));
			for (int i = 0; i < costume.texture.Length; i++)
			{
				if (costume.texture[i] > VanillaCounts.Data.MaterialCounts[i])
				{
					int index = costume.texture[i] - VanillaCounts.Data.MaterialCounts[i] - 1;
					string text = ContentMappings.ContentMap.MaterialNameMap[i][index];
					betterCostumeData.textureC[i] = "Custom/" + text;
				}
				else if (i == 3 && costume.texture[i] < -VanillaCounts.Data.FaceFemaleCount)
				{
					int index2 = -costume.texture[i] - VanillaCounts.Data.FaceFemaleCount - 1;
					string text2 = ContentMappings.ContentMap.FaceFemaleNameMap[index2];
					betterCostumeData.textureC[i] = "Custom/" + text2;
				}
				else if (i == 14 && costume.texture[i] < -VanillaCounts.Data.SpecialFootwearCount)
				{
					int index3 = -costume.texture[i] - VanillaCounts.Data.SpecialFootwearCount - 1;
					string text3 = ContentMappings.ContentMap.SpecialFootwearNameMap[index3];
					betterCostumeData.textureC[i] = "Custom/" + text3;
				}
				else if (i == 15 && costume.texture[i] < -VanillaCounts.Data.SpecialFootwearCount)
				{
					int index4 = -costume.texture[i] - VanillaCounts.Data.SpecialFootwearCount - 1;
					string text4 = ContentMappings.ContentMap.SpecialFootwearNameMap[index4];
					betterCostumeData.textureC[i] = "Custom/" + text4;
				}
				else if (i == 17 && costume.texture[i] < -VanillaCounts.Data.TransparentHairMaterialCount)
				{
					int index5 = -costume.texture[i] - VanillaCounts.Data.TransparentHairMaterialCount - 1;
					string text5 = ContentMappings.ContentMap.TransparentHairMaterialNameMap[index5];
					betterCostumeData.textureC[i] = "Custom/" + text5;
				}
				else if (i == 24 && costume.texture[i] < -VanillaCounts.Data.KneepadCount)
				{
					int index6 = -costume.texture[i] - VanillaCounts.Data.KneepadCount - 1;
					string text6 = ContentMappings.ContentMap.KneepadNameMap[index6];
					betterCostumeData.textureC[i] = "Custom/" + text6;
				}
				else if (i == 25 && costume.texture[i] < -VanillaCounts.Data.KneepadCount)
				{
					int index7 = -costume.texture[i] - VanillaCounts.Data.KneepadCount - 1;
					string text7 = ContentMappings.ContentMap.KneepadNameMap[index7];
					betterCostumeData.textureC[i] = "Custom/" + text7;
				}
				else
				{
					int num = costume.texture[i];
					betterCostumeData.textureC[i] = "Vanilla/" + num;
				}
			}
			for (int j = 0; j < costume.flesh.Length; j++)
			{
				if (j == 17 && costume.flesh[j] == 100)
				{
					int num2 = costume.flesh[j];
					betterCostumeData.fleshC[j] = "Vanilla/" + num2;
				}
				else if (costume.flesh[j] > VanillaCounts.Data.FleshCounts[j])
				{
					int num3 = costume.flesh[j] - VanillaCounts.Data.FleshCounts[j] - 1;
					if (num3 >= ContentMappings.ContentMap.FleshNameMap[j].Count || num3 < 0)
					{
						betterCostumeData.fleshC[j] = "Vanilla/" + costume.flesh[j];
						continue;
					}
					string text8 = ContentMappings.ContentMap.FleshNameMap[j][num3];
					betterCostumeData.fleshC[j] = "Custom/" + text8;
				}
				else if (j == 2 && costume.flesh[j] < -VanillaCounts.Data.BodyFemaleCount)
				{
					int index8 = -costume.flesh[j] - VanillaCounts.Data.BodyFemaleCount - 1;
					string text9 = ContentMappings.ContentMap.BodyFemaleNameMap[index8];
					betterCostumeData.fleshC[j] = "Custom/" + text9;
				}
				else
				{
					int num4 = costume.flesh[j];
					betterCostumeData.fleshC[j] = "Vanilla/" + num4;
				}
			}
			for (int k = 0; k < costume.shape.Length; k++)
			{
				if ((costume.shape[k] > 50 && costume.shape[k] % 10 == 0) || VanillaCounts.Data.ShapeCounts[k] == 0)
				{
					int num5 = costume.shape[k];
					betterCostumeData.shapeC[k] = "Vanilla/" + num5;
				}
				else if (costume.shape[k] > VanillaCounts.Data.ShapeCounts[k])
				{
					int num6 = costume.shape[k] - VanillaCounts.Data.ShapeCounts[k] - 1;
					if (num6 >= ContentMappings.ContentMap.ShapeNameMap[k].Count || num6 < 0)
					{
						betterCostumeData.shapeC[k] = "Vanilla/" + costume.shape[k];
						continue;
					}
					string text10 = ContentMappings.ContentMap.ShapeNameMap[k][num6];
					betterCostumeData.shapeC[k] = "Custom/" + text10;
				}
				else if (k == 17 && costume.shape[k] < -VanillaCounts.Data.TransparentHairHairstyleCount)
				{
					int index9 = -costume.shape[k] - VanillaCounts.Data.TransparentHairHairstyleCount - 1;
					string text11 = ContentMappings.ContentMap.TransparentHairHairstyleNameMap[index9];
					betterCostumeData.shapeC[k] = "Custom/" + text11;
				}
				else
				{
					int num7 = costume.shape[k];
					betterCostumeData.shapeC[k] = "Vanilla/" + num7;
				}
			}
			return betterCostumeData;
		}

		public Costume ToRegularCostume()
		{
			Costume val = JsonConvert.DeserializeObject<Costume>(JsonConvert.SerializeObject((object)this));
			for (int i = 0; i < val.texture.Length; i++)
			{
				if (textureC[i].StartsWith("Custom/"))
				{
					try
					{
						string item = textureC[i].Substring(7);
						int num = ContentMappings.ContentMap.MaterialNameMap[i].IndexOf(item);
						val.texture[i] = num + VanillaCounts.Data.MaterialCounts[i] + 1;
					}
					catch
					{
						LogUtils.LogWarning("Failed to find texture from name " + textureC[i] + ", setting to 0.");
						val.texture[i] = 0;
					}
				}
				else if (i == 3 && textureC[i].StartsWith("Custom/"))
				{
					try
					{
						string item2 = textureC[i].Substring(7);
						int num2 = ContentMappings.ContentMap.KneepadNameMap.IndexOf(item2);
						val.texture[i] = -num2 - VanillaCounts.Data.KneepadCount - 1;
					}
					catch
					{
						LogUtils.LogWarning("Failed to find texture from name " + textureC[i] + ", setting to 0.");
						val.texture[i] = 0;
					}
				}
				else if (i == 14 && textureC[i].StartsWith("Custom/"))
				{
					try
					{
						string item3 = textureC[i].Substring(7);
						int num3 = ContentMappings.ContentMap.SpecialFootwearNameMap.IndexOf(item3);
						val.texture[i] = -num3 - VanillaCounts.Data.SpecialFootwearCount - 1;
					}
					catch
					{
						LogUtils.LogWarning("Failed to find texture from name " + textureC[i] + ", setting to 0.");
						val.texture[i] = 0;
					}
				}
				else if (i == 15 && textureC[i].StartsWith("Custom/"))
				{
					try
					{
						string item4 = textureC[i].Substring(7);
						int num4 = ContentMappings.ContentMap.SpecialFootwearNameMap.IndexOf(item4);
						val.texture[i] = -num4 - VanillaCounts.Data.SpecialFootwearCount - 1;
					}
					catch
					{
						LogUtils.LogWarning("Failed to find texture from name " + textureC[i] + ", setting to 0.");
						val.texture[i] = 0;
					}
				}