Decompiled source of UniversalSurvivorUnlocks v0.1.0

BepInEx/plugins/UniversalSurvivorUnlocks/UniversalSurvivorUnlocks.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HG;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using On.RoR2.UI;
using R2API;
using R2API.ContentManagement;
using RoR2;
using RoR2.Achievements;
using RoR2.ContentManagement;
using RoR2.EntitlementManagement;
using RoR2.ExpansionManagement;
using RoR2.UI;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("UniversalSurvivorUnlocks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b01f3b37167fb4861fa67748bb80335f67d57f20")]
[assembly: AssemblyProduct("UniversalSurvivorUnlocks")]
[assembly: AssemblyTitle("UniversalSurvivorUnlocks")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 UniversalSurvivorUnlocks
{
	public static class ModdedSurvivorRegistry
	{
		private class ModdedSourceInfo
		{
			public string ContentPackIdentifier = "";

			public string AssemblyName = "";
		}

		private static readonly Dictionary<SurvivorDef, ModdedSourceInfo> ModdedSurvivors = new Dictionary<SurvivorDef, ModdedSourceInfo>();

		private static readonly Dictionary<GameObject, ModdedSourceInfo> ModdedBodies = new Dictionary<GameObject, ModdedSourceInfo>();

		public static int Count => ModdedSurvivors.Count;

		public static void Reset(ManualLogSource logger)
		{
			ModdedSurvivors.Clear();
			ModdedBodies.Clear();
			logger.LogInfo((object)"Registro universal de survivors modded reiniciado.");
		}

		public static void RegisterContentPack(ReadOnlyContentPack contentPack, ManualLogSource logger)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			string text = ((ReadOnlyContentPack)(ref contentPack)).identifier;
			if (string.IsNullOrWhiteSpace(text))
			{
				text = "UnknownContentPack";
			}
			if (text.StartsWith("RoR2.", StringComparison.Ordinal) || text.StartsWith("com.danileo.UniversalSurvivorUnlocks", StringComparison.Ordinal))
			{
				return;
			}
			string assemblyName = ResolveAssemblyName(text);
			ModdedSourceInfo moddedSourceInfo = new ModdedSourceInfo
			{
				ContentPackIdentifier = text,
				AssemblyName = assemblyName
			};
			AssetEnumerator<GameObject> enumerator = ((ReadOnlyContentPack)(ref contentPack)).bodyPrefabs.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					GameObject current = enumerator.Current;
					if (!((Object)(object)current == (Object)null) && !ModdedBodies.ContainsKey(current))
					{
						ModdedBodies.Add(current, moddedSourceInfo);
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			AssetEnumerator<SurvivorDef> enumerator2 = ((ReadOnlyContentPack)(ref contentPack)).survivorDefs.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					SurvivorDef current2 = enumerator2.Current;
					if (!((Object)(object)current2 == (Object)null))
					{
						if ((Object)(object)current2.bodyPrefab != (Object)null && !ModdedBodies.ContainsKey(current2.bodyPrefab))
						{
							ModdedBodies.Add(current2.bodyPrefab, moddedSourceInfo);
						}
						RegisterSurvivor(current2, moddedSourceInfo, "PeerContentPack", logger);
					}
				}
			}
			finally
			{
				((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
			}
		}

		public static void ReconcileCatalog(ManualLogSource logger)
		{
			if (SurvivorCatalog.survivorDefs == null)
			{
				return;
			}
			SurvivorDef[] survivorDefs = SurvivorCatalog.survivorDefs;
			foreach (SurvivorDef val in survivorDefs)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.bodyPrefab == (Object)null) && !ModdedSurvivors.ContainsKey(val) && ModdedBodies.TryGetValue(val.bodyPrefab, out var value))
				{
					RegisterSurvivor(val, value, "BodyPrefabFallback", logger);
				}
			}
			logger.LogInfo((object)("Survivors modded registrados tras reconciliar catálogo: " + $"{ModdedSurvivors.Count}"));
		}

		private static void RegisterSurvivor(SurvivorDef survivor, ModdedSourceInfo sourceInfo, string detectionMethod, ManualLogSource logger)
		{
			if (!((Object)(object)survivor == (Object)null) && sourceInfo != null && !ModdedSurvivors.ContainsKey(survivor))
			{
				ModdedSurvivors.Add(survivor, sourceInfo);
				string text = (((Object)(object)survivor.bodyPrefab != (Object)null) ? ((Object)survivor.bodyPrefab).name : "Sin Body");
				logger.LogInfo((object)("Survivor MOD detectado por " + detectionMethod + " | " + survivor.cachedName + " | Body: " + text + " | Pack: " + sourceInfo.ContentPackIdentifier + " | Assembly: " + sourceInfo.AssemblyName));
			}
		}

		private static string ResolveAssemblyName(string identifier)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Enumerator<ManagedReadOnlyContentPack> enumerator = R2APIContentManager.ManagedContentPacks.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						ManagedReadOnlyContentPack current = enumerator.Current;
						if (string.Equals(((ManagedReadOnlyContentPack)(ref current)).Identifier, identifier, StringComparison.Ordinal) && ((ManagedReadOnlyContentPack)(ref current)).TiedAssembly != null)
						{
							return ((ManagedReadOnlyContentPack)(ref current)).TiedAssembly.GetName().Name;
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch
			{
			}
			return identifier;
		}

		public static List<SurvivorDef> GetRegisteredSurvivors()
		{
			return new List<SurvivorDef>(ModdedSurvivors.Keys);
		}

		public static bool TryGetSource(SurvivorDef survivor, out string contentPackIdentifier, out string assemblyName)
		{
			contentPackIdentifier = "";
			assemblyName = "";
			if ((Object)(object)survivor == (Object)null)
			{
				return false;
			}
			if (!ModdedSurvivors.TryGetValue(survivor, out var value))
			{
				return false;
			}
			contentPackIdentifier = value.ContentPackIdentifier;
			assemblyName = value.AssemblyName;
			return true;
		}
	}
	[BepInPlugin("com.danileo.UniversalSurvivorUnlocks", "Universal Survivor Unlocks", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.danileo.UniversalSurvivorUnlocks";

		public const string PluginName = "Universal Survivor Unlocks";

		public const string PluginVersion = "0.1.0";

		public static List<SurvivorInfo> Survivors { get; private set; }

		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Universal Survivor Unlocks 0.1.0 cargado.");
			SurvivorJsonManager.LoadForStartup(((BaseUnityPlugin)this).Logger);
			SurvivorUnlockManager.RegisterConfiguredUnlockables(((BaseUnityPlugin)this).Logger);
			UniversalContentPackProvider.Initialize(((BaseUnityPlugin)this).Logger);
			SurvivorLockedPortraitManager.Initialize(((BaseUnityPlugin)this).Logger);
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnGameLoaded));
		}

		private void OnGameLoaded()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Risk of Rain 2 terminó de cargar.");
			ModdedSurvivorRegistry.ReconcileCatalog(((BaseUnityPlugin)this).Logger);
			Survivors = SurvivorDetector.DetectSurvivors(((BaseUnityPlugin)this).Logger);
			SurvivorJsonManager.Sync(Survivors, ((BaseUnityPlugin)this).Logger);
			SurvivorUnlockManager.ApplyConfiguredUnlockables(Survivors, ((BaseUnityPlugin)this).Logger);
			RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(OnGameLoaded));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Universal Survivor Unlocks terminó su inicialización.");
		}
	}
	public static class SurvivorDetector
	{
		public static List<SurvivorInfo> DetectSurvivors(ManualLogSource logger)
		{
			List<SurvivorInfo> list = new List<SurvivorInfo>();
			if (SurvivorCatalog.survivorDefs == null)
			{
				logger.LogWarning((object)"SurvivorCatalog.survivorDefs todavía no está disponible.");
				return list;
			}
			logger.LogInfo((object)("Survivors encontrados en SurvivorCatalog: " + $"{SurvivorCatalog.survivorDefs.Length}"));
			SurvivorDef[] survivorDefs = SurvivorCatalog.survivorDefs;
			foreach (SurvivorDef val in survivorDefs)
			{
				if (!((Object)(object)val == (Object)null))
				{
					SurvivorInfo survivorInfo = BuildSurvivorInfo(val, logger);
					if (survivorInfo != null)
					{
						list.Add(survivorInfo);
					}
				}
			}
			PrintResults(list, logger);
			return list;
		}

		private static SurvivorInfo BuildSurvivorInfo(SurvivorDef survivor, ManualLogSource logger)
		{
			if ((Object)(object)survivor == (Object)null)
			{
				return null;
			}
			string text = ((!string.IsNullOrWhiteSpace(survivor.cachedName)) ? survivor.cachedName : "UnknownSurvivor");
			string displayName = text;
			if (!string.IsNullOrWhiteSpace(survivor.displayNameToken))
			{
				string text2 = Language.GetString(survivor.displayNameToken);
				if (!string.IsNullOrWhiteSpace(text2))
				{
					displayName = text2;
				}
			}
			string bodyName = "UnknownBody";
			if ((Object)(object)survivor.bodyPrefab != (Object)null)
			{
				bodyName = ((Object)survivor.bodyPrefab).name;
			}
			string unlockableName = "Ninguno";
			UnlockableDef unlockableDef = survivor.unlockableDef;
			bool flag = SurvivorUnlockManager.IsCustomUnlock(unlockableDef);
			bool flag2 = (Object)(object)unlockableDef != (Object)null && !flag;
			if (flag2 && !string.IsNullOrWhiteSpace(unlockableDef.cachedName))
			{
				unlockableName = unlockableDef.cachedName;
			}
			ExpansionDef requiredExpansion = GetRequiredExpansion(survivor);
			string expansionName = "Base Game";
			if ((Object)(object)requiredExpansion != (Object)null)
			{
				expansionName = GetExpansionName(requiredExpansion);
			}
			string contentPackIdentifier;
			string assemblyName;
			bool isModded = ModdedSurvivorRegistry.TryGetSource(survivor, out contentPackIdentifier, out assemblyName);
			SurvivorStatus status = DetermineStatus(survivor, requiredExpansion);
			return new SurvivorInfo
			{
				SurvivorDef = survivor,
				InternalName = text,
				DisplayName = displayName,
				BodyName = bodyName,
				UnlockableName = unlockableName,
				RequiredExpansion = requiredExpansion,
				ExpansionName = expansionName,
				Status = status,
				IsModded = isModded,
				HasOriginalUnlock = flag2,
				ContentPackIdentifier = contentPackIdentifier,
				SourceAssembly = assemblyName
			};
		}

		private static ExpansionDef GetRequiredExpansion(SurvivorDef survivor)
		{
			if ((Object)(object)survivor == (Object)null || (Object)(object)survivor.bodyPrefab == (Object)null)
			{
				return null;
			}
			ExpansionRequirementComponent component = survivor.bodyPrefab.GetComponent<ExpansionRequirementComponent>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			return component.requiredExpansion;
		}

		private static string GetExpansionName(ExpansionDef expansion)
		{
			if ((Object)(object)expansion == (Object)null)
			{
				return "Base Game";
			}
			if (!string.IsNullOrWhiteSpace(expansion.nameToken))
			{
				string text = Language.GetString(expansion.nameToken);
				if (!string.IsNullOrWhiteSpace(text))
				{
					return text;
				}
			}
			if (!string.IsNullOrWhiteSpace(((Object)expansion).name))
			{
				return ((Object)expansion).name;
			}
			return "Unknown Expansion";
		}

		private static bool OwnsExpansion(ExpansionDef expansion)
		{
			if ((Object)(object)expansion == (Object)null)
			{
				return true;
			}
			if ((Object)(object)expansion.requiredEntitlement == (Object)null)
			{
				return true;
			}
			if (EntitlementManager.localUserEntitlementTracker == null)
			{
				return false;
			}
			return ((BaseUserEntitlementTracker<LocalUser>)(object)EntitlementManager.localUserEntitlementTracker).AnyUserHasEntitlement(expansion.requiredEntitlement);
		}

		private static SurvivorStatus DetermineStatus(SurvivorDef survivor, ExpansionDef requiredExpansion)
		{
			if (survivor.hidden)
			{
				return SurvivorStatus.Hidden;
			}
			if ((Object)(object)survivor.bodyPrefab == (Object)null)
			{
				return SurvivorStatus.NotSelectable;
			}
			if ((Object)(object)requiredExpansion != (Object)null && !OwnsExpansion(requiredExpansion))
			{
				return SurvivorStatus.DlcNotOwned;
			}
			return SurvivorStatus.Available;
		}

		private static void PrintResults(List<SurvivorInfo> survivors, ManualLogSource logger)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			logger.LogInfo((object)"===============================================");
			logger.LogInfo((object)"========== UNIVERSAL SURVIVOR DETECTOR ==========");
			foreach (SurvivorInfo survivor in survivors)
			{
				switch (survivor.Status)
				{
				case SurvivorStatus.Available:
					num++;
					break;
				case SurvivorStatus.DlcNotOwned:
					num2++;
					break;
				case SurvivorStatus.Hidden:
					num3++;
					break;
				case SurvivorStatus.NotSelectable:
					num4++;
					break;
				}
				if (survivor.IsModded)
				{
					num5++;
				}
				logger.LogInfo((object)(survivor.DisplayName + " | Internal: " + survivor.InternalName + " | Body: " + survivor.BodyName + " | " + $"Estado: {survivor.Status} | " + "Expansion: " + survivor.ExpansionName + " | Unlock: " + survivor.UnlockableName + " | Modded: " + (survivor.IsModded ? "SI" : "NO")));
			}
			logger.LogInfo((object)"-----------------------------------------------");
			logger.LogInfo((object)$"Disponibles: {num}");
			logger.LogInfo((object)$"DLC no disponible: {num2}");
			logger.LogInfo((object)$"Ocultos: {num3}");
			logger.LogInfo((object)$"No seleccionables: {num4}");
			logger.LogInfo((object)$"Modded detectados: {num5}");
			logger.LogInfo((object)"===============================================");
			logger.LogInfo((object)"========== SURVIVORS MODDED ==========");
			foreach (SurvivorInfo survivor2 in survivors)
			{
				if (survivor2.IsModded)
				{
					logger.LogInfo((object)(survivor2.DisplayName + " | Internal: " + survivor2.InternalName + " | Body: " + survivor2.BodyName + " | Pack: " + survivor2.ContentPackIdentifier + " | Assembly: " + survivor2.SourceAssembly + " | Unlock propio: " + (survivor2.HasOriginalUnlock ? "SI" : "NO") + " | Unlock: " + survivor2.UnlockableName));
				}
			}
			if (num5 == 0)
			{
				logger.LogInfo((object)"No se detectaron survivors pertenecientes a ContentPacks de mods.");
			}
			logger.LogInfo((object)"===============================================");
		}
	}
	public enum SurvivorStatus
	{
		Available,
		DlcNotOwned,
		Hidden,
		NotSelectable
	}
	public class SurvivorInfo
	{
		public SurvivorDef SurvivorDef { get; set; }

		public string InternalName { get; set; }

		public string DisplayName { get; set; }

		public string BodyName { get; set; }

		public string UnlockableName { get; set; }

		public ExpansionDef RequiredExpansion { get; set; }

		public string ExpansionName { get; set; }

		public SurvivorStatus Status { get; set; }

		public bool IsModded { get; set; }

		public bool HasOriginalUnlock { get; set; }

		public string ContentPackIdentifier { get; set; }

		public string SourceAssembly { get; set; }
	}
	public static class SurvivorJsonManager
	{
		public static SurvivorJsonFile CurrentConfig { get; private set; } = new SurvivorJsonFile();

		private static string ConfigDirectory => Path.Combine(Paths.ConfigPath, "UniversalSurvivorUnlocks");

		private static string JsonPath => Path.Combine(ConfigDirectory, "Survivors.json");

		private static string BackupPath => Path.Combine(ConfigDirectory, "Survivors.backup.json");

		public static void LoadForStartup(ManualLogSource logger)
		{
			Directory.CreateDirectory(ConfigDirectory);
			if (TryLoadExisting(logger, out var file))
			{
				CurrentConfig = file;
				logger.LogInfo((object)("Configuración inicial cargada. Disponibles guardados: " + $"{CurrentConfig.AvailableSurvivors.Count}"));
			}
		}

		public static SurvivorJsonEntry GetEntryAnywhere(string bodyName)
		{
			if (string.IsNullOrWhiteSpace(bodyName) || CurrentConfig == null)
			{
				return null;
			}
			if (CurrentConfig.AvailableSurvivors == null)
			{
				CurrentConfig.AvailableSurvivors = new Dictionary<string, SurvivorJsonEntry>();
			}
			if (CurrentConfig.UnavailableSurvivors == null)
			{
				CurrentConfig.UnavailableSurvivors = new Dictionary<string, SurvivorJsonEntry>();
			}
			if (CurrentConfig.AvailableSurvivors.TryGetValue(bodyName, out var value))
			{
				return value;
			}
			if (CurrentConfig.UnavailableSurvivors.TryGetValue(bodyName, out var value2))
			{
				return value2;
			}
			return null;
		}

		public static SurvivorJsonEntry CreateAutomaticEntry(SurvivorDef survivor, string contentPackIdentifier, string sourceAssembly, ManualLogSource logger)
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			if ((Object)(object)survivor == (Object)null || (Object)(object)survivor.bodyPrefab == (Object)null)
			{
				return null;
			}
			string name = ((Object)survivor.bodyPrefab).name;
			SurvivorJsonEntry entryAnywhere = GetEntryAnywhere(name);
			if (entryAnywhere != null)
			{
				return entryAnywhere;
			}
			string text = name;
			try
			{
				if (!string.IsNullOrWhiteSpace(survivor.displayNameToken))
				{
					string text2 = Language.GetString(survivor.displayNameToken);
					if (!string.IsNullOrWhiteSpace(text2) && !string.Equals(text2, survivor.displayNameToken, StringComparison.Ordinal))
					{
						text = text2;
					}
				}
			}
			catch
			{
			}
			if (text == name && name.EndsWith("Body", StringComparison.Ordinal))
			{
				text = name.Substring(0, name.Length - 4);
			}
			SurvivorJsonEntry survivorJsonEntry = new SurvivorJsonEntry
			{
				DisplayName = text,
				InternalName = ((!string.IsNullOrWhiteSpace(survivor.cachedName)) ? survivor.cachedName : name),
				BodyName = name,
				Source = ((!string.IsNullOrWhiteSpace(contentPackIdentifier)) ? contentPackIdentifier : ((!string.IsNullOrWhiteSpace(sourceAssembly)) ? sourceAssembly : "Modded")),
				OriginalUnlock = "Ninguno",
				Available = true,
				Status = "Available",
				Reason = "",
				Challenge = new SurvivorChallengeJson
				{
					Enabled = true,
					Name = "Desafío de desbloqueo",
					Type = "KillEnemies",
					Parameters = new JObject { ["amount"] = JToken.op_Implicit(100) }
				}
			};
			if (CurrentConfig == null)
			{
				CurrentConfig = new SurvivorJsonFile();
			}
			if (CurrentConfig.AvailableSurvivors == null)
			{
				CurrentConfig.AvailableSurvivors = new Dictionary<string, SurvivorJsonEntry>();
			}
			if (CurrentConfig.UnavailableSurvivors == null)
			{
				CurrentConfig.UnavailableSurvivors = new Dictionary<string, SurvivorJsonEntry>();
			}
			CurrentConfig.UnavailableSurvivors.Remove(name);
			CurrentConfig.AvailableSurvivors[name] = survivorJsonEntry;
			logger.LogInfo((object)("Configuración automática creada en memoria | Survivor: " + text + " | Body: " + name + " | Pack: " + survivorJsonEntry.Source + " | Challenge: KillEnemies 100"));
			return survivorJsonEntry;
		}

		public static void Sync(List<SurvivorInfo> detectedSurvivors, ManualLogSource logger)
		{
			Directory.CreateDirectory(ConfigDirectory);
			SurvivorJsonFile survivorJsonFile = CurrentConfig ?? new SurvivorJsonFile();
			if (survivorJsonFile.AvailableSurvivors == null)
			{
				survivorJsonFile.AvailableSurvivors = new Dictionary<string, SurvivorJsonEntry>();
			}
			if (survivorJsonFile.UnavailableSurvivors == null)
			{
				survivorJsonFile.UnavailableSurvivors = new Dictionary<string, SurvivorJsonEntry>();
			}
			Dictionary<string, SurvivorJsonEntry> dictionary = CombineExistingRecords(survivorJsonFile);
			SurvivorJsonFile survivorJsonFile2 = new SurvivorJsonFile();
			HashSet<string> hashSet = new HashSet<string>();
			HashSet<string> hashSet2 = new HashSet<string>();
			foreach (SurvivorInfo detectedSurvivor in detectedSurvivors)
			{
				if (detectedSurvivor == null)
				{
					continue;
				}
				string bodyName = detectedSurvivor.BodyName;
				if (string.IsNullOrWhiteSpace(bodyName) || bodyName == "Sin Body" || bodyName == "UnknownBody")
				{
					continue;
				}
				if (!detectedSurvivor.IsModded)
				{
					hashSet2.Add(bodyName);
					continue;
				}
				hashSet.Add(bodyName);
				if (detectedSurvivor.Status == SurvivorStatus.Hidden || detectedSurvivor.Status == SurvivorStatus.NotSelectable)
				{
					continue;
				}
				if (!dictionary.TryGetValue(bodyName, out var value))
				{
					value = new SurvivorJsonEntry();
				}
				value.DisplayName = detectedSurvivor.DisplayName;
				value.InternalName = detectedSurvivor.InternalName;
				value.BodyName = detectedSurvivor.BodyName;
				if (!string.IsNullOrWhiteSpace(detectedSurvivor.ContentPackIdentifier))
				{
					value.Source = detectedSurvivor.ContentPackIdentifier;
				}
				else if (!string.IsNullOrWhiteSpace(detectedSurvivor.SourceAssembly))
				{
					value.Source = detectedSurvivor.SourceAssembly;
				}
				else
				{
					value.Source = "Modded";
				}
				value.OriginalUnlock = detectedSurvivor.UnlockableName;
				if (value.Challenge == null)
				{
					value.Challenge = new SurvivorChallengeJson();
				}
				if (detectedSurvivor.Status == SurvivorStatus.Available)
				{
					value.Available = true;
					value.Status = "Available";
					value.Reason = "";
					survivorJsonFile2.AvailableSurvivors[bodyName] = value;
					continue;
				}
				value.Available = false;
				value.Status = detectedSurvivor.Status.ToString();
				if (detectedSurvivor.Status == SurvivorStatus.DlcNotOwned)
				{
					value.Reason = "Requires DLC: " + detectedSurvivor.ExpansionName;
				}
				else
				{
					value.Reason = "Survivor actualmente no disponible.";
				}
				survivorJsonFile2.UnavailableSurvivors[bodyName] = value;
			}
			foreach (KeyValuePair<string, SurvivorJsonEntry> item in dictionary)
			{
				string key = item.Key;
				if (hashSet2.Contains(key) || hashSet.Contains(key))
				{
					continue;
				}
				SurvivorJsonEntry value2 = item.Value;
				if (value2 != null)
				{
					value2.Available = false;
					value2.Status = "MissingContent";
					value2.Reason = "Survivor mod no detectado. El mod puede estar desactivado o desinstalado.";
					if (value2.Challenge == null)
					{
						value2.Challenge = new SurvivorChallengeJson();
					}
					survivorJsonFile2.UnavailableSurvivors[key] = value2;
				}
			}
			SortEntries(survivorJsonFile2);
			CurrentConfig = survivorJsonFile2;
			Save(survivorJsonFile2, logger);
			logger.LogInfo((object)("JSON modded sincronizado | Disponibles: " + $"{survivorJsonFile2.AvailableSurvivors.Count} | " + "No disponibles: " + $"{survivorJsonFile2.UnavailableSurvivors.Count}"));
		}

		private static bool TryLoadExisting(ManualLogSource logger, out SurvivorJsonFile file)
		{
			file = new SurvivorJsonFile();
			if (!File.Exists(JsonPath))
			{
				return true;
			}
			try
			{
				SurvivorJsonFile survivorJsonFile = JsonConvert.DeserializeObject<SurvivorJsonFile>(File.ReadAllText(JsonPath, Encoding.UTF8));
				if (survivorJsonFile != null)
				{
					file = survivorJsonFile;
				}
				if (file.AvailableSurvivors == null)
				{
					file.AvailableSurvivors = new Dictionary<string, SurvivorJsonEntry>();
				}
				if (file.UnavailableSurvivors == null)
				{
					file.UnavailableSurvivors = new Dictionary<string, SurvivorJsonEntry>();
				}
				return true;
			}
			catch (Exception ex)
			{
				logger.LogError((object)"Survivors.json contiene un error y no será sobrescrito.");
				logger.LogError((object)ex.Message);
				return false;
			}
		}

		private static Dictionary<string, SurvivorJsonEntry> CombineExistingRecords(SurvivorJsonFile file)
		{
			Dictionary<string, SurvivorJsonEntry> dictionary = new Dictionary<string, SurvivorJsonEntry>();
			foreach (KeyValuePair<string, SurvivorJsonEntry> availableSurvivor in file.AvailableSurvivors)
			{
				dictionary[availableSurvivor.Key] = availableSurvivor.Value;
			}
			foreach (KeyValuePair<string, SurvivorJsonEntry> unavailableSurvivor in file.UnavailableSurvivors)
			{
				dictionary[unavailableSurvivor.Key] = unavailableSurvivor.Value;
			}
			return dictionary;
		}

		private static void SortEntries(SurvivorJsonFile file)
		{
			file.AvailableSurvivors = file.AvailableSurvivors.OrderBy((KeyValuePair<string, SurvivorJsonEntry> pair) => pair.Value.DisplayName).ToDictionary((KeyValuePair<string, SurvivorJsonEntry> pair) => pair.Key, (KeyValuePair<string, SurvivorJsonEntry> pair) => pair.Value);
			file.UnavailableSurvivors = file.UnavailableSurvivors.OrderBy((KeyValuePair<string, SurvivorJsonEntry> pair) => pair.Value.DisplayName).ToDictionary((KeyValuePair<string, SurvivorJsonEntry> pair) => pair.Key, (KeyValuePair<string, SurvivorJsonEntry> pair) => pair.Value);
		}

		private static void Save(SurvivorJsonFile file, ManualLogSource logger)
		{
			try
			{
				if (File.Exists(JsonPath))
				{
					File.Copy(JsonPath, BackupPath, overwrite: true);
				}
				string contents = JsonConvert.SerializeObject((object)file, (Formatting)1);
				File.WriteAllText(JsonPath, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				logger.LogInfo((object)"Survivors.json actualizado correctamente.");
				logger.LogInfo((object)("Disponibles en JSON: " + $"{file.AvailableSurvivors.Count}"));
				logger.LogInfo((object)("No disponibles en JSON: " + $"{file.UnavailableSurvivors.Count}"));
				logger.LogInfo((object)("Ruta: " + JsonPath));
			}
			catch (Exception ex)
			{
				logger.LogError((object)"No se pudo guardar Survivors.json.");
				logger.LogError((object)ex.Message);
			}
		}
	}
	public class SurvivorJsonFile
	{
		[JsonProperty("_guide", Order = 1)]
		public SurvivorJsonGuide Guide { get; set; } = new SurvivorJsonGuide();

		[JsonProperty("schemaVersion", Order = 2)]
		public int SchemaVersion { get; set; } = 1;

		[JsonProperty("_availableTitle", Order = 3)]
		public string AvailableTitle { get; set; } = "==================== PERSONAJES HABILITADOS ====================";

		[JsonProperty("_availableMessage", Order = 4)]
		public string AvailableMessage { get; set; } = "Estos personajes están disponibles actualmente y pueden recibir una misión de desbloqueo personalizada.";

		[JsonProperty("availableSurvivors", Order = 5)]
		public Dictionary<string, SurvivorJsonEntry> AvailableSurvivors { get; set; } = new Dictionary<string, SurvivorJsonEntry>();

		[JsonProperty("_unavailableTitle", Order = 6)]
		public string UnavailableTitle { get; set; } = "================== PERSONAJES NO HABILITADOS ==================";

		[JsonProperty("_unavailableMessage", Order = 7)]
		public string UnavailableMessage { get; set; } = "Estos personajes no están disponibles actualmente. Su configuración se conserva, pero sus misiones no pueden activarse hasta que vuelva a estar disponible su DLC, mod o dependencia.";

		[JsonProperty("unavailableSurvivors", Order = 8)]
		public Dictionary<string, SurvivorJsonEntry> UnavailableSurvivors { get; set; } = new Dictionary<string, SurvivorJsonEntry>();
	}
	public class SurvivorJsonGuide
	{
		[JsonProperty("title", Order = 1)]
		public string Title { get; set; } = "================ UNIVERSAL SURVIVOR UNLOCKS ================";

		[JsonProperty("instructions", Order = 2)]
		public List<string> Instructions { get; set; } = new List<string> { "Las misiones personalizadas se configurarán dentro del bloque challenge de cada personaje habilitado.", "enabled = false mantiene desactivada la misión personalizada.", "enabled = true permitirá utilizar la misión configurada.", "type indicará el tipo de misión.", "parameters contendrá las condiciones específicas de esa misión.", "Los tipos de misión disponibles se implementarán progresivamente durante el desarrollo del mod.", "No es necesario modificar displayName, internalName, bodyName, source, status ni originalUnlock." };

		[JsonProperty("exampleChallenge", Order = 3)]
		public SurvivorChallengeJson ExampleChallenge { get; set; } = new SurvivorChallengeJson
		{
			Enabled = true,
			Type = "KillEnemies",
			Parameters = new JObject { ["amount"] = JToken.op_Implicit(100) }
		};
	}
	public class SurvivorJsonEntry
	{
		[JsonProperty("displayName", Order = 1)]
		public string DisplayName { get; set; } = "";

		[JsonProperty("internalName", Order = 2)]
		public string InternalName { get; set; } = "";

		[JsonProperty("bodyName", Order = 3)]
		public string BodyName { get; set; } = "";

		[JsonProperty("source", Order = 4)]
		public string Source { get; set; } = "";

		[JsonProperty("originalUnlock", Order = 5)]
		public string OriginalUnlock { get; set; } = "";

		[JsonProperty("available", Order = 6)]
		public bool Available { get; set; }

		[JsonProperty("status", Order = 7)]
		public string Status { get; set; } = "";

		[JsonProperty("reason", Order = 8)]
		public string Reason { get; set; } = "";

		[JsonProperty("challenge", Order = 9)]
		public SurvivorChallengeJson Challenge { get; set; } = new SurvivorChallengeJson();

		[JsonExtensionData]
		public IDictionary<string, JToken> ExtraData { get; set; } = new Dictionary<string, JToken>();
	}
	public class SurvivorChallengeJson
	{
		[JsonProperty("enabled", Order = 1)]
		public bool Enabled { get; set; }

		[JsonProperty("name", Order = 2)]
		public string Name { get; set; } = "";

		[JsonProperty("type", Order = 3)]
		public string Type { get; set; } = "Original";

		[JsonProperty("parameters", Order = 4)]
		public JObject Parameters { get; set; } = new JObject();

		[JsonExtensionData]
		public IDictionary<string, JToken> ExtraData { get; set; } = new Dictionary<string, JToken>();
	}
	public static class SurvivorLockedPortraitManager
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_Rebuild <0>__SurvivorIconController_Rebuild;

			public static hook_UpdateAvailability <1>__SurvivorIconController_UpdateAvailability;
		}

		private static bool initialized;

		private static ManualLogSource Logger;

		private static readonly Dictionary<SurvivorIconController, Color> OriginalColors = new Dictionary<SurvivorIconController, Color>();

		public static void Initialize(ManualLogSource logger)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			if (!initialized)
			{
				initialized = true;
				Logger = logger;
				object obj = <>O.<0>__SurvivorIconController_Rebuild;
				if (obj == null)
				{
					hook_Rebuild val = SurvivorIconController_Rebuild;
					<>O.<0>__SurvivorIconController_Rebuild = val;
					obj = (object)val;
				}
				SurvivorIconController.Rebuild += (hook_Rebuild)obj;
				object obj2 = <>O.<1>__SurvivorIconController_UpdateAvailability;
				if (obj2 == null)
				{
					hook_UpdateAvailability val2 = SurvivorIconController_UpdateAvailability;
					<>O.<1>__SurvivorIconController_UpdateAvailability = val2;
					obj2 = (object)val2;
				}
				SurvivorIconController.UpdateAvailability += (hook_UpdateAvailability)obj2;
				Logger.LogInfo((object)"SurvivorLockedPortraitManager inicializado.");
			}
		}

		private static void SurvivorIconController_Rebuild(orig_Rebuild orig, SurvivorIconController self)
		{
			orig.Invoke(self);
			RefreshPortrait(self);
		}

		private static void SurvivorIconController_UpdateAvailability(orig_UpdateAvailability orig, SurvivorIconController self)
		{
			orig.Invoke(self);
			RefreshPortrait(self);
		}

		private static void RefreshPortrait(SurvivorIconController self)
		{
			if (!((Object)(object)self == (Object)null) && !((Object)(object)self.survivorDef == (Object)null) && !((Object)(object)self.survivorIcon == (Object)null))
			{
				if (!SurvivorUnlockManager.IsCustomUnlock(self.survivorDef.unlockableDef))
				{
					RestoreColor(self);
				}
				else if (self.survivorIsUnlocked)
				{
					RestoreColor(self);
				}
				else
				{
					ApplyLockedColor(self);
				}
			}
		}

		private static void ApplyLockedColor(SurvivorIconController self)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (!OriginalColors.ContainsKey(self))
			{
				OriginalColors[self] = ((Graphic)self.survivorIcon).color;
				Logger.LogInfo((object)("Silueta bloqueada aplicada: " + self.survivorDef.cachedName));
			}
			Color val = OriginalColors[self];
			((Graphic)self.survivorIcon).color = new Color(0f, 0f, 0f, val.a);
		}

		private static void RestoreColor(SurvivorIconController self)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)self == (Object)null) && !((Object)(object)self.survivorIcon == (Object)null) && OriginalColors.TryGetValue(self, out var value))
			{
				((Graphic)self.survivorIcon).color = value;
				OriginalColors.Remove(self);
				Logger.LogInfo((object)("Color restaurado: " + self.survivorDef.cachedName));
			}
		}
	}
	public static class SurvivorLockUiManager
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_UpdateAvailability <0>__SurvivorIconController_UpdateAvailability;

			public static hook_Rebuild <1>__SurvivorIconController_Rebuild;
		}

		private static ManualLogSource Logger;

		private static bool initialized;

		private const string LockedOverlayName = "USU_LockedOverlay";

		public static void Initialize(ManualLogSource logger)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			if (!initialized)
			{
				initialized = true;
				Logger = logger;
				object obj = <>O.<0>__SurvivorIconController_UpdateAvailability;
				if (obj == null)
				{
					hook_UpdateAvailability val = SurvivorIconController_UpdateAvailability;
					<>O.<0>__SurvivorIconController_UpdateAvailability = val;
					obj = (object)val;
				}
				SurvivorIconController.UpdateAvailability += (hook_UpdateAvailability)obj;
				object obj2 = <>O.<1>__SurvivorIconController_Rebuild;
				if (obj2 == null)
				{
					hook_Rebuild val2 = SurvivorIconController_Rebuild;
					<>O.<1>__SurvivorIconController_Rebuild = val2;
					obj2 = (object)val2;
				}
				SurvivorIconController.Rebuild += (hook_Rebuild)obj2;
				Logger.LogInfo((object)"SurvivorLockUiManager inicializado.");
			}
		}

		private static void SurvivorIconController_UpdateAvailability(orig_UpdateAvailability orig, SurvivorIconController self)
		{
			orig.Invoke(self);
			if (ShouldCustomLock(self.survivorDef))
			{
				self.survivorIsUnlocked = false;
			}
		}

		private static void SurvivorIconController_Rebuild(orig_Rebuild orig, SurvivorIconController self)
		{
			orig.Invoke(self);
			if (!ShouldCustomLock(self.survivorDef))
			{
				RemoveLockedOverlay(self);
				return;
			}
			self.survivorIsUnlocked = false;
			ApplyLockedUi(self);
		}

		private static bool ShouldCustomLock(SurvivorDef survivor)
		{
			if ((Object)(object)survivor == (Object)null)
			{
				return false;
			}
			if ((Object)(object)survivor.bodyPrefab == (Object)null)
			{
				return false;
			}
			SurvivorJsonFile currentConfig = SurvivorJsonManager.CurrentConfig;
			if (currentConfig == null)
			{
				return false;
			}
			if (currentConfig.AvailableSurvivors == null)
			{
				return false;
			}
			string name = ((Object)survivor.bodyPrefab).name;
			if (!currentConfig.AvailableSurvivors.TryGetValue(name, out var value))
			{
				return false;
			}
			if (value == null)
			{
				return false;
			}
			if (value.Challenge == null)
			{
				return false;
			}
			if (!value.Challenge.Enabled)
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(value.Challenge.Type) || value.Challenge.Type == "Original")
			{
				return false;
			}
			return true;
		}

		private static void ApplyLockedUi(SurvivorIconController self)
		{
			if (!((Object)(object)self == (Object)null) && !((Object)(object)self.hgButton == (Object)null))
			{
				SurvivorJsonEntry entry = GetEntry(self.survivorDef);
				if (entry != null)
				{
					((MPButton)self.hgButton).disableGamepadClick = true;
					((MPButton)self.hgButton).disablePointerClick = true;
					ApplyPortraitDarkening(self);
					CreateLockedOverlay(self);
					ApplyTooltip(self, entry);
					Logger.LogInfo((object)("Bloqueo personalizado aplicado: " + entry.DisplayName + " | " + entry.BodyName));
				}
			}
		}

		private static void ApplyPortraitDarkening(SurvivorIconController self)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)self.survivorDef == (Object)null || (Object)(object)self.survivorDef.bodyPrefab == (Object)null)
			{
				return;
			}
			CharacterBody component = self.survivorDef.bodyPrefab.GetComponent<CharacterBody>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Texture portraitIcon = component.portraitIcon;
			if ((Object)(object)portraitIcon == (Object)null)
			{
				return;
			}
			RawImage[] componentsInChildren = ((Component)self.hgButton).GetComponentsInChildren<RawImage>(true);
			foreach (RawImage val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.texture != (Object)(object)portraitIcon))
				{
					Color color = ((Graphic)val).color;
					((Graphic)val).color = new Color(color.r * 0.25f, color.g * 0.25f, color.b * 0.25f, color.a);
				}
			}
		}

		private static void CreateLockedOverlay(SurvivorIconController self)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)self.hgButton).transform;
			Transform val = transform.Find("USU_LockedOverlay");
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(true);
				return;
			}
			GameObject val2 = new GameObject("USU_LockedOverlay", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val2.transform.SetParent(transform, false);
			RectTransform component = val2.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			Image component2 = val2.GetComponent<Image>();
			((Graphic)component2).color = new Color(0f, 0f, 0f, 0.55f);
			((Graphic)component2).raycastTarget = false;
			val2.transform.SetAsLastSibling();
		}

		private static void RemoveLockedOverlay(SurvivorIconController self)
		{
			if (!((Object)(object)self == (Object)null) && !((Object)(object)self.hgButton == (Object)null))
			{
				Transform val = ((Component)self.hgButton).transform.Find("USU_LockedOverlay");
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		private static void ApplyTooltip(SurvivorIconController self, SurvivorJsonEntry entry)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			TooltipProvider val = ((Component)self.hgButton).GetComponent<TooltipProvider>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)self.hgButton).gameObject.AddComponent<TooltipProvider>();
			}
			((Behaviour)val).enabled = true;
			val.AllowTooltipOnNavigationSelect = true;
			TooltipContent content = new TooltipContent
			{
				overrideTitleText = entry.DisplayName + " - BLOQUEADO",
				overrideBodyText = BuildUnlockDescription(entry),
				titleColor = Color.gray,
				bodyColor = Color.white
			};
			val.SetContent(content);
		}

		private static SurvivorJsonEntry GetEntry(SurvivorDef survivor)
		{
			if ((Object)(object)survivor == (Object)null || (Object)(object)survivor.bodyPrefab == (Object)null)
			{
				return null;
			}
			if (SurvivorJsonManager.CurrentConfig == null)
			{
				return null;
			}
			if (SurvivorJsonManager.CurrentConfig.AvailableSurvivors == null)
			{
				return null;
			}
			string name = ((Object)survivor.bodyPrefab).name;
			SurvivorJsonManager.CurrentConfig.AvailableSurvivors.TryGetValue(name, out var value);
			return value;
		}

		private static string BuildUnlockDescription(SurvivorJsonEntry entry)
		{
			if (entry == null || entry.Challenge == null)
			{
				return "Cómo desbloquear:\nCompleta su desafío.";
			}
			string type = entry.Challenge.Type;
			JObject parameters = entry.Challenge.Parameters;
			switch (type)
			{
			case "KillEnemies":
			{
				int num4 = GetInt(parameters, "amount", 1);
				return "Cómo desbloquear:\n" + $"Derrota {num4} enemigos.";
			}
			case "KillBoss":
			{
				int num3 = GetInt(parameters, "amount", 1);
				return "Cómo desbloquear:\n" + $"Derrota {num3} jefes.";
			}
			case "ReachLevel":
			{
				int num2 = GetInt(parameters, "level", 1);
				return "Cómo desbloquear:\n" + $"Alcanza el nivel {num2}.";
			}
			case "ReachStage":
			{
				int num = GetInt(parameters, "stage", 1);
				return "Cómo desbloquear:\n" + $"Alcanza la fase {num}.";
			}
			default:
				return "Cómo desbloquear:\nCompleta la misión '" + type + "'.";
			}
		}

		private static int GetInt(JObject parameters, string key, int defaultValue)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if (parameters == null)
			{
				return defaultValue;
			}
			JToken val = parameters[key];
			if (val == null)
			{
				return defaultValue;
			}
			if ((int)val.Type != 6)
			{
				return defaultValue;
			}
			return Extensions.Value<int>((IEnumerable<JToken>)val);
		}
	}
	public static class SurvivorUnlockManager
	{
		private static readonly Dictionary<string, UnlockableDef> CustomUnlockables = new Dictionary<string, UnlockableDef>();

		private static readonly Dictionary<string, AchievementDef> CustomAchievements = new Dictionary<string, AchievementDef>();

		private static readonly Dictionary<string, Sprite> CustomAchievementIcons = new Dictionary<string, Sprite>();

		private static readonly Dictionary<SurvivorDef, UnlockableDef> OriginalUnlockables = new Dictionary<SurvivorDef, UnlockableDef>();

		public static bool IsCustomUnlock(UnlockableDef unlockableDef)
		{
			if ((Object)(object)unlockableDef == (Object)null)
			{
				return false;
			}
			if (unlockableDef.cachedName != null)
			{
				return unlockableDef.cachedName.StartsWith("UniversalSurvivorUnlocks.", StringComparison.Ordinal);
			}
			return false;
		}

		public static bool RequiresCustomUnlock(SurvivorJsonEntry entry)
		{
			if (entry == null || entry.Challenge == null)
			{
				return false;
			}
			if (!entry.Challenge.Enabled)
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(entry.Challenge.Type))
			{
				return false;
			}
			return !string.Equals(entry.Challenge.Type, "Original", StringComparison.OrdinalIgnoreCase);
		}

		public static void RegisterConfiguredUnlockables(ManualLogSource logger)
		{
			SurvivorJsonFile currentConfig = SurvivorJsonManager.CurrentConfig;
			if (currentConfig != null)
			{
				RegisterEntries(currentConfig.AvailableSurvivors, logger);
				RegisterEntries(currentConfig.UnavailableSurvivors, logger);
			}
		}

		private static void RegisterEntries(Dictionary<string, SurvivorJsonEntry> entries, ManualLogSource logger)
		{
			if (entries == null)
			{
				return;
			}
			foreach (KeyValuePair<string, SurvivorJsonEntry> entry in entries)
			{
				string key = entry.Key;
				SurvivorJsonEntry value = entry.Value;
				if (RequiresCustomUnlock(value) && !CustomUnlockables.ContainsKey(key))
				{
					RegisterOneUnlockable(key, value, logger, addThroughContentAddition: true);
				}
			}
		}

		public static UnlockableDef RegisterDynamicUnlockable(string bodyName, SurvivorJsonEntry entry, ManualLogSource logger)
		{
			if (CustomUnlockables.TryGetValue(bodyName, out var value))
			{
				return value;
			}
			return RegisterOneUnlockable(bodyName, entry, logger, addThroughContentAddition: false);
		}

		public static bool TryGetCustomUnlockable(string bodyName, out UnlockableDef unlockable)
		{
			return CustomUnlockables.TryGetValue(bodyName, out unlockable);
		}

		public static void RememberOriginalUnlock(SurvivorDef survivorDef, UnlockableDef originalUnlock)
		{
			if (!((Object)(object)survivorDef == (Object)null) && !IsCustomUnlock(originalUnlock))
			{
				if (!OriginalUnlockables.TryGetValue(survivorDef, out var value))
				{
					OriginalUnlockables[survivorDef] = originalUnlock;
				}
				else if ((Object)(object)value == (Object)null && (Object)(object)originalUnlock != (Object)null)
				{
					OriginalUnlockables[survivorDef] = originalUnlock;
				}
			}
		}

		public static void RestoreOriginalUnlock(SurvivorDef survivorDef)
		{
			if (!((Object)(object)survivorDef == (Object)null))
			{
				if (OriginalUnlockables.TryGetValue(survivorDef, out var value))
				{
					survivorDef.unlockableDef = value;
				}
				else if (IsCustomUnlock(survivorDef.unlockableDef))
				{
					survivorDef.unlockableDef = null;
				}
			}
		}

		public static void AssignEarlyCustomUnlock(SurvivorDef survivorDef, UnlockableDef customUnlock, ManualLogSource logger)
		{
			if (!((Object)(object)survivorDef == (Object)null) && !((Object)(object)customUnlock == (Object)null))
			{
				UnlockableDef unlockableDef = survivorDef.unlockableDef;
				if (!OriginalUnlockables.ContainsKey(survivorDef))
				{
					OriginalUnlockables[survivorDef] = (IsCustomUnlock(unlockableDef) ? null : unlockableDef);
				}
				survivorDef.unlockableDef = customUnlock;
				logger.LogInfo((object)("Unlock temprano asignado | Survivor: " + survivorDef.cachedName + " | Unlock: " + customUnlock.cachedName));
			}
		}

		private static UnlockableDef RegisterOneUnlockable(string bodyName, SurvivorJsonEntry entry, ManualLogSource logger, bool addThroughContentAddition)
		{
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			if (string.IsNullOrWhiteSpace(bodyName) || entry == null)
			{
				return null;
			}
			if (CustomUnlockables.TryGetValue(bodyName, out var value))
			{
				return value;
			}
			string text = "UniversalSurvivorUnlocks." + bodyName;
			string text2 = "UniversalSurvivorUnlocks." + bodyName + ".Achievement";
			string text3 = "USU_" + MakeToken(bodyName);
			string text4 = text3 + "_UNLOCKABLE_NAME";
			string text5 = text3 + "_ACHIEVEMENT_NAME";
			string text6 = text3 + "_ACHIEVEMENT_DESCRIPTION";
			string challengeName = GetChallengeName(entry);
			string text7 = BuildChallengeDescription(entry);
			LanguageAPI.Add(text4, entry.DisplayName);
			LanguageAPI.Add(text5, challengeName);
			LanguageAPI.Add(text6, text7);
			UnlockableDef val = ScriptableObject.CreateInstance<UnlockableDef>();
			val.cachedName = text;
			val.nameToken = text4;
			val.sortScore = 200;
			val.hidden = false;
			val.achievementIcon = LegacyResourcesAPI.Load<Sprite>("Textures/MiscIcons/texUnlockIcon");
			val.getHowToUnlockString = delegate
			{
				SurvivorJsonEntry entry2 = GetEntry(bodyName) ?? entry;
				return Language.GetStringFormatted("UNLOCK_VIA_ACHIEVEMENT_FORMAT", new object[2]
				{
					GetChallengeName(entry2),
					BuildChallengeDescription(entry2)
				});
			};
			val.getUnlockedString = delegate
			{
				SurvivorJsonEntry entry2 = GetEntry(bodyName) ?? entry;
				return Language.GetStringFormatted("UNLOCKED_FORMAT", new object[2]
				{
					GetChallengeName(entry2),
					BuildChallengeDescription(entry2)
				});
			};
			AchievementDef val2 = new AchievementDef
			{
				identifier = text2,
				unlockableRewardIdentifier = text,
				prerequisiteAchievementIdentifier = null,
				nameToken = text5,
				descriptionToken = text6,
				achievedIcon = val.achievementIcon,
				type = typeof(UniversalSurvivorAchievement),
				serverTrackerType = null
			};
			if (!UnlockableAPI.AddAchievement(val2))
			{
				logger.LogError((object)("No se pudo registrar el achievement para " + bodyName + "."));
				return null;
			}
			if (addThroughContentAddition)
			{
				ContentAddition.AddUnlockableDef(val);
			}
			CustomAchievements[bodyName] = val2;
			CustomUnlockables[bodyName] = val;
			logger.LogInfo((object)("Unlock registrado correctamente | Survivor: " + bodyName + " | Unlockable: " + text + " | Achievement: " + text2 + " | Ruta: " + (addThroughContentAddition ? "R2API" : "DynamicContentPack")));
			return val;
		}

		public static void ApplyConfiguredUnlockables(List<SurvivorInfo> survivors, ManualLogSource logger)
		{
			foreach (SurvivorInfo survivor in survivors)
			{
				if (survivor == null || (Object)(object)survivor.SurvivorDef == (Object)null || !survivor.IsModded || survivor.Status != SurvivorStatus.Available)
				{
					continue;
				}
				SurvivorDef survivorDef = survivor.SurvivorDef;
				string bodyName = survivor.BodyName;
				if (!OriginalUnlockables.ContainsKey(survivorDef))
				{
					OriginalUnlockables[survivorDef] = (IsCustomUnlock(survivorDef.unlockableDef) ? null : survivorDef.unlockableDef);
				}
				UnlockableDef value;
				if (survivor.HasOriginalUnlock)
				{
					if ((Object)(object)survivorDef.unlockableDef != (Object)null && !IsCustomUnlock(survivorDef.unlockableDef))
					{
						OriginalUnlockables[survivorDef] = survivorDef.unlockableDef;
					}
					RestoreOriginalUnlock(survivorDef);
					logger.LogInfo((object)("Unlock original respetado: " + survivor.DisplayName));
				}
				else if (!RequiresCustomUnlock(GetEntry(bodyName)))
				{
					RestoreOriginalUnlock(survivorDef);
				}
				else if (!CustomUnlockables.TryGetValue(bodyName, out value))
				{
					logger.LogWarning((object)("No existe UnlockableDef registrado para " + bodyName + "."));
				}
				else
				{
					survivorDef.unlockableDef = value;
					ApplySurvivorAchievementIcon(survivor, value, logger);
					logger.LogInfo((object)("Unlock personalizado asignado: " + survivor.DisplayName + " | " + value.cachedName));
				}
			}
		}

		private static void ApplySurvivorAchievementIcon(SurvivorInfo survivorInfo, UnlockableDef unlockable, ManualLogSource logger)
		{
			if (survivorInfo == null || (Object)(object)survivorInfo.SurvivorDef == (Object)null || (Object)(object)survivorInfo.SurvivorDef.bodyPrefab == (Object)null)
			{
				return;
			}
			CharacterBody component = survivorInfo.SurvivorDef.bodyPrefab.GetComponent<CharacterBody>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.portraitIcon == (Object)null)
			{
				logger.LogWarning((object)("No se encontró portraitIcon para " + survivorInfo.BodyName + "."));
				return;
			}
			if (!CustomAchievementIcons.TryGetValue(survivorInfo.BodyName, out var value) || (Object)(object)value == (Object)null)
			{
				value = CreateFramedAchievementIcon(component.portraitIcon, survivorInfo.BodyName);
				if ((Object)(object)value == (Object)null)
				{
					logger.LogWarning((object)("No se pudo crear el icono con marco para " + survivorInfo.BodyName + "."));
					return;
				}
				CustomAchievementIcons[survivorInfo.BodyName] = value;
			}
			unlockable.achievementIcon = value;
			if (CustomAchievements.TryGetValue(survivorInfo.BodyName, out var value2))
			{
				value2.achievedIcon = value;
			}
			logger.LogInfo((object)("Icono de achievement con marco actualizado: " + survivorInfo.DisplayName));
		}

		private static Sprite CreateFramedAchievementIcon(Texture source, string bodyName)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit(source, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, false);
				val.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0);
				val.Apply();
				((Object)val).name = "USU_" + bodyName + "_AchievementTexture";
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)1;
				FillAchievementBackground(val);
				DrawAchievementFrame(val);
				Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				((Object)obj).name = "USU_" + bodyName + "_AchievementIcon";
				return obj;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		private static void FillAchievementBackground(Texture2D texture)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)texture == (Object)null))
			{
				Color32 val = default(Color32);
				((Color32)(ref val))..ctor((byte)24, (byte)40, (byte)57, byte.MaxValue);
				Color32[] pixels = texture.GetPixels32();
				for (int i = 0; i < pixels.Length; i++)
				{
					Color32 val2 = pixels[i];
					float num = (float)(int)val2.a / 255f;
					byte b = (byte)Mathf.RoundToInt((float)(int)val2.r * num + (float)(int)val.r * (1f - num));
					byte b2 = (byte)Mathf.RoundToInt((float)(int)val2.g * num + (float)(int)val.g * (1f - num));
					byte b3 = (byte)Mathf.RoundToInt((float)(int)val2.b * num + (float)(int)val.b * (1f - num));
					pixels[i] = new Color32(b, b2, b3, byte.MaxValue);
				}
				texture.SetPixels32(pixels);
				texture.Apply();
			}
		}

		private static void DrawAchievementFrame(Texture2D texture)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			int width = ((Texture)texture).width;
			int height = ((Texture)texture).height;
			int num = Mathf.Max(2, Mathf.RoundToInt((float)Mathf.Min(width, height) * 0.018f));
			Color32 color = default(Color32);
			((Color32)(ref color))..ctor((byte)73, (byte)99, (byte)124, byte.MaxValue);
			Color32 color2 = default(Color32);
			((Color32)(ref color2))..ctor((byte)20, (byte)25, (byte)30, byte.MaxValue);
			int num2 = Mathf.Max(1, num / 2);
			DrawTextureBorder(texture, color2, num + num2);
			DrawTextureBorder(texture, color, num);
			texture.Apply();
		}

		private static void DrawTextureBorder(Texture2D texture, Color32 color, int thickness)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			int width = ((Texture)texture).width;
			int height = ((Texture)texture).height;
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					if (j < thickness || j >= width - thickness || i < thickness || i >= height - thickness)
					{
						texture.SetPixel(j, i, Color32.op_Implicit(color));
					}
				}
			}
		}

		private static SurvivorJsonEntry GetEntry(string bodyName)
		{
			return SurvivorJsonManager.GetEntryAnywhere(bodyName);
		}

		private static string GetChallengeName(SurvivorJsonEntry entry)
		{
			if (entry?.Challenge != null && !string.IsNullOrWhiteSpace(entry.Challenge.Name))
			{
				return entry.Challenge.Name;
			}
			return "Desafío de desbloqueo";
		}

		private static string BuildChallengeDescription(SurvivorJsonEntry entry)
		{
			if (entry == null || entry.Challenge == null)
			{
				return "Completa el desafío para desbloquear este personaje.";
			}
			JObject parameters = entry.Challenge.Parameters;
			switch (entry.Challenge.Type)
			{
			case "KillEnemies":
			{
				int num4 = GetInt(parameters, "amount", 1);
				return $"Derrota {num4} enemigos.";
			}
			case "KillBoss":
			{
				int num3 = GetInt(parameters, "amount", 1);
				return $"Derrota {num3} jefes.";
			}
			case "ReachLevel":
			{
				int num2 = GetInt(parameters, "level", 1);
				return $"Alcanza el nivel {num2}.";
			}
			case "ReachStage":
			{
				int num = GetInt(parameters, "stage", 1);
				return $"Alcanza la fase {num}.";
			}
			default:
				return "Completa la misión \"" + entry.Challenge.Type + "\".";
			}
		}

		private static int GetInt(JObject parameters, string key, int defaultValue)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			if (parameters == null)
			{
				return defaultValue;
			}
			JToken val = parameters[key];
			if (val == null || (int)val.Type != 6)
			{
				return defaultValue;
			}
			return Extensions.Value<int>((IEnumerable<JToken>)val);
		}

		private static string MakeToken(string value)
		{
			return value.Replace(".", "_").Replace("-", "_").Replace(" ", "_")
				.ToUpperInvariant();
		}
	}
	public sealed class UniversalContentPackProvider : IContentPackProvider
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static CollectContentPackProvidersDelegate <0>__CollectContentPackProviders;
		}

		private static ManualLogSource _logger;

		private static bool _initialized;

		private static UniversalContentPackProvider _instance;

		private readonly ContentPack _contentPack;

		private readonly HashSet<string> _dynamicUnlockBodies = new HashSet<string>(StringComparer.Ordinal);

		private readonly HashSet<string> _loggedAutoLocks = new HashSet<string>(StringComparer.Ordinal);

		private readonly HashSet<string> _loggedOriginalUnlocks = new HashSet<string>(StringComparer.Ordinal);

		public string identifier => "com.danileo.UniversalSurvivorUnlocks.DynamicUnlocks";

		private UniversalContentPackProvider()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			_contentPack = new ContentPack();
			_contentPack.identifier = identifier;
		}

		public static void Initialize(ManualLogSource logger)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			if (!_initialized)
			{
				_initialized = true;
				_logger = logger;
				_instance = new UniversalContentPackProvider();
				ModdedSurvivorRegistry.Reset(logger);
				object obj = <>O.<0>__CollectContentPackProviders;
				if (obj == null)
				{
					CollectContentPackProvidersDelegate val = CollectContentPackProviders;
					<>O.<0>__CollectContentPackProviders = val;
					obj = (object)val;
				}
				ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)obj;
				logger.LogInfo((object)"UniversalContentPackProvider registrado.");
			}
		}

		private static void CollectContentPackProviders(AddContentPackProviderDelegate addContentPackProvider)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__CollectContentPackProviders;
			if (obj == null)
			{
				CollectContentPackProvidersDelegate val = CollectContentPackProviders;
				<>O.<0>__CollectContentPackProviders = val;
				obj = (object)val;
			}
			ContentManager.collectContentPackProviders -= (CollectContentPackProvidersDelegate)obj;
			addContentPackProvider.Invoke((IContentPackProvider)(object)_instance);
			_logger.LogInfo((object)"UniversalContentPackProvider añadido al pipeline de ContentManager.");
		}

		public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
		{
			args.ReportProgress(1f);
			yield break;
		}

		public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args)
		{
			Enumerator<ContentPackLoadInfo> enumerator = args.peerLoadInfos.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					ModdedSurvivorRegistry.RegisterContentPack(enumerator.Current.previousContentPack, _logger);
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			ProcessDiscoveredSurvivors();
			ContentPack.Copy(_contentPack, args.output);
			args.ReportProgress(1f);
			yield break;
		}

		private void ProcessDiscoveredSurvivors()
		{
			foreach (SurvivorDef registeredSurvivor in ModdedSurvivorRegistry.GetRegisteredSurvivors())
			{
				if ((Object)(object)registeredSurvivor == (Object)null || registeredSurvivor.hidden || (Object)(object)registeredSurvivor.bodyPrefab == (Object)null)
				{
					continue;
				}
				string name = ((Object)registeredSurvivor.bodyPrefab).name;
				ModdedSurvivorRegistry.TryGetSource(registeredSurvivor, out var contentPackIdentifier, out var assemblyName);
				UnlockableDef unlockableDef = registeredSurvivor.unlockableDef;
				if ((Object)(object)unlockableDef != (Object)null && !SurvivorUnlockManager.IsCustomUnlock(unlockableDef))
				{
					SurvivorUnlockManager.RememberOriginalUnlock(registeredSurvivor, unlockableDef);
					if (_loggedOriginalUnlocks.Add(name))
					{
						_logger.LogInfo((object)("UNLOCK ORIGINAL RESPETADO | Body: " + name + " | Pack: " + contentPackIdentifier + " | Unlock: " + unlockableDef.cachedName));
					}
					continue;
				}
				SurvivorJsonEntry survivorJsonEntry = SurvivorJsonManager.GetEntryAnywhere(name);
				if (survivorJsonEntry == null)
				{
					survivorJsonEntry = SurvivorJsonManager.CreateAutomaticEntry(registeredSurvivor, contentPackIdentifier, assemblyName, _logger);
				}
				if (survivorJsonEntry == null)
				{
					continue;
				}
				if (!SurvivorUnlockManager.RequiresCustomUnlock(survivorJsonEntry))
				{
					SurvivorUnlockManager.RestoreOriginalUnlock(registeredSurvivor);
					continue;
				}
				if (!SurvivorUnlockManager.TryGetCustomUnlockable(name, out var unlockable))
				{
					unlockable = SurvivorUnlockManager.RegisterDynamicUnlockable(name, survivorJsonEntry, _logger);
					if ((Object)(object)unlockable == (Object)null)
					{
						_logger.LogError((object)("No fue posible crear el unlock dinámico de " + name + "."));
						continue;
					}
					if (_dynamicUnlockBodies.Add(name))
					{
						_contentPack.unlockableDefs.Add((UnlockableDef[])(object)new UnlockableDef[1] { unlockable });
						_logger.LogInfo((object)("UnlockableDef añadido al Dynamic ContentPack | " + unlockable.cachedName));
					}
				}
				SurvivorUnlockManager.RememberOriginalUnlock(registeredSurvivor, null);
				SurvivorUnlockManager.AssignEarlyCustomUnlock(registeredSurvivor, unlockable, _logger);
				if (_loggedAutoLocks.Add(name))
				{
					_logger.LogInfo((object)("AUTOLOCK ACTIVADO | Body: " + name + " | Pack: " + contentPackIdentifier));
				}
			}
		}

		public IEnumerator FinalizeAsync(FinalizeAsyncArgs args)
		{
			_logger.LogInfo((object)("Universal ContentPack finalizado | Survivors modded detectados: " + $"{ModdedSurvivorRegistry.Count} | " + "Unlockables dinámicos: " + $"{_dynamicUnlockBodies.Count}"));
			args.ReportProgress(1f);
			yield break;
		}
	}
	public class UniversalSurvivorAchievement : BaseAchievement
	{
	}
}