Decompiled source of Deathlink v0.11.2

plugins/Deathlink.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
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.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using AlmanacClasses.API;
using AzuExtendedPlayerInventory;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Deathlink.Common;
using Deathlink.Death;
using Deathlink.external;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SimpleJson;
using Splatform;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Deathlink")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Deathlink")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Backpacks
{
	[PublicAPI]
	public static class API
	{
		public static EpicMMOSystem_API.API_State state;

		private static MethodInfo eCountItemsInBackpacks;

		private static MethodInfo eAddItemToBackpack;

		private static MethodInfo eDeleteItemsFromBackpacks;

		private static MethodInfo eGetEquippedBackpackInventory;

		private static MethodInfo eGetAllBackpackInventories;

		public static int CountItemsInBackpacks(Inventory inventory, string name, bool onlyRemoveable = true)
		{
			return (int)eCountItemsInBackpacks?.Invoke(null, new object[3] { inventory, name, onlyRemoveable });
		}

		public static bool IsItemInBackpacks(Inventory inventory, string name)
		{
			return CountItemsInBackpacks(inventory, name) > 0;
		}

		public static bool AddItemToBackpack(ItemData backpack, ItemData item)
		{
			return (bool)eAddItemToBackpack?.Invoke(null, new object[2] { backpack, item });
		}

		public static bool DeleteItemsFromBackpacks(Inventory inventory, string name, int count = 1)
		{
			return (bool)eDeleteItemsFromBackpacks?.Invoke(null, new object[3] { inventory, name, count });
		}

		public static Inventory? GetEquippedBackpackInventory()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return (Inventory)(eGetEquippedBackpackInventory?.Invoke(null, new object[0]));
		}

		public static List<Inventory> GetAllBackpackInventories(Inventory inventory)
		{
			return (List<Inventory>)(eGetAllBackpackInventories?.Invoke(null, new object[1] { inventory }));
		}

		public static void Init()
		{
			EpicMMOSystem_API.API_State aPI_State = state;
			if ((uint)(aPI_State - 1) > 1u)
			{
				if (Type.GetType("Backpacks.API, Backpacks") == null)
				{
					state = EpicMMOSystem_API.API_State.NotInstalled;
					return;
				}
				state = EpicMMOSystem_API.API_State.Ready;
				Type type = Type.GetType("Backpacks.API, Backpacks");
				eCountItemsInBackpacks = type.GetMethod("CountItemsInBackpacks", BindingFlags.Static | BindingFlags.Public);
				eAddItemToBackpack = type.GetMethod("AddItemToBackpack", BindingFlags.Static | BindingFlags.Public);
				eDeleteItemsFromBackpacks = type.GetMethod("DeleteItemsFromBackpacks", BindingFlags.Static | BindingFlags.Public);
				eGetEquippedBackpackInventory = type.GetMethod("GetEquippedBackpackInventory", BindingFlags.Static | BindingFlags.Public);
				eGetAllBackpackInventories = type.GetMethod("GetAllBackpackInventories", BindingFlags.Static | BindingFlags.Public);
			}
		}
	}
}
namespace AzuExtendedPlayerInventory
{
	[PublicAPI]
	public class API
	{
		public delegate void SlotAddedHandler(string slotName);

		public delegate void SlotRemovedHandler(string slotName);

		public static event Action<Hud>? OnHudAwake;

		public static event Action<Hud>? OnHudAwakeComplete;

		public static event Action<Hud>? OnHudUpdate;

		public static event Action<Hud>? OnHudUpdateComplete;

		public static event SlotAddedHandler? SlotAdded;

		public static event SlotRemovedHandler? SlotRemoved;

		public static bool IsLoaded()
		{
			return false;
		}

		public static bool AddSlot(string slotName, Func<Player, ItemData?> getItem, Func<ItemData, bool> isValid, int index = -1)
		{
			return false;
		}

		public static bool RemoveSlot(string slotName)
		{
			return false;
		}

		public static SlotInfo GetSlots()
		{
			return new SlotInfo();
		}

		public static SlotInfo GetQuickSlots()
		{
			return new SlotInfo();
		}

		public static List<ItemData> GetQuickSlotsItems()
		{
			return new List<ItemData>();
		}

		public static int GetAddedRows(int width)
		{
			return 0;
		}
	}
	[PublicAPI]
	public class SlotInfo
	{
		public string[] SlotNames { get; set; } = new string[0];

		public Vector2[] SlotPositions { get; set; } = (Vector2[])(object)new Vector2[0];

		public Func<Player, ItemData?>?[] GetItemFuncs { get; set; } = new Func<Player, ItemData>[0];

		public Func<ItemData, bool>?[] IsValidFuncs { get; set; } = new Func<ItemData, bool>[0];
	}
}
namespace AlmanacClasses.API
{
	public static class ClassesAPI
	{
		private static readonly MethodInfo? API_AddExperience;

		private static readonly MethodInfo? API_GetLevel;

		private static readonly MethodInfo? API_GetCharacteristic;

		public static void AddEXP(int amount)
		{
			API_AddExperience?.Invoke(null, new object[1] { amount });
		}

		public static int GetLevel()
		{
			return (int)(API_GetLevel?.Invoke(null, null) ?? ((object)0));
		}

		public static int GetCharacteristic(string type)
		{
			return (int)(API_GetCharacteristic?.Invoke(null, new object[1] { type }) ?? ((object)0));
		}

		public static int GetConstitution()
		{
			return GetCharacteristic("Constitution");
		}

		public static int GetDexterity()
		{
			return GetCharacteristic("Dexterity");
		}

		public static int GetStrength()
		{
			return GetCharacteristic("Strength");
		}

		public static int GetIntelligence()
		{
			return GetCharacteristic("Intelligence");
		}

		public static int GetWisdom()
		{
			return GetCharacteristic("Wisdom");
		}

		static ClassesAPI()
		{
			Type type = Type.GetType("AlmanacClasses.API.API, AlmanacClasses");
			if ((object)type != null)
			{
				API_AddExperience = type.GetMethod("AddExperience", BindingFlags.Static | BindingFlags.Public);
				API_GetLevel = type.GetMethod("GetLevel", BindingFlags.Static | BindingFlags.Public);
				API_GetCharacteristic = type.GetMethod("GetCharacteristic", BindingFlags.Static | BindingFlags.Public);
			}
		}
	}
}
namespace Deathlink
{
	internal class Logger
	{
		public static LogLevel Level = (LogLevel)16;

		public static void enableDebugLogging(object sender, EventArgs e)
		{
			//IL_0016: 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)
			if (ValConfig.EnableDebugMode.Value)
			{
				Level = (LogLevel)32;
			}
			else
			{
				Level = (LogLevel)16;
			}
		}

		public static void CheckEnableDebugLogging()
		{
			//IL_0016: 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)
			if (ValConfig.EnableDebugMode.Value)
			{
				Level = (LogLevel)32;
			}
			else
			{
				Level = (LogLevel)16;
			}
		}

		public static void LogDebug(string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)Level >= 32)
			{
				Deathlink.Log.LogInfo((object)message);
			}
		}

		public static void LogInfo(string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)Level >= 16)
			{
				Deathlink.Log.LogInfo((object)message);
			}
		}

		public static void LogWarning(string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)Level >= 4)
			{
				Deathlink.Log.LogWarning((object)message);
			}
		}

		public static void LogError(string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)Level >= 2)
			{
				Deathlink.Log.LogError((object)message);
			}
		}
	}
	[BepInPlugin("MidnightsFX.Deathlink", "Deathlink", "0.11.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class Deathlink : BaseUnityPlugin
	{
		public const string PluginGUID = "MidnightsFX.Deathlink";

		public const string PluginName = "Deathlink";

		public const string PluginVersion = "0.11.2";

		public ValConfig cfg;

		internal static AssetBundle EmbeddedResourceBundle;

		internal static bool AzuEPILoaded = false;

		internal static bool RustyAlmanacClassesLoaded = false;

		internal static bool WackyMMOLoaded = false;

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		public static ManualLogSource Log;

		public void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			cfg = new ValConfig(((BaseUnityPlugin)this).Config);
			AddLocalizations();
			EmbeddedResourceBundle = AssetUtils.LoadAssetBundleFromResources("Deathlink.AssetsEmbedded.deathless", typeof(Deathlink).Assembly);
			DeathProgressionSkill.SetupDeathSkill();
			if (API.IsLoaded())
			{
				AzuEPILoaded = true;
			}
			if (Enumerable.Contains(BepInExUtils.GetPlugins(false).Keys, "WackyMole.EpicMMOSystem"))
			{
				EpicMMOSystem_API.Init();
				if (EpicMMOSystem_API.state == EpicMMOSystem_API.API_State.Ready)
				{
					WackyMMOLoaded = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)"WackMMO API loaded.");
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"WackMMO API installed but API not ready.");
				}
			}
			if (Enumerable.Contains(BepInExUtils.GetPlugins(false).Keys, "RustyMods.AlmanacClasses"))
			{
				RustyAlmanacClassesLoaded = true;
			}
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			YamlConfigManager.Init();
			DeathChoiceEditor.Init();
			LeaderboardData.Init();
			((MonoBehaviour)this).StartCoroutine(LeaderboardData.SyncLoop());
			TerminalCommands.AddCommands();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Death is not the end.");
		}

		public static DataObjects.DeathChoiceLevel pcfg()
		{
			return DeathConfigurationData.playerDeathConfiguration;
		}

		private void AddLocalizations()
		{
			Localization = LocalizationManager.Instance.GetLocalization();
			string text = Path.Combine(Paths.ConfigPath, "Deathlink", "localizations");
			Directory.CreateDirectory(text);
			string[] manifestResourceNames = typeof(Deathlink).Assembly.GetManifestResourceNames();
			foreach (string text2 in manifestResourceNames)
			{
				if (!text2.Contains("Localizations"))
				{
					continue;
				}
				string input = ReadEmbeddedResourceFile(text2);
				string text3 = Regex.Replace(input, "\\/\\/.*", "");
				Dictionary<string, string> internal_localization = SimpleJson.DeserializeObject<Dictionary<string, string>>(text3);
				string[] array = text2.Split(new char[1] { '.' });
				if (File.Exists(text + "/" + array[2] + ".json"))
				{
					string text4 = File.ReadAllText(text + "/" + array[2] + ".json");
					try
					{
						Dictionary<string, string> dictionary = SimpleJson.DeserializeObject<Dictionary<string, string>>(text4);
						UpdateLocalizationWithMissingKeys(internal_localization, dictionary);
						((BaseUnityPlugin)this).Logger.LogDebug((object)("Reading " + text + "/" + array[2] + ".json"));
						File.WriteAllText(text + "/" + array[2] + ".json", SimpleJson.SerializeObject((object)dictionary));
						string text5 = File.ReadAllText(text + "/" + array[2] + ".json");
						Localization.AddJsonFile(array[2], text5);
					}
					catch
					{
						File.WriteAllText(text + "/" + array[2] + ".json", text3);
						((BaseUnityPlugin)this).Logger.LogDebug((object)("Reading " + text2));
						Localization.AddJsonFile(array[2], text3);
					}
				}
				else
				{
					File.WriteAllText(text + "/" + array[2] + ".json", text3);
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Reading " + text2));
					Localization.AddJsonFile(array[2], text3);
				}
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Added localization: '" + array[2] + "'"));
			}
		}

		private void UpdateLocalizationWithMissingKeys(Dictionary<string, string> internal_localization, Dictionary<string, string> cached_localization)
		{
			if (internal_localization.Keys.Count == cached_localization.Keys.Count)
			{
				return;
			}
			((BaseUnityPlugin)this).Logger.LogDebug((object)"Cached localization was missing some entries. They will be added.");
			foreach (KeyValuePair<string, string> item in internal_localization)
			{
				if (!cached_localization.ContainsKey(item.Key))
				{
					cached_localization.Add(item.Key, item.Value);
				}
			}
		}

		private string ReadEmbeddedResourceFile(string filename)
		{
			using Stream stream = typeof(Deathlink).Assembly.GetManifestResourceStream(filename);
			using StreamReader streamReader = new StreamReader(stream);
			return streamReader.ReadToEnd();
		}

		public static List<T> shuffleList<T>(List<T> inputList)
		{
			int i = 0;
			int count = inputList.Count;
			int num = 0;
			T val = default(T);
			List<T> list = new List<T>();
			list.AddRange(inputList);
			for (; i < count; i++)
			{
				num = Random.Range(i, list.Count);
				val = list[i];
				list[i] = list[num];
				list[num] = val;
			}
			return list;
		}
	}
}
namespace Deathlink.external
{
	public static class EpicMMOSystem_API
	{
		public enum API_State
		{
			NotReady,
			NotInstalled,
			Ready
		}

		public enum Attribut
		{
			Strength,
			Agility,
			Intellect,
			Body,
			Vigour,
			Special
		}

		public static API_State state;

		private static MethodInfo eGetLevel;

		private static MethodInfo eAddExp;

		private static MethodInfo eGetAttribute;

		private static MethodInfo eGetAttributeRusty;

		private static MethodInfo eSetSingleRate;

		public static int GetLevel()
		{
			int result = 0;
			Init();
			if (eGetLevel != null)
			{
				result = (int)eGetLevel.Invoke(null, null);
			}
			return result;
		}

		public static int GetAttribute(Attribut attribute)
		{
			int result = 0;
			Init();
			if (eGetAttribute != null)
			{
				result = (int)eGetAttribute.Invoke(null, new object[1] { attribute });
			}
			return result;
		}

		public static int GetAttributeRusty(string attribute)
		{
			int result = 0;
			Init();
			if (eGetAttributeRusty != null)
			{
				result = (int)eGetAttributeRusty.Invoke(null, new object[1] { attribute });
			}
			return result;
		}

		public static void AddExp(int value)
		{
			Init();
			eAddExp?.Invoke(null, new object[1] { value });
		}

		public static void SetSingleRate(float rate)
		{
			Init();
			eSetSingleRate?.Invoke(null, new object[1] { rate });
		}

		public static void Init()
		{
			API_State aPI_State = state;
			if ((uint)(aPI_State - 1) > 1u)
			{
				if (Type.GetType("EpicMMOSystem.EpicMMOSystem, EpicMMOSystem") == null)
				{
					state = API_State.NotInstalled;
					return;
				}
				state = API_State.Ready;
				Type type = Type.GetType("API.EMMOS_API, EpicMMOSystem");
				eGetLevel = type.GetMethod("GetLevel", BindingFlags.Static | BindingFlags.Public);
				eAddExp = type.GetMethod("AddExp", BindingFlags.Static | BindingFlags.Public);
				eGetAttribute = type.GetMethod("GetAttribute", BindingFlags.Static | BindingFlags.Public);
				eGetAttributeRusty = type.GetMethod("GetAttribute", BindingFlags.Static | BindingFlags.Public);
				eSetSingleRate = type.GetMethod("SetSingleRate", BindingFlags.Static | BindingFlags.Public);
			}
		}
	}
}
namespace Deathlink.Death
{
	public static class Compendium
	{
		[HarmonyPatch(typeof(TextsDialog), "UpdateTextsList")]
		public static class TextsDialog_UpdateTextsList_Patch
		{
			public static void Postfix(TextsDialog __instance)
			{
				AddDeathLinkExplanationPage(__instance);
			}

			private static void AddDeathLinkExplanationPage(TextsDialog textsDialog)
			{
				//IL_018a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0194: Expected O, but got Unknown
				DataObjects.DeathChoiceLevel playerDeathConfiguration = DeathConfigurationData.playerDeathConfiguration;
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("<size=48>" + Localization.instance.Localize("$comp_header") + ": <color=" + specialColor + ">" + playerDeathConfiguration.DisplayName + "</color></size>");
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("<size=30><b>Death Effects</b></size>");
				stringBuilder.AppendLine(playerDeathConfiguration.GetDeathStyleDescription());
				stringBuilder.AppendLine();
				if (playerDeathConfiguration.DamageTakenModifier != 1f || playerDeathConfiguration.DamageDoneModifier != 1f)
				{
					stringBuilder.AppendLine("<size=30><b>Combat Modifiers</b></size>");
					stringBuilder.AppendLine(playerDeathConfiguration.GetDamageModifierDescription());
					stringBuilder.AppendLine();
				}
				if (playerDeathConfiguration.SkillModifiers != null && playerDeathConfiguration.SkillModifiers.Count > 0)
				{
					stringBuilder.AppendLine("<size=30><b>Skill Modifiers</b></size>");
					stringBuilder.AppendLine(playerDeathConfiguration.GetSkillModiferDescription());
					stringBuilder.AppendLine();
				}
				if (playerDeathConfiguration.ResourceModifiers != null && playerDeathConfiguration.ResourceModifiers.Count > 0)
				{
					stringBuilder.AppendLine("<size=30><b>Resource Modifiers</b></size>");
					stringBuilder.AppendLine(playerDeathConfiguration.GetResourceModiferDescription());
					stringBuilder.AppendLine();
				}
				if (playerDeathConfiguration.DeathLootModifiers != null && playerDeathConfiguration.DeathLootModifiers.Count > 0)
				{
					stringBuilder.AppendLine("<size=30><b>Loot Modifiers</b></size>");
					stringBuilder.AppendLine(playerDeathConfiguration.GetLootModifiersDescription());
					stringBuilder.AppendLine();
				}
				textsDialog.m_texts.Insert(0, new TextInfo(Localization.instance.Localize("$deathlink_settings"), Localization.instance.Localize(stringBuilder.ToString())));
			}
		}

		[HarmonyPatch(typeof(TextsDialog), "ShowText", new Type[] { typeof(TextInfo) })]
		public static class TextsDialog_ShowText_Patch
		{
			public static void Postfix(TextsDialog __instance, TextInfo text)
			{
				bool flag = text != null && text.m_topic == Localization.instance.Localize("$deathlink_settings");
				bool flag2 = flag && DeathConfigurationData.PlayerCanChangeChoice(Player.m_localPlayer);
				Logger.LogDebug($"TextsDialog.ShowText topic='{text?.m_topic}' isDeathlinkPage={flag} canChange={flag2}");
				if (!flag2)
				{
					if ((Object)(object)changeChoiceButton != (Object)null)
					{
						changeChoiceButton.SetActive(false);
					}
					return;
				}
				EnsureChangeChoiceButton(__instance);
				if ((Object)(object)changeChoiceButton != (Object)null)
				{
					changeChoiceButton.SetActive(true);
					changeChoiceButton.transform.SetAsLastSibling();
				}
			}

			private static void EnsureChangeChoiceButton(TextsDialog dialog)
			{
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0080: 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_00b9: Expected O, but got Unknown
				if ((Object)(object)changeChoiceButton != (Object)null)
				{
					return;
				}
				if (GUIManager.Instance == null)
				{
					Logger.LogWarning("GUIManager not setup, skipping death choice change button creation.");
					return;
				}
				Transform val = ((Component)dialog).transform.Find("Texts_frame/Closebutton");
				changeChoiceButton = GUIManager.Instance.CreateButton(Localization.instance.Localize("$comp_change_choice"), val, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(300f, 0f), 200f, 40f);
				((UnityEvent)changeChoiceButton.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					dialog.OnClose();
					DeathChoices.DeathChoiceUI.Instance.ShowForChange();
				});
			}

			private static RectTransform FindCloseButton(TextsDialog dialog)
			{
				Button val = null;
				Button[] componentsInChildren = ((Component)dialog).GetComponentsInChildren<Button>(true);
				foreach (Button val2 in componentsInChildren)
				{
					if ((Object)(object)((Component)val2).gameObject == (Object)(object)changeChoiceButton)
					{
						continue;
					}
					for (int j = 0; j < ((UnityEventBase)val2.onClick).GetPersistentEventCount(); j++)
					{
						if (((UnityEventBase)val2.onClick).GetPersistentMethodName(j) == "OnClose")
						{
							return ((Component)val2).GetComponent<RectTransform>();
						}
					}
					if ((Object)(object)val == (Object)null && ((Object)val2).name.IndexOf("close", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						val = val2;
					}
				}
				if (!((Object)(object)val != (Object)null))
				{
					return null;
				}
				return ((Component)val).GetComponent<RectTransform>();
			}
		}

		private static string specialColor = "#ffa64d";

		private static GameObject changeChoiceButton;
	}
	public static class DamageModifiers
	{
		[HarmonyPatch(typeof(Character), "RPC_Damage")]
		public static class DamageModifierPatch
		{
			private static void Prefix(Character __instance, HitData hit)
			{
				if (hit == null)
				{
					return;
				}
				if (__instance is Player)
				{
					float storedModifier = GetStoredModifier(__instance, DataObjects.DamageTakenModifierKey);
					if (storedModifier != 1f)
					{
						hit.ApplyModifier(storedModifier);
					}
				}
				Character attacker = hit.GetAttacker();
				Player val = (Player)(object)((attacker is Player) ? attacker : null);
				if (val != null)
				{
					float storedModifier2 = GetStoredModifier((Character)(object)val, DataObjects.DamageDoneModifierKey);
					if (storedModifier2 != 1f)
					{
						hit.ApplyModifier(storedModifier2);
					}
				}
			}

			private static float GetStoredModifier(Character character, string key)
			{
				if ((Object)(object)character == (Object)null)
				{
					return 1f;
				}
				ZNetView nview = character.m_nview;
				if ((Object)(object)nview == (Object)null || !nview.IsValid())
				{
					return 1f;
				}
				ZDO zDO = nview.GetZDO();
				if (zDO == null)
				{
					return 1f;
				}
				return zDO.GetFloat(key, 1f);
			}
		}
	}
	internal static class DeathChoiceEditor
	{
		private const string EntryName = "Deathlink";

		private const float PanelW = 1000f;

		private const float PanelH = 720f;

		private const float ListW = 250f;

		private const float DetailX = 280f;

		private const float DetailY = 96f;

		private const float LabelW = 230f;

		private const float MessagesH = 60f;

		private static GameObject panel;

		private static Transform body;

		private static GameObject detailRoot;

		private static Transform listContent;

		private static Text messages;

		private static DeathChoiceEditorModel model;

		private static int activeTab;

		private static bool awaitingServer;

		private static float sentAtTime;

		private static readonly string[] TabNames = new string[4] { "$dl_cfg_general", "$dl_cfg_deathstyle", "$dl_cfg_resources", "$dl_cfg_loot" };

		internal static void Init()
		{
			ConfigUILauncher.Init();
			ApplyRegistration();
			ConfigNetwork.EditResult += OnEditResult;
		}

		internal static void ApplyRegistration()
		{
			if (ValConfig.ShowQuickConfigButton == null || ValConfig.ShowQuickConfigButton.Value)
			{
				ConfigUILauncher.Register("Deathlink", OpenPanel);
			}
			else
			{
				ConfigUILauncher.Unregister("Deathlink");
			}
		}

		private static bool IsOwner()
		{
			if (!((Object)(object)ZNet.instance == (Object)null))
			{
				return ZNet.instance.IsServer();
			}
			return true;
		}

		internal static void OpenPanel()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			ClosePanel();
			if (GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null))
			{
				model = DeathChoiceEditorModel.Snapshot();
				awaitingServer = false;
				activeTab = 0;
				panel = ConfigUI.CreatePanel("$dl_cfg_title", 1000f, 720f, out body);
				ConfigUI.AddText(body, 280f, 54f, 700f, 24f, IsOwner() ? "$dl_cfg_banner_local" : "$dl_cfg_banner_remote", 13, (TextAnchor)3, GUIManager.Instance.ValheimBeige);
				BuildLevelList();
				BuildTabs();
				BuildDetail();
				messages = ConfigUI.AddText(body, 20f, 608f, 960f, 60f, "", 13, (TextAnchor)0);
				ConfigUI.AddButton(body, 20f, 668f, 130f, "$dl_cfg_validate", new UnityAction(RunValidate), 36f);
				ConfigUI.AddButton(body, 670f, 668f, 140f, "$dl_cfg_cancel", new UnityAction(ClosePanel), 36f);
				ConfigUI.AddButton(body, 820f, 668f, 160f, "$dl_cfg_apply", new UnityAction(ApplyAndSave), 36f);
			}
		}

		private static void ClosePanel()
		{
			ConfigUIPicker.Close();
			if ((Object)(object)panel != (Object)null)
			{
				Object.Destroy((Object)(object)panel);
				panel = null;
			}
			body = null;
			detailRoot = null;
			listContent = null;
			messages = null;
			awaitingServer = false;
		}

		private static void BuildLevelList()
		{
			//IL_0026: 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_0093: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			ConfigUI.AddText(body, 20f, 54f, 250f, 24f, "$dl_cfg_levels", 15, (TextAnchor)3, GUIManager.Instance.ValheimYellow);
			ConfigUI.CreateScroll(body, 20f, 82f, 250f, 480f, out listContent, out var contentWidth);
			RefreshLevelList(contentWidth);
			float y = 570f;
			ConfigUI.AddButton(body, 20f, y, 58f, "$dl_cfg_add", new UnityAction(OnAdd), 30f);
			ConfigUI.AddButton(body, 82f, y, 58f, "$dl_cfg_duplicate", new UnityAction(OnDuplicate), 30f);
			ConfigUI.AddButton(body, 144f, y, 58f, "$dl_cfg_rename", new UnityAction(OnRename), 30f);
			ConfigUI.AddButton(body, 206f, y, 58f, "$dl_cfg_delete", new UnityAction(OnDelete), 30f);
		}

		private static void RefreshLevelList(float contentW)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)listContent == (Object)null)
			{
				return;
			}
			foreach (Transform item in listContent)
			{
				Transform val = item;
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			foreach (string item2 in model.Order)
			{
				string entry = item2;
				bool flag = string.Equals(entry, model.SelectedKey, StringComparison.Ordinal);
				GameObject val2 = ConfigUI.NewLayoutRow(listContent, contentW, 32f);
				GameObject val3 = ConfigUI.AddButton(val2.transform, 0f, 0f, contentW, entry, (UnityAction)delegate
				{
					model.SelectedKey = entry;
					RefreshLevelList(contentW);
					BuildDetail();
				}, 30f);
				if (flag)
				{
					Text componentInChildren = val3.GetComponentInChildren<Text>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						((Graphic)componentInChildren).color = GUIManager.Instance.ValheimOrange;
					}
				}
			}
		}

		private static void RebuildList()
		{
			RefreshLevelList(234f);
			BuildDetail();
		}

		private static void OnAdd()
		{
			ConfigUIPrompt.Show("$dl_cfg_add_title", "$dl_cfg_add_label", "", null, delegate(string name)
			{
				if (!model.TryAdd(name, out var message))
				{
					ShowError(message);
				}
				else
				{
					if (!string.IsNullOrEmpty(message))
					{
						ShowWarning(message);
					}
					RebuildList();
				}
			});
		}

		private static void OnDuplicate()
		{
			if (!string.IsNullOrEmpty(model.SelectedKey) && model.Duplicate(model.SelectedKey) != null)
			{
				RebuildList();
			}
		}

		private static void OnRename()
		{
			if (string.IsNullOrEmpty(model.SelectedKey))
			{
				return;
			}
			string oldKey = model.SelectedKey;
			string text = ConfigUI.L("$dl_cfg_rename_warning").Replace("{0}", oldKey);
			if (ValConfig.DefaultDeathChoice != null && string.Equals(ValConfig.DefaultDeathChoice.Value, oldKey, StringComparison.Ordinal))
			{
				text = text + "\n" + ConfigUI.L("$dl_cfg_rename_isdefault");
			}
			ConfigUIPrompt.Show("$dl_cfg_rename_title", "$dl_cfg_rename_label", oldKey, text, delegate(string newKey)
			{
				if (!model.TryRename(oldKey, newKey, out var message))
				{
					ShowError(message);
				}
				else
				{
					if (!string.IsNullOrEmpty(message))
					{
						ShowWarning(message);
					}
					RebuildList();
				}
			});
		}

		private static void OnDelete()
		{
			if (string.IsNullOrEmpty(model.SelectedKey))
			{
				return;
			}
			if (!model.TryDelete(model.SelectedKey, out var message))
			{
				ShowError(message);
				return;
			}
			if (!string.IsNullOrEmpty(message))
			{
				ShowWarning(message);
			}
			RebuildList();
		}

		private static void BuildTabs()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			float num = 280f;
			for (int i = 0; i < TabNames.Length; i++)
			{
				int index = i;
				ConfigUI.AddButton(body, num, 78f, 170f, TabNames[index], (UnityAction)delegate
				{
					activeTab = index;
					BuildDetail();
				}, 30f);
				num += 176f;
			}
		}

		private static void BuildDetail()
		{
			if ((Object)(object)detailRoot != (Object)null)
			{
				Object.Destroy((Object)(object)detailRoot);
				detailRoot = null;
			}
			if ((Object)(object)body == (Object)null)
			{
				return;
			}
			float num = 700f;
			float num2 = 494f;
			detailRoot = ConfigUI.NewRect("Detail", body, 280f, 116f, num, num2);
			if (string.IsNullOrEmpty(model.SelectedKey) || !model.Levels.TryGetValue(model.SelectedKey, out var value))
			{
				ConfigUI.AddText(detailRoot.transform, 0f, 0f, num, 30f, "$dl_cfg_noselection", 15, (TextAnchor)3);
				return;
			}
			switch (activeTab)
			{
			case 1:
				BuildDeathStyleTab(value, num, num2);
				break;
			case 2:
				BuildResourcesTab(value, num, num2);
				break;
			case 3:
				BuildLootTab(value, num, num2);
				break;
			default:
				BuildGeneralTab(value, num);
				break;
			}
		}

		private static void BuildGeneralTab(DataObjects.DeathChoiceLevel level, float width)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			List<GameObject> list = new List<GameObject>();
			Transform transform = detailRoot.transform;
			list.Add(ConfigUI.AddTextRow(transform, width, 26f, ConfigUI.L("$dl_cfg_key") + ": " + model.SelectedKey, 14, GUIManager.Instance.ValheimOrange, (TextAnchor)0));
			list.Add(ConfigUI.AddTextFieldRow(transform, width, 230f, 300f, "$dl_cfg_displayname", level.DisplayName, delegate(string s)
			{
				level.DisplayName = s;
			}, null, 64));
			list.Add(ConfigUI.AddToggleRow(transform, width, 230f, "$dl_cfg_fallback", level.Fallback, delegate(bool on)
			{
				if (on)
				{
					model.SetFallback(model.SelectedKey);
				}
				else
				{
					level.Fallback = false;
				}
				BuildDetail();
			}));
			list.Add(ConfigUI.AddSliderRow(transform, width, 230f, 230f, 60f, "$dl_cfg_deathskillrate", 0f, 10f, level.DeathSkillRate, wholeNumbers: false, delegate(float v)
			{
				level.DeathSkillRate = v;
			}));
			list.Add(ConfigUI.AddSliderRow(transform, width, 230f, 230f, 60f, "$dl_cfg_damagetaken", 0f, 3f, level.DamageTakenModifier, wholeNumbers: false, delegate(float v)
			{
				level.DamageTakenModifier = v;
			}));
			list.Add(ConfigUI.AddSliderRow(transform, width, 230f, 230f, 60f, "$dl_cfg_damagedone", 0f, 3f, level.DamageDoneModifier, wholeNumbers: false, delegate(float v)
			{
				level.DamageDoneModifier = v;
			}));
			ConfigUI.LayoutColumn(list, 0f, 0f);
		}

		private static void BuildDeathStyleTab(DataObjects.DeathChoiceLevel level, float width, float height)
		{
			if (level.DeathStyle == null)
			{
				level.DeathStyle = new DataObjects.DeathProgressionDetails();
			}
			DataObjects.DeathProgressionDetails style = level.DeathStyle;
			ConfigUI.CreateScroll(detailRoot.transform, 0f, 0f, width, height, out var content, out var contentWidth);
			if ((Object)(object)content == (Object)null)
			{
				return;
			}
			AddScrollEnumCycle(content, contentWidth, "$dl_cfg_itemlossstyle", Enum.GetNames(typeof(DataObjects.ItemLossStyle)), (int)style.itemLossStyle, delegate(int i)
			{
				style.itemLossStyle = (DataObjects.ItemLossStyle)i;
				BuildDetail();
			});
			if (style.itemLossStyle != DataObjects.ItemLossStyle.DestroyAll)
			{
				AddScrollEnumCycle(content, contentWidth, "$dl_cfg_itemsavedstyle", Enum.GetNames(typeof(DataObjects.ItemSavedStyle)), (int)style.itemSavedStyle, delegate(int i)
				{
					style.itemSavedStyle = (DataObjects.ItemSavedStyle)i;
				});
				AddScrollEnumCycle(content, contentWidth, "$dl_cfg_nonskillchecked", Enum.GetNames(typeof(DataObjects.NonSkillCheckedItemAction)), (int)style.nonSkillCheckedItemAction, delegate(int i)
				{
					style.nonSkillCheckedItemAction = (DataObjects.NonSkillCheckedItemAction)i;
				});
				AddScrollToggle(content, contentWidth, "$dl_cfg_enablesavingchoices", style.EnableItemSavingChoices, delegate(bool v)
				{
					style.EnableItemSavingChoices = v;
				});
			}
			if (style.itemLossStyle == DataObjects.ItemLossStyle.DeathlinkBased)
			{
				AddScrollHeader(content, contentWidth, "$dl_cfg_keepbudget");
				AddScrollSlider(content, contentWidth, "$dl_cfg_minitems", 0f, 64f, style.minItemsKept, whole: true, delegate(float v)
				{
					style.minItemsKept = (int)v;
				});
				AddScrollSlider(content, contentWidth, "$dl_cfg_maxitems", 0f, 64f, style.maxItemsKept, whole: true, delegate(float v)
				{
					style.maxItemsKept = (int)v;
				});
				AddScrollSlider(content, contentWidth, "$dl_cfg_minequip", 0f, 16f, style.minEquipmentKept, whole: true, delegate(float v)
				{
					style.minEquipmentKept = (int)v;
				});
				AddScrollSlider(content, contentWidth, "$dl_cfg_maxequip", 0f, 16f, style.maxEquipmentKept, whole: true, delegate(float v)
				{
					style.maxEquipmentKept = (int)v;
				});
				AddScrollSlider(content, contentWidth, "$dl_cfg_minchoices", 0f, 16f, style.minItemsKeptChoices, whole: true, delegate(float v)
				{
					style.minItemsKeptChoices = (int)v;
				});
				AddScrollSlider(content, contentWidth, "$dl_cfg_maxchoices", 0f, 16f, style.maxItemsKeptChoices, whole: true, delegate(float v)
				{
					style.maxItemsKeptChoices = (int)v;
				});
			}
			AddScrollHeader(content, contentWidth, "$dl_cfg_skillloss");
			AddScrollToggle(content, contentWidth, "$dl_cfg_skilllossondeath", style.skillLossOnDeath, delegate(bool v)
			{
				style.skillLossOnDeath = v;
			});
			if (style.skillLossOnDeath)
			{
				AddScrollSlider(content, contentWidth, "$dl_cfg_minskillloss", 0f, 1f, style.minSkillLossPercentage, whole: false, delegate(float v)
				{
					style.minSkillLossPercentage = v;
				});
				AddScrollSlider(content, contentWidth, "$dl_cfg_maxskillloss", 0f, 1f, style.maxSkillLossPercentage, whole: false, delegate(float v)
				{
					style.maxSkillLossPercentage = v;
				});
			}
			AddScrollHeader(content, contentWidth, "$dl_cfg_food");
			AddScrollToggle(content, contentWidth, "$dl_cfg_foodloss", style.foodLossOnDeath, delegate(bool v)
			{
				style.foodLossOnDeath = v;
				BuildDetail();
			});
			if (style.foodLossOnDeath)
			{
				AddScrollToggle(content, contentWidth, "$dl_cfg_fooddeathlink", style.foodLossUsesDeathlink, delegate(bool v)
				{
					style.foodLossUsesDeathlink = v;
				});
			}
		}

		private static void BuildResourcesTab(DataObjects.DeathChoiceLevel level, float width, float height)
		{
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			ConfigUI.CreateScroll(detailRoot.transform, 0f, 0f, width, height, out var content, out var contentWidth);
			if ((Object)(object)content == (Object)null)
			{
				return;
			}
			if (level.ResourceModifiers == null)
			{
				level.ResourceModifiers = new Dictionary<string, DataObjects.DeathResourceModifier>();
			}
			if (level.SkillModifiers == null)
			{
				level.SkillModifiers = new Dictionary<string, DataObjects.DeathSkillModifier>();
			}
			AddScrollHeader(content, contentWidth, "$dl_cfg_resourcemods");
			foreach (KeyValuePair<string, DataObjects.DeathResourceModifier> item in new List<KeyValuePair<string, DataObjects.DeathResourceModifier>>(level.ResourceModifiers))
			{
				string entryKey = item.Key;
				DataObjects.DeathResourceModifier modifier = item.Value;
				if (modifier != null)
				{
					AddEntryHeader(content, contentWidth, entryKey, delegate
					{
						level.ResourceModifiers.Remove(entryKey);
						BuildDetail();
					});
					AddScrollSlider(content, contentWidth, "$dl_cfg_bonusmodifier", 0f, 5f, modifier.BonusModifier, whole: false, delegate(float v)
					{
						modifier.BonusModifier = v;
					});
					AddScrollToggle(content, contentWidth, "$dl_cfg_skillinfluence", modifier.skillInfluence, delegate(bool v)
					{
						modifier.skillInfluence = v;
					});
					AddBonusActions(content, contentWidth, modifier.bonusActions);
					if (modifier.prefabs == null)
					{
						modifier.prefabs = new List<string>();
					}
					ConfigUI.AddStringListEditor(content, contentWidth, "$dl_cfg_prefabs", modifier.prefabs, BuildDetail, PrefabNames, IsKnownPrefab);
				}
			}
			AddAddButton(content, contentWidth, "$dl_cfg_addresource", delegate
			{
				level.ResourceModifiers[UniqueEntryKey(level.ResourceModifiers.Keys, "NewResource")] = new DataObjects.DeathResourceModifier
				{
					BonusModifier = 1f,
					prefabs = new List<string>()
				};
				BuildDetail();
			});
			AddScrollHeader(content, contentWidth, "$dl_cfg_skillmods");
			foreach (KeyValuePair<string, DataObjects.DeathSkillModifier> item2 in new List<KeyValuePair<string, DataObjects.DeathSkillModifier>>(level.SkillModifiers))
			{
				string entryKey2 = item2.Key;
				DataObjects.DeathSkillModifier modifier2 = item2.Value;
				if (modifier2 == null)
				{
					continue;
				}
				AddEntryHeader(content, contentWidth, entryKey2, delegate
				{
					level.SkillModifiers.Remove(entryKey2);
					BuildDetail();
				});
				AddScrollPicker(content, contentWidth, "$dl_cfg_skill", ((object)modifier2.skill/*cast due to .constrained prefix*/).ToString(), SkillNames, delegate(string s)
				{
					//IL_0029: Unknown result type (might be due to invalid IL or missing references)
					if (Enum.IsDefined(typeof(SkillType), s))
					{
						modifier2.skill = (SkillType)Enum.Parse(typeof(SkillType), s, ignoreCase: true);
					}
				}, IsKnownSkill);
				AddScrollSlider(content, contentWidth, "$dl_cfg_bonusmodifier", 0f, 5f, modifier2.BonusModifier, whole: false, delegate(float v)
				{
					modifier2.BonusModifier = v;
				});
				AddScrollToggle(content, contentWidth, "$dl_cfg_skillinfluence", modifier2.skillInfluence, delegate(bool v)
				{
					modifier2.skillInfluence = v;
				});
			}
			AddAddButton(content, contentWidth, "$dl_cfg_addskill", delegate
			{
				level.SkillModifiers[UniqueEntryKey(level.SkillModifiers.Keys, "NewSkill")] = new DataObjects.DeathSkillModifier
				{
					BonusModifier = 1f,
					skill = (SkillType)999
				};
				BuildDetail();
			});
		}

		private static void BuildLootTab(DataObjects.DeathChoiceLevel level, float width, float height)
		{
			ConfigUI.CreateScroll(detailRoot.transform, 0f, 0f, width, height, out var content, out var contentWidth);
			if ((Object)(object)content == (Object)null)
			{
				return;
			}
			if (level.DeathLootModifiers == null)
			{
				level.DeathLootModifiers = new Dictionary<string, DataObjects.DeathLootModifier>();
			}
			AddScrollHeader(content, contentWidth, "$dl_cfg_lootmods");
			foreach (KeyValuePair<string, DataObjects.DeathLootModifier> item in new List<KeyValuePair<string, DataObjects.DeathLootModifier>>(level.DeathLootModifiers))
			{
				string entryKey = item.Key;
				DataObjects.DeathLootModifier modifier = item.Value;
				if (modifier != null)
				{
					AddEntryHeader(content, contentWidth, entryKey, delegate
					{
						level.DeathLootModifiers.Remove(entryKey);
						BuildDetail();
					});
					AddScrollPicker(content, contentWidth, "$dl_cfg_prefab", modifier.prefab, PrefabNames, delegate(string s)
					{
						modifier.prefab = s;
					}, IsKnownPrefab);
					AddScrollSlider(content, contentWidth, "$dl_cfg_chance", 0f, 1f, modifier.chance, whole: false, delegate(float v)
					{
						modifier.chance = v;
					});
					AddScrollSlider(content, contentWidth, "$dl_cfg_amount", 1f, 100f, modifier.amount, whole: true, delegate(float v)
					{
						modifier.amount = (int)v;
					});
					AddBonusActions(content, contentWidth, modifier.bonusActions);
				}
			}
			AddAddButton(content, contentWidth, "$dl_cfg_addloot", delegate
			{
				level.DeathLootModifiers[UniqueEntryKey(level.DeathLootModifiers.Keys, "NewLoot")] = new DataObjects.DeathLootModifier
				{
					chance = 0.05f,
					amount = 1,
					bonusActions = new List<DataObjects.ResourceGainTypes>()
				};
				BuildDetail();
			});
		}

		private static void AddScrollHeader(Transform content, float w, string label)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ConfigUI.NewLayoutRow(content, w, 34f);
			ConfigUI.AddText(val.transform, 0f, 0f, w, 34f, label, 16, (TextAnchor)3, GUIManager.Instance.ValheimYellow);
		}

		private static void AddEntryHeader(Transform content, float w, string entryKey, Action onDelete)
		{
			//IL_003f: 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_0081: Expected O, but got Unknown
			GameObject val = ConfigUI.NewLayoutRow(content, w, 34f);
			ConfigUI.AddText(val.transform, 8f, 0f, w - 110f, 34f, entryKey, 15, (TextAnchor)3, GUIManager.Instance.ValheimOrange);
			ConfigUI.AddButton(val.transform, w - 96f, 2f, 92f, "$dl_cfg_deleteentry", (UnityAction)delegate
			{
				onDelete();
			}, 28f);
		}

		private static void AddAddButton(Transform content, float w, string label, Action onAdd)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			GameObject val = ConfigUI.NewLayoutRow(content, w, 34f);
			ConfigUI.AddButton(val.transform, 8f, 2f, 220f, label, (UnityAction)delegate
			{
				onAdd();
			}, 28f);
		}

		private static void AddScrollToggle(Transform content, float w, string label, bool value, Action<bool> onChange)
		{
			GameObject val = ConfigUI.NewLayoutRow(content, w, 34f);
			ConfigUI.AddText(val.transform, 8f, 0f, 230f, 34f, label, 15, (TextAnchor)3);
			ConfigUI.AddToggle(val.transform, 244f, 4f, 24f, value, onChange);
		}

		private static void AddScrollSlider(Transform content, float w, string label, float min, float max, float value, bool whole, Action<float> onChange)
		{
			GameObject val = ConfigUI.NewLayoutRow(content, w, 34f);
			ConfigUI.AddText(val.transform, 8f, 0f, 230f, 34f, label, 15, (TextAnchor)3);
			Slider slider = ConfigUI.BuildSlider(val.transform, 244f, 7f, 220f, min, max, value, whole);
			float x = 474f;
			InputField box = ConfigUI.AddTextField(val.transform, x, 3f, 66f, ConfigUI.Fmt(value, whole), null, (ContentType)(whole ? 2 : 3));
			((UnityEvent<float>)(object)slider.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
			{
				if (whole)
				{
					v = Mathf.Round(v);
				}
				box.SetTextWithoutNotify(ConfigUI.Fmt(v, whole));
				onChange(v);
			});
			((UnityEvent<string>)(object)box.onEndEdit).AddListener((UnityAction<string>)delegate(string str)
			{
				if (!float.TryParse(str, out var result))
				{
					result = slider.value;
				}
				result = Mathf.Clamp(result, min, max);
				if (whole)
				{
					result = Mathf.Round(result);
				}
				box.SetTextWithoutNotify(ConfigUI.Fmt(result, whole));
				if (slider.value != result)
				{
					slider.value = result;
				}
				else
				{
					onChange(result);
				}
			});
		}

		private static void AddScrollEnumCycle(Transform content, float w, string label, string[] options, int current, Action<int> onChange)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			GameObject val = ConfigUI.NewLayoutRow(content, w, 34f);
			ConfigUI.AddText(val.transform, 8f, 0f, 230f, 34f, label, 15, (TextAnchor)3);
			int idx = Mathf.Clamp(current, 0, Math.Max(0, options.Length - 1));
			GameObject val2 = ConfigUI.AddButton(val.transform, 244f, 2f, 210f, (options.Length != 0) ? options[idx] : "", null, 28f);
			Text caption = val2.GetComponentInChildren<Text>();
			((UnityEvent)val2.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				if (options.Length != 0)
				{
					idx = (idx + 1) % options.Length;
					caption.text = options[idx];
					onChange(idx);
				}
			});
		}

		private static void AddScrollPicker(Transform content, float w, string label, string current, Func<IList<string>> options, Action<string> onPick, Func<string, bool> isKnown)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			GameObject val = ConfigUI.NewLayoutRow(content, w, 34f);
			ConfigUI.AddText(val.transform, 8f, 0f, 230f, 34f, label, 15, (TextAnchor)3);
			InputField field = ConfigUI.AddTextField(val.transform, 244f, 3f, 220f, current, onPick, (ContentType)0);
			Text marker = ConfigUI.AddText(val.transform, 508f, 0f, 20f, 34f, "", 15, (TextAnchor)3, (Color?)new Color(0.98f, 0.75f, 0.14f));
			Action refresh = delegate
			{
				bool flag = !string.IsNullOrEmpty(field.text) && !isKnown(field.text);
				marker.text = (flag ? "!" : "");
			};
			refresh();
			((UnityEvent<string>)(object)field.onEndEdit).AddListener((UnityAction<string>)delegate
			{
				refresh();
			});
			ConfigUI.AddButton(val.transform, 470f, 3f, 34f, "...", (UnityAction)delegate
			{
				ConfigUIPicker.ShowPicker(label, options(), field.text, delegate(string picked)
				{
					field.SetTextWithoutNotify(picked);
					refresh();
					onPick(picked);
				});
			}, 28f);
		}

		private static void AddBonusActions(Transform content, float w, List<DataObjects.ResourceGainTypes> actions)
		{
			if (actions == null)
			{
				return;
			}
			GameObject val = ConfigUI.NewLayoutRow(content, w, 34f);
			ConfigUI.AddText(val.transform, 8f, 0f, 230f, 34f, "$dl_cfg_bonusactions", 15, (TextAnchor)3);
			string[] names = Enum.GetNames(typeof(DataObjects.ResourceGainTypes));
			float num = 244f;
			for (int i = 0; i < names.Length; i++)
			{
				DataObjects.ResourceGainTypes value = (DataObjects.ResourceGainTypes)Enum.Parse(typeof(DataObjects.ResourceGainTypes), names[i]);
				ConfigUI.AddToggle(val.transform, num, 4f, 22f, actions.Contains(value), delegate(bool on)
				{
					if (on)
					{
						if (!actions.Contains(value))
						{
							actions.Add(value);
						}
					}
					else
					{
						actions.Remove(value);
					}
				});
				ConfigUI.AddText(val.transform, num + 26f, 0f, 100f, 34f, names[i], 13, (TextAnchor)3);
				num += 130f;
			}
		}

		private static void RunValidate()
		{
			if (model != null)
			{
				ValidationReport validationReport = model.Validate();
				if (validationReport.Errors.Count == 0 && validationReport.Warnings.Count == 0)
				{
					messages.text = ConfigUI.L("$dl_cfg_looksgood");
				}
				else
				{
					ConfigUI.SetMessages(messages, validationReport.Errors, validationReport.Warnings);
				}
			}
		}

		private static void ApplyAndSave()
		{
			if (model == null || awaitingServer)
			{
				return;
			}
			try
			{
				ValidationReport validationReport = model.Validate();
				if (validationReport.HasErrors)
				{
					ConfigUI.SetMessages(messages, validationReport.Errors, validationReport.Warnings);
					return;
				}
				YamlConfigFile<Dictionary<string, DataObjects.DeathChoiceLevel>> deathChoices = YamlConfigManager.DeathChoices;
				if (deathChoices != null && deathChoices.LastLoadedUtc != model.BaseLoadedUtc)
				{
					model.BaseLoadedUtc = deathChoices.LastLoadedUtc;
					ShowWarning(ConfigUI.L("$dl_cfg_changedunderneath"));
					return;
				}
				string yaml = model.Serialize();
				if (IsOwner())
				{
					if (!YamlConfigManager.ApplyEdited(deathChoices, yaml, out var message))
					{
						ShowError(message);
						return;
					}
					if (!string.IsNullOrEmpty(message))
					{
						Logger.LogWarning(message);
					}
					ClosePanel();
					return;
				}
				if (!ConfigNetwork.RequestEdit(deathChoices, yaml, out var refusal))
				{
					ShowError(refusal);
					return;
				}
				awaitingServer = true;
				sentAtTime = Time.realtimeSinceStartup;
				messages.text = ConfigUI.L("$dl_cfg_sent");
				ThreadingHelper instance = ThreadingHelper.Instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(AwaitServerReply());
				}
			}
			catch (Exception ex)
			{
				Logger.LogError($"Death choice editor failed to apply: {ex}");
				ShowError(ex.Message);
			}
		}

		private static IEnumerator AwaitServerReply()
		{
			while (awaitingServer && Time.realtimeSinceStartup - sentAtTime < 10f)
			{
				yield return null;
			}
			if (awaitingServer)
			{
				awaitingServer = false;
				ShowError(ConfigUI.L("$dl_cfg_noreply"));
			}
		}

		private static void OnEditResult(YamlConfigFile file, bool accepted, string message)
		{
			if (!awaitingServer || file != YamlConfigManager.DeathChoices)
			{
				return;
			}
			awaitingServer = false;
			if (!accepted)
			{
				ShowError(message);
				return;
			}
			if (!string.IsNullOrEmpty(message))
			{
				Logger.LogWarning(message);
			}
			ClosePanel();
		}

		private static void ShowError(string message)
		{
			ConfigUI.SetMessages(messages, new List<string> { message }, null);
		}

		private static void ShowWarning(string message)
		{
			ConfigUI.SetMessages(messages, null, new List<string> { message });
		}

		private static IList<string> PrefabNames()
		{
			List<string> list = new List<string>();
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return list;
			}
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				if ((Object)(object)prefab != (Object)null)
				{
					list.Add(((Object)prefab).name);
				}
			}
			return list;
		}

		private static bool IsKnownPrefab(string name)
		{
			if (!Utils.PrefabsAvailable())
			{
				return true;
			}
			return (Object)(object)PrefabManager.Instance.GetPrefab(name) != (Object)null;
		}

		private static IList<string> SkillNames()
		{
			//IL_000b: 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)
			List<string> list = new List<string> { ((object)(SkillType)999/*cast due to .constrained prefix*/).ToString() };
			string[] names = Enum.GetNames(typeof(SkillType));
			foreach (string text in names)
			{
				if (!(text == ((object)(SkillType)999/*cast due to .constrained prefix*/).ToString()))
				{
					list.Add(text);
				}
			}
			return list;
		}

		private static bool IsKnownSkill(string name)
		{
			return Enum.IsDefined(typeof(SkillType), name);
		}

		private static string UniqueEntryKey(ICollection<string> existing, string candidate)
		{
			if (!existing.Contains(candidate))
			{
				return candidate;
			}
			for (int i = 2; i < 1000; i++)
			{
				if (!existing.Contains(candidate + i))
				{
					return candidate + i;
				}
			}
			return candidate + Guid.NewGuid().ToString("N").Substring(0, 4);
		}
	}
	internal sealed class DeathChoiceEditorModel
	{
		internal Dictionary<string, DataObjects.DeathChoiceLevel> Levels = new Dictionary<string, DataObjects.DeathChoiceLevel>();

		internal List<string> Order = new List<string>();

		internal string SelectedKey;

		internal DateTime BaseLoadedUtc;

		private static YamlFormat Format
		{
			get
			{
				YamlConfigFile<Dictionary<string, DataObjects.DeathChoiceLevel>> deathChoices = YamlConfigManager.DeathChoices;
				if (deathChoices == null)
				{
					return YamlFormat.Default;
				}
				return deathChoices.EffectiveFormat;
			}
		}

		internal static DeathChoiceEditorModel Snapshot()
		{
			DeathChoiceEditorModel deathChoiceEditorModel = new DeathChoiceEditorModel();
			YamlConfigFile<Dictionary<string, DataObjects.DeathChoiceLevel>> deathChoices = YamlConfigManager.DeathChoices;
			Dictionary<string, DataObjects.DeathChoiceLevel> dictionary = null;
			if (deathChoices != null && deathChoices.Value != null)
			{
				try
				{
					YamlFormat effectiveFormat = deathChoices.EffectiveFormat;
					dictionary = effectiveFormat.Deserializer.Deserialize<Dictionary<string, DataObjects.DeathChoiceLevel>>(effectiveFormat.Serializer.Serialize((object)deathChoices.Value));
				}
				catch (Exception ex)
				{
					Logger.LogError("Could not copy the death levels for editing: " + ex.Message);
				}
			}
			deathChoiceEditorModel.Levels = dictionary ?? new Dictionary<string, DataObjects.DeathChoiceLevel>();
			deathChoiceEditorModel.Order = new List<string>(deathChoiceEditorModel.Levels.Keys);
			deathChoiceEditorModel.SelectedKey = ((deathChoiceEditorModel.Order.Count > 0) ? deathChoiceEditorModel.Order[0] : null);
			deathChoiceEditorModel.BaseLoadedUtc = deathChoices?.LastLoadedUtc ?? DateTime.MinValue;
			return deathChoiceEditorModel;
		}

		internal bool TryAdd(string key, out string message)
		{
			key = (key ?? "").Trim();
			if (!IsUsableKey(key, out message))
			{
				return false;
			}
			if (Levels.ContainsKey(key))
			{
				message = "A level called '" + key + "' already exists.";
				return false;
			}
			Levels[key] = new DataObjects.DeathChoiceLevel
			{
				DisplayName = key,
				DeathStyle = new DataObjects.DeathProgressionDetails()
			};
			Order.Add(key);
			SelectedKey = key;
			message = NearMatchWarning(key);
			return true;
		}

		internal bool TryRename(string oldKey, string newKey, out string message)
		{
			message = null;
			newKey = (newKey ?? "").Trim();
			if (!Levels.ContainsKey(oldKey))
			{
				message = "That level no longer exists.";
				return false;
			}
			if (!IsUsableKey(newKey, out message))
			{
				return false;
			}
			if (string.Equals(oldKey, newKey, StringComparison.Ordinal))
			{
				return true;
			}
			if (Levels.ContainsKey(newKey))
			{
				message = "A level called '" + newKey + "' already exists.";
				return false;
			}
			DataObjects.DeathChoiceLevel value = Levels[oldKey];
			Levels.Remove(oldKey);
			Levels[newKey] = value;
			int num = Order.IndexOf(oldKey);
			if (num >= 0)
			{
				Order[num] = newKey;
			}
			else
			{
				Order.Add(newKey);
			}
			if (string.Equals(SelectedKey, oldKey, StringComparison.Ordinal))
			{
				SelectedKey = newKey;
			}
			message = NearMatchWarning(newKey);
			return true;
		}

		internal bool TryDelete(string key, out string message)
		{
			message = null;
			if (!Levels.ContainsKey(key))
			{
				message = "That level no longer exists.";
				return false;
			}
			if (Levels.Count <= 1)
			{
				message = "There has to be at least one death level.";
				return false;
			}
			bool fallback = Levels[key].Fallback;
			Levels.Remove(key);
			Order.Remove(key);
			if (string.Equals(SelectedKey, key, StringComparison.Ordinal))
			{
				SelectedKey = ((Order.Count > 0) ? Order[0] : null);
			}
			if (fallback && Order.Count > 0)
			{
				Levels[Order[0]].Fallback = true;
				message = "'" + key + "' was the fallback level, so '" + Order[0] + "' is now.";
			}
			return true;
		}

		internal string Duplicate(string key)
		{
			if (!Levels.ContainsKey(key))
			{
				return null;
			}
			DataObjects.DeathChoiceLevel deathChoiceLevel;
			try
			{
				YamlFormat format = Format;
				deathChoiceLevel = format.Deserializer.Deserialize<DataObjects.DeathChoiceLevel>(format.Serializer.Serialize((object)Levels[key]));
			}
			catch (Exception ex)
			{
				Logger.LogError("Could not duplicate '" + key + "': " + ex.Message);
				return null;
			}
			if (deathChoiceLevel == null)
			{
				return null;
			}
			deathChoiceLevel.Fallback = false;
			string text = UniqueKey(key + "Copy");
			Levels[text] = deathChoiceLevel;
			int num = Order.IndexOf(key);
			if (num >= 0)
			{
				Order.Insert(num + 1, text);
			}
			else
			{
				Order.Add(text);
			}
			SelectedKey = text;
			return text;
		}

		internal void SetFallback(string key)
		{
			foreach (KeyValuePair<string, DataObjects.DeathChoiceLevel> level in Levels)
			{
				if (level.Value != null)
				{
					level.Value.Fallback = string.Equals(level.Key, key, StringComparison.Ordinal);
				}
			}
		}

		internal string Serialize()
		{
			Dictionary<string, DataObjects.DeathChoiceLevel> dictionary = new Dictionary<string, DataObjects.DeathChoiceLevel>();
			foreach (string item in Order)
			{
				if (Levels.TryGetValue(item, out var value))
				{
					dictionary[item] = value;
				}
			}
			foreach (KeyValuePair<string, DataObjects.DeathChoiceLevel> level in Levels)
			{
				if (!dictionary.ContainsKey(level.Key))
				{
					dictionary[level.Key] = level.Value;
				}
			}
			return YamlConfigManager.SerializeForEdit(YamlConfigManager.DeathChoices, dictionary);
		}

		internal ValidationReport Validate()
		{
			return DeathConfigurationData.ValidateDeathLevels(Levels, DeathConfigurationData.DeathLevels);
		}

		private static bool IsUsableKey(string key, out string message)
		{
			message = null;
			if (string.IsNullOrWhiteSpace(key))
			{
				message = "A level needs a name.";
				return false;
			}
			if (key.IndexOf(':') >= 0 || key.IndexOf('#') >= 0 || key.StartsWith("-"))
			{
				message = "A level name cannot contain ':' or '#', or start with '-'.";
				return false;
			}
			return true;
		}

		private string NearMatchWarning(string key)
		{
			foreach (string item in Order)
			{
				if (!string.Equals(item, key, StringComparison.Ordinal) && string.Equals(item, key, StringComparison.OrdinalIgnoreCase))
				{
					return "'" + key + "' differs from '" + item + "' only by capitalisation. They are two separate levels.";
				}
			}
			return null;
		}

		private string UniqueKey(string candidate)
		{
			if (!Levels.ContainsKey(candidate))
			{
				return candidate;
			}
			for (int i = 2; i < 1000; i++)
			{
				string text = candidate + i;
				if (!Levels.ContainsKey(text))
				{
					return text;
				}
			}
			return candidate + Guid.NewGuid().ToString("N").Substring(0, 4);
		}
	}
	public static class DeathChoiceEnable
	{
		[HarmonyPatch(typeof(InventoryGui), "Show")]
		public static class ShowDeathChoiceUI
		{
			public static void Postfix(InventoryGui __instance)
			{
				if (ValConfig.UsePrivateKeysForDeathChoice.Value)
				{
					if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.PlayerHasUniqueKey(DataObjects.DeathChoiceKey))
					{
						return;
					}
				}
				else if ((Object)(object)Player.m_localPlayer != (Object)null && DeathConfigurationData.playerSettings.ContainsKey(Player.m_localPlayer.GetPlayerID()))
				{
					return;
				}
				DeathChoices.DeathChoiceUI.Instance.Show();
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		public static class HideDeathChoiceUI
		{
			public static void Postfix(InventoryGui __instance)
			{
				if (DeathChoices.DeathChoiceUI.IsInitialized)
				{
					DeathChoices.DeathChoiceUI.Instance.Hide();
				}
			}
		}
	}
	public class DeathChoices
	{
		public class DeathChoiceUI : MonoBehaviour
		{
			private static DeathChoiceUI _instance;

			private static GameObject DeathChoicePanel;

			private static GameObject ChoicesScrollView;

			private static GameObject ChoicesContent;

			private static GameObject ChoicesContainer;

			private static GameObject manualCloseButton;

			private static GameObject selectChoiceButton;

			private static Text DeathPenaltyDescription;

			private static Text CombatModifiersDescription;

			private static Text XPModifiersDescription;

			private static Text LootModifersDescription;

			private static Text HarvestModifiersDescription;

			private static List<Toggle> difficultyToggles = new List<Toggle>();

			private static ToggleGroup choiceGroup;

			private static string selectedDeathChoice = "none";

			private static bool isChangeMode = false;

			public static DeathChoiceUI Instance
			{
				get
				{
					//IL_0012: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Expected O, but got Unknown
					if ((Object)(object)_instance == (Object)null)
					{
						GameObject val = new GameObject("DeathlinkDeathChoiceUI");
						Object.DontDestroyOnLoad((Object)(object)val);
						_instance = val.AddComponent<DeathChoiceUI>();
					}
					return _instance;
				}
			}

			public static bool IsInitialized => (Object)(object)_instance != (Object)null;

			public void Awake()
			{
				_instance = this;
				CreateStaticUIObjects();
				SetChoiceList();
			}

			public void Show()
			{
				if ((Object)(object)DeathChoicePanel == (Object)null)
				{
					CreateStaticUIObjects();
					SetChoiceList();
				}
				DeathChoicePanel.SetActive(true);
			}

			public void ShowForChange()
			{
				isChangeMode = true;
				Show();
			}

			public void Hide()
			{
				if ((Object)(object)DeathChoicePanel != (Object)null)
				{
					DeathChoicePanel.SetActive(false);
				}
				isChangeMode = false;
				GUIManager.BlockInput(false);
			}

			internal void RebuildChoiceList()
			{
				if (!((Object)(object)ChoicesContent == (Object)null))
				{
					SetChoiceList();
				}
			}

			internal static void RefreshIfBuilt()
			{
				if (IsInitialized)
				{
					Instance.RebuildChoiceList();
				}
			}

			public void MakePlayerDeathSelection()
			{
				if ((Object)(object)Player.m_localPlayer == (Object)null)
				{
					Logger.LogWarning("Player not set, ensure the local player is set.");
					return;
				}
				if (selectedDeathChoice == "none")
				{
					Logger.LogWarning("No death type selected");
					return;
				}
				Logger.LogDebug("Player selected death type " + selectedDeathChoice);
				long playerID = Player.m_localPlayer.GetPlayerID();
				if (DeathConfigurationData.playerSettings.ContainsKey(playerID))
				{
					DeathConfigurationData.playerSettings[playerID].DeathChoiceLevel = selectedDeathChoice;
				}
				else
				{
					DeathConfigurationData.playerSettings.Add(playerID, new DataObjects.DeathConfiguration
					{
						DeathChoiceLevel = selectedDeathChoice
					});
				}
				Player.m_localPlayer.PlayerRemoveUniqueKey(DataObjects.DeathChoiceKey);
				Player.m_localPlayer.AddUniqueKeyValue(DataObjects.DeathChoiceKey, selectedDeathChoice);
				if (isChangeMode)
				{
					DeathConfigurationData.IncrementPlayerChangesUsed(Player.m_localPlayer);
				}
				DeathConfigurationData.CheckAndSetPlayerDeathConfig(Player.m_localPlayer);
				DeathConfigurationData.WritePlayerChoices();
				Hide();
			}

			private void SetChoiceList()
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Expected O, but got Unknown
				//IL_012d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0148: Unknown result type (might be due to invalid IL or missing references)
				foreach (Transform item in ChoicesContent.transform)
				{
					Transform val = item;
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				difficultyToggles.Clear();
				int num = -75;
				foreach (KeyValuePair<string, DataObjects.DeathChoiceLevel> entry in DeathConfigurationData.DeathLevels)
				{
					GameObject val2 = Object.Instantiate<GameObject>(ChoicesContainer, ChoicesContent.transform);
					Transform val3 = val2.transform.Find("selecter");
					((Component)val3.Find("Label")).GetComponent<Text>().text = entry.Key;
					((Component)val2.transform.Find("ChoiceName")).GetComponent<Text>().text = entry.Value.DisplayName;
					Toggle component = ((Component)val3).GetComponent<Toggle>();
					component.group = choiceGroup;
					((UnityEvent<bool>)(object)component.onValueChanged).AddListener((UnityAction<bool>)delegate(bool isOn)
					{
						if (isOn)
						{
							((Component)DeathPenaltyDescription).GetComponent<Text>().text = entry.Value.GetDeathStyleDescription();
							((Component)CombatModifiersDescription).GetComponent<Text>().text = entry.Value.GetDamageModifierDescription();
							((Component)XPModifiersDescription).GetComponent<Text>().text = entry.Value.GetSkillModiferDescription();
							((Component)LootModifersDescription).GetComponent<Text>().text = entry.Value.GetLootModifiersDescription();
							((Component)HarvestModifiersDescription).GetComponent<Text>().text = entry.Value.GetResourceModiferDescription();
							selectedDeathChoice = entry.Key;
						}
					});
					val2.SetActive(true);
					val2.transform.localPosition = new Vector3
					{
						x = 5f,
						y = num
					};
					difficultyToggles.Add(component);
					num -= 50;
				}
			}

			private void CreateStaticUIObjects()
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: 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)
				//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_013d: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				//IL_015b: Unknown result type (might be due to invalid IL or missing references)
				//IL_016c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0172: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0223: Unknown result type (might be due to invalid IL or missing references)
				//IL_022d: Expected O, but got Unknown
				//IL_0260: Unknown result type (might be due to invalid IL or missing references)
				//IL_026f: Unknown result type (might be due to invalid IL or missing references)
				//IL_027e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0294: Unknown result type (might be due to invalid IL or missing references)
				//IL_029a: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0303: Unknown result type (might be due to invalid IL or missing references)
				//IL_0314: Unknown result type (might be due to invalid IL or missing references)
				//IL_031a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0388: Unknown result type (might be due to invalid IL or missing references)
				//IL_0397: Unknown result type (might be due to invalid IL or missing references)
				//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_040d: Unknown result type (might be due to invalid IL or missing references)
				//IL_041c: Unknown result type (might be due to invalid IL or missing references)
				//IL_042b: Unknown result type (might be due to invalid IL or missing references)
				//IL_043c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0442: Unknown result type (might be due to invalid IL or missing references)
				//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_0535: Unknown result type (might be due to invalid IL or missing references)
				//IL_0544: Unknown result type (might be due to invalid IL or missing references)
				//IL_0553: Unknown result type (might be due to invalid IL or missing references)
				//IL_0564: Unknown result type (might be due to invalid IL or missing references)
				//IL_056a: Unknown result type (might be due to invalid IL or missing references)
				//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_060c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0612: Unknown result type (might be due to invalid IL or missing references)
				//IL_065d: Unknown result type (might be due to invalid IL or missing references)
				//IL_066c: Unknown result type (might be due to invalid IL or missing references)
				//IL_067b: Unknown result type (might be due to invalid IL or missing references)
				//IL_068c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0692: Unknown result type (might be due to invalid IL or missing references)
				//IL_0700: Unknown result type (might be due to invalid IL or missing references)
				//IL_070f: Unknown result type (might be due to invalid IL or missing references)
				//IL_071e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0734: Unknown result type (might be due to invalid IL or missing references)
				//IL_073a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0785: Unknown result type (might be due to invalid IL or missing references)
				//IL_0794: Unknown result type (might be due to invalid IL or missing references)
				//IL_07a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_07b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_07ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_0828: Unknown result type (might be due to invalid IL or missing references)
				//IL_0837: Unknown result type (might be due to invalid IL or missing references)
				//IL_0846: Unknown result type (might be due to invalid IL or missing references)
				//IL_0879: Unknown result type (might be due to invalid IL or missing references)
				//IL_0883: Expected O, but got Unknown
				//IL_08ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_08b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_08d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_08f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_08f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0947: Unknown result type (might be due to invalid IL or missing references)
				//IL_095b: Expected O, but got Unknown
				//IL_0992: Unknown result type (might be due to invalid IL or missing references)
				//IL_09f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_09f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a52: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a61: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a70: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a86: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a8c: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)DeathChoicePanel != (Object)null))
				{
					if (GUIManager.Instance == null || !Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront))
					{
						Logger.LogWarning("GUIManager not setup, skipping static object creation.");
						return;
					}
					Logger.LogDebug("Creating static UI");
					DeathChoicePanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 800f, 960f, true);
					DeathChoicePanel.SetActive(false);
					GameObject val = GUIManager.Instance.CreateText(Localization.instance.Localize("$selection_header"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(50f, 430f), GUIManager.Instance.AveriaSerifBold, 30, GUIManager.Instance.ValheimOrange, true, Color.black, 350f, 40f, false);
					((Object)val).name = "DLHeader";
					GameObject val2 = GUIManager.Instance.CreateText(Localization.instance.Localize("$selection_description"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 380f), GUIManager.Instance.AveriaSerif, 20, Color.white, true, Color.black, 560f, 60f, false);
					Text component = val2.GetComponent<Text>();
					component.resizeTextForBestFit = true;
					component.resizeTextMaxSize = 20;
					component.alignment = (TextAnchor)4;
					manualCloseButton = GUIManager.Instance.CreateButton(Localization.instance.Localize("$close"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(360f, 430f), 60f, 60f);
					Button component2 = manualCloseButton.GetComponent<Button>();
					((Selectable)component2).interactable = true;
					((UnityEvent)component2.onClick).AddListener(new UnityAction(Hide));
					manualCloseButton.SetActive(true);
					GameObject val3 = GUIManager.Instance.CreateText(Localization.instance.Localize("$death_penalty_header"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(100f, 330f), GUIManager.Instance.AveriaSerifBold, 22, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false);
					((Object)val3).name = "DeathPenaltyTitle";
					GameObject val4 = GUIManager.Instance.CreateText(Localization.instance.Localize("$death_penalty_description"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(147f, 240f), GUIManager.Instance.AveriaSerifBold, 18, Color.white, true, Color.black, 490f, 160f, false);
					((Object)val4).name = "DeathPenaltyDesc";
					DeathPenaltyDescription = val4.GetComponent<Text>();
					DeathPenaltyDescription.resizeTextForBestFit = true;
					DeathPenaltyDescription.resizeTextMaxSize = 18;
					GameObject val5 = GUIManager.Instance.CreateText(Localization.instance.Localize("$combat_header"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(100f, 150f), GUIManager.Instance.AveriaSerifBold, 22, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false);
					((Object)val5).name = "combatModifiersTitle";
					GameObject val6 = GUIManager.Instance.CreateText(Localization.instance.Localize("$combat_modifier_description"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(150f, 80f), GUIManager.Instance.AveriaSerifBold, 16, Color.white, true, Color.black, 500f, 100f, false);
					((Object)val6).name = "combatModifiersDesc";
					CombatModifiersDescription = val6.GetComponent<Text>();
					CombatModifiersDescription.resizeTextForBestFit = true;
					CombatModifiersDescription.resizeTextMaxSize = 18;
					GameObject val7 = GUIManager.Instance.CreateText(Localization.instance.Localize("$xp_header"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(100f, 30f), GUIManager.Instance.AveriaSerifBold, 22, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false);
					((Object)val7).name = "xpModifiersTitle";
					GameObject val8 = GUIManager.Instance.CreateText(Localization.instance.Localize("$xp_mod_description"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(150f, -80f), GUIManager.Instance.AveriaSerifBold, 16, Color.white, true, Color.black, 500f, 200f, false);
					((Object)val8).name = "xpModifiersDesc";
					XPModifiersDescription = val8.GetComponent<Text>();
					XPModifiersDescription.resizeTextForBestFit = true;
					XPModifiersDescription.resizeTextMaxSize = 18;
					GameObject val9 = GUIManager.Instance.CreateText(Localization.instance.Localize("$loot_header"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(100f, -130f), GUIManager.Instance.AveriaSerifBold, 22, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false);
					((Object)val9).name = "lootModifiersTitle";
					GameObject val10 = GUIManager.Instance.CreateText(Localization.instance.Localize("$loot_modifier_description"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(150f, -240f), GUIManager.Instance.AveriaSerifBold, 16, Color.white, true, Color.black, 500f, 200f, false);
					((Object)val10).name = "lootModifersDesc";
					LootModifersDescription = val10.GetComponent<Text>();
					LootModifersDescription.resizeTextForBestFit = true;
					LootModifersDescription.resizeTextMaxSize = 18;
					GameObject val11 = GUIManager.Instance.CreateText(Localization.instance.Localize("$harvest_header"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(100f, -260f), GUIManager.Instance.AveriaSerifBold, 22, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false);
					((Object)val11).name = "harvestModifiersTitle";
					GameObject val12 = GUIManager.Instance.CreateText(Localization.instance.Localize("$harvest_modifier_description"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(150f, -370f), GUIManager.Instance.AveriaSerifBold, 16, Color.white, true, Color.black, 500f, 200f, false);
					((Object)val12).name = "harvestModifersDesc";
					HarvestModifiersDescription = val12.GetComponent<Text>();
					HarvestModifiersDescription.resizeTextForBestFit = true;
					HarvestModifiersDescription.resizeTextMaxSize = 18;
					selectChoiceButton = GUIManager.Instance.CreateButton(Localization.instance.Localize("$deathchoice_select"), DeathChoicePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-240f, -290f), 200f, 80f);
					Button component3 = selectChoiceButton.GetComponent<Button>();
					((UnityEvent)component3.onClick).AddListener(new UnityAction(MakePlayerDeathSelection));
					Logger.LogDebug("Setting up scroll entry");
					ChoicesScrollView = GUIManager.Instance.CreateScrollView(DeathChoicePanel.transform, false, true, 10f, 10f, GUIManager.Instance.ValheimScrollbarHandleColorBlock, Color.grey, 250f, 400f);
					ChoicesScrollView.transform.localPosition = Vector2.op_Implicit(new Vector2
					{
						x = -260f,
						y = -30f
					});
					ChoicesContent = ((Component)ChoicesScrollView.GetComponentInChildren<ContentSizeFitter>()).gameObject;
					ChoicesScrollView.GetComponentInChildren<ScrollRect>().scrollSensitivity = 200f;
					choiceGroup = ChoicesContent.AddComponent<ToggleGroup>();
					Logger.LogDebug("Setting up death choice template entry");
					ChoicesContainer = Object.Instantiate<GameObject>(new GameObject("DeathChoice"), DeathChoicePanel.transform);
					RectTransform val13 = ChoicesContainer.AddComponent<RectTransform>();
					val13.SetSizeWithCurrentAnchors((Axis)0, 100f);
					val13.SetSizeWithCurrentAnchors((Axis)1, 50f);
					((Transform)val13).position = new Vector3(0f, 0f);
					LayoutElement val14 = ChoicesContainer.AddComponent<LayoutElement>();
					val14.minHeight = 50f;
					ChoicesContainer.SetActive(false);
					GameObject val15 = GUIManager.Instance.CreateToggle(ChoicesContainer.transform, 40f, 40f);
					val15.transform.localPosition = Vector2.op_Implicit(new Vector2(10f, 0f));
					((Object)val15).name = "selecter";
					((Component)val15.transform.Find("Label")).gameObject.SetActive(false);
					val15.GetComponent<Toggle>().isOn = false;
					GameObject val16 = GUIManager.Instance.CreateText("Name", ChoicesContainer.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(200f, 0f), GUIManager.Instance.AveriaSerifBold, 20, GUIManager.Instance.ValheimYellow, true, Color.black, 350f, 40f, false);
					((Object)val16).name = "ChoiceName";
				}
			}
		}
	}
	public static class DeathProgressionSkill
	{
		[HarmonyPatch(typeof(Player), "RaiseSkill")]
		public class Deathskill_EXP_Patch
		{
			public static void Postfix(Player __instance)
			{
				//IL_0384: Unknown result type (might be due to invalid IL or missing references)
				timeSinceGameStart += Time.deltaTime;
				if (lastSkillIncreaseTickTime == 0f)
				{
					lastSkillIncreaseTickTime = timeSinceGameStart + ValConfig.SkillProgressUpdateCheckInterval.Value;
					PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
					Dictionary<PlayerStatType, float> stats = playerProfile.m_playerStats[0].m_stats;
					_bossKills = stats[(PlayerStatType)85];
					_enemykills = stats[(PlayerStatType)6];
					_piecesBuilt = stats[(PlayerStatType)2];
					_treesChopped = stats[(PlayerStatType)27];
					_mineAmount = stats[(PlayerStatType)38];
					_craftAndUpgrades = stats[(PlayerStatType)1];
				}
				if (timeSinceGameStart > lastSkillIncreaseTickTime)
				{
					lastSkillIncreaseTickTime = timeSinceGameStart + ValConfig.SkillProgressUpdateCheckInterval.Value;
					PlayerProfile playerProfile2 = Game.instance.GetPlayerProfile();
					Dictionary<PlayerStatType, float> stats2 = playerProfile2.m_playerStats[0].m_stats;
					float num = stats2[(PlayerStatType)85];
					float num2 = stats2[(PlayerStatType)6];
					float num3 = stats2[(PlayerStatType)2];
					float num4 = stats2[(PlayerStatType)27];
					float num5 = stats2[(PlayerStatType)38];
					float num6 = stats2[(PlayerStatType)1];
					float num7 = 0f;
					float num8 = 0f;
					float num9 = 0f;
					float num10 = 0f;
					float num11 = 0f;
					float num12 = 0f;
					if (num > _bossKills || num2 > _enemykills)
					{
						num12 = (num - _bossKills) * ValConfig.SkillGainOnBossKills.Value;
						num11 = (num2 - _enemykills) * ValConfig.SkillGainOnKills.Value;
						Logger.LogDebug($"DeathProgression kill skill bosskill: {num12} kill: {num11}");
						_bossKills = num;
						_enemykills = num2;
					}
					if (num3 > _piecesBuilt)
					{
						num10 = (num3 - _piecesBuilt) * ValConfig.SkillGainOnBuilding.Value;
						Logger.LogDebug($"DeathProgression building skill: {num10}");
						_piecesBuilt = num3;
					}
					if (num4 > _treesChopped || num5 > _mineAmount)
					{
						num9 = (num4 - _treesChopped) * ValConfig.SkillGainOnResourceGathering.Value;
						num8 = (num5 - _mineAmount) * ValConfig.SkillGainOnResourceGathering.Value;
						Logger.LogDebug($"DeathProgression harvesting skill tree_harvest: {num9} mining: {num8}");
						_treesChopped = num4;
						_mineAmount = num5;
					}
					if (num6 > _craftAndUpgrades)
					{
						num7 = (num6 - _craftAndUpgrades) * ValConfig.SkillGainOnCrafts.Value;
						Logger.LogDebug($"DeathProgression crafting skill crafting: {num7}");
						_craftAndUpgrades = num6;
					}
					float num13 = num12 + num11 + num10 + num9 + num8 + num7;
					float num14 = Mathf.Max(0f, (float)Math.Log(__instance.m_timeSinceDeath) / 5f * 0.5f);
					float num15 = num14 * num13;
					if (Deathlink.RustyAlmanacClassesLoaded)
					{
						int num16 = Mathf.RoundToInt(num15 * ValConfig.AlmanacClassesXPGainScale.Value);
						Logger.LogDebug($"Almanac XP Gain {num16}");
						ClassesAPI.AddEXP(num16);
					}
					if (Deathlink.WackyMMOLoaded)
					{
						int num17 = Mathf.RoundToInt(num15 * ValConfig.WackyMMOXPGainScale.Value);
						Logger.LogDebug($"WackyMMO XP Gain {num17}");
						EpicMMOSystem_API.AddExp(num17);
					}
					float deathSkillRate = Deathlink.pcfg().DeathSkillRate;
					Logger.LogDebug($"DeathProgression skill bonus from survival (survive time: {__instance.m_timeSinceDeath}) {num14} x {num13} = {num15}, death skill rate {deathSkillRate}");
					((Character)Player.m_localPlayer).RaiseSkill(DeathSkill, num15 * deathSkillRate);
				}
			}
		}

		public static SkillType DeathSkill;

		private static float lastSkillIncreaseTickTime;

		private static float timeSinceGameStart;

		private static float _bossKills;

		private static float _enemykills;

		private static float _piecesBuilt;

		private static float _mineAmount;

		private static float _treesChopped;

		private static float _craftAndUpgrades;

		public static void SetupDeathSkill()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			SkillConfig val = new SkillConfig();
			val.Name = LocalizationManager.Instance.TryTranslate("$death_skill");
			val.Description = LocalizationManager.Instance.TryTranslate("$death_skill_description");
			val.Icon = Deathlink.EmbeddedResourceBundle.LoadAsset<Sprite>("Assets/Custom/Icons/death_skill.png");
			val.Identifier = "midnightsfx.deathskill";
			val.IncreaseStep = 0.1f;
			DeathSkill = SkillManager.Instance.AddSkill(val);
			if (!SkillsChanges.skills_to_avoid_standard_death_penalty.Contains(DeathSkill))
			{
				SkillsChanges.skills_to_avoid_standard_death_penalty.Add(DeathSkill);
			}
		}

		public static float DeathSkillCalculatePercentWithBonus(float bonus = 0f, float min = 0.01f, float max = 1f)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor(DeathSkill);
				num += skillFactor;
			}
			num += bonus;
			if (num < min)
			{
				num = min;
			}
			if (num > max)
			{
				num = max;
			}
			return num;
		}
	}
	internal static class DeathSavingOptions
	{
		[HarmonyPatch(typeof(Player), "OnSpawned")]
		public static class Player_OnSpawned_Patch
		{
			public static void Postfix(Player __instance)
			{
				if (pendingChoice && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					((Character)__instance).Message((MessageType)2, Localization.instance.Localize("$dso_spawn_message"), 0, (Sprite)null, false);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Show")]
		public static class ShowSaveChoiceUI
		{
			public static void Postfix()
			{
				if (pendingChoice)
				{
					SaveChoiceUI.Instance.Show(new List<ItemData>(deathItems), totalToSave, maxChoices);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		public static class HideSaveChoiceUI
		{
			public static void Postfix()
			{
				if (SaveChoiceUI.IsInitialized)
				{
					SaveChoiceUI.Instance.Hide();
				}
			}
		}

		public class SaveChoiceUI : MonoBehaviour
		{
			private static SaveChoiceUI _instance;

			private const int GridWidth = 8;

			private static GameObject panel;

			private static Text counterText;

			private static InventoryGrid grid;

			private static RectTransform gridRoot;

			private static Inventory tempInv;

			private static bool selectionWired;

			private static readonly HashSet<ItemData> selected = new HashSet<ItemData>();

			private static int keepBudget = 0;

			private static int pickLimit = 0;

			public static SaveChoiceUI Instance
			{
				get
				{
					//IL_0012: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Expected O, but got Unknown
					if ((Object)(object)_instance == (Object)null)
					{
						GameObject val = new GameObject("DeathlinkSaveChoiceUI");
						Object.DontDestroyOnLoad((Object)(object)val);
						_instance = val.AddComponent<SaveChoiceUI>();
					}
					return _instance;
				}
			}

			public static bool IsInitialized => (Object)(object)_instance != (Object)null;

			public void Awake()
			{
				_instance = this;
			}

			public void Update()
			{
				if (!((Object)(object)panel == (Object)null) && panel.activeSelf && !((Object)(object)grid == (Object)null) && tempInv != null)
				{
					grid.UpdateInventory(tempInv, (Player)null, (ItemData)null);
				}
			}

			public void Show(List<ItemData> items, int totalKept, int choiceCount)
			{
				//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_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				if (EnsurePanel() && EnsureGrid())
				{
					keepBudget = totalKept;
					pickLimit = choiceCount;
					selected.Clear();
					BuildInventory(items);
					grid.UpdateInventory(tempInv, (Player)null, (ItemData)null);
					grid.ResetView();
					string text = $"SaveChoiceUI grid: {tempInv.GetWidth()}x{tempInv.GetHeight()}, ";
					string text2 = $"slot elements={(((Object)(object)gridRoot != (Object)null) ? ((Transform)gridRoot).childCount : (-1))}, ";
					Rect rect = ((RectTransform)((Component)grid).transform).rect;
					Logger.LogDebug(text + text2 + $"gridRect={((Rect)(ref rect)).size}");
					ClearHighlights();
					UpdateCounter();
					panel.SetActive(true);
				}
			}

			public void Hide()
			{
				if ((Object)(object)panel != (Object)null)
				{
					panel.SetActive(false);
				}
			}

			private void Confirm()
			{
				List<ItemData> picked = selected.ToList();
				Hide();
				selected.Clear();
				ApplySelection(picked);
			}

			private bool EnsurePanel()
			{
				//IL_0047: 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_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0139: Unknown result type (might be due to invalid IL or missing references)
				//IL_0148: Unknown result type (might be due to invalid IL or missing references)
				//IL_0159: Unknown result type (might be due to invalid IL or missing references)
				//IL_015f: Unknown result type (might be due to invalid IL or missing references)
				//IL_019f: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_022b: Unknown result type (might be due to invalid IL or missing references)
				//IL_023a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0249: Unknown result type (might be due to invalid IL or missing references)
				//IL_0270: Unknown result type (might be due to invalid IL or missing references)
				//IL_027a: Expected O, but got Unknown
				if ((Object)(object)panel != (Object)null)
				{
					return true;
				}
				if (GUIManager.Instance == null || !Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront))
				{
					Logger.LogWarning("GUIManager not setup, skipping death saving panel creation.");
					return false;
				}
				panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 700f, 640f, true);
				panel.SetActive(false);
				GUIManager.Instance.CreateText(Localization.instance.Localize("$dso_header"), panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 270f), GUIManager.Instance.AveriaSerifBold, 30, GUIManager.Instance.ValheimOrange, true, Color.black, 620f, 40f, false);
				GameObject val = GUIManager.Instance.CreateText(Localization.instance.Localize("$dso_description"), panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 225f), GUIManager.Instance.AveriaSerif, 18, Color.white, true, Color.black, 620f, 50f, false);
				val.GetComponent<Text>().alignment = (TextAnchor)4;
				counterText = GUIManager.Instance.CreateText("", panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 180f), GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimYellow, true, Color.black, 620f, 40f, false).GetComponent<Text>();
				counterText.alignment = (TextAnchor)4;
				GameObject val2 = GUIManager.Instance.CreateButton(Localization.instance.Localize("$dso_confirm"), panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -270f), 250f, 60f);
				((UnityEvent)val2.GetComponent<Button>().onClick).AddListener(new UnityAction(Confirm));
				return true;
			}

			private bool EnsureGrid()
			{
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Expected O, but got Unknown
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Expected O, but got Unknown
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0113: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Expected O, but got Unknown
				//IL_011c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0128: Unknown result type (might be due to invalid IL or missing references)
				//IL_0134: Unknown result type (might be due to invalid IL or missing references)
				//IL_0140: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0158: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c2: Expected O, but got Unknown
				if ((Object)(object)grid != (Object)null)
				{
					return true;
				}
				if ((Object)(object)InventoryGui.instance == (Object)null || (Object)(object)InventoryGui.instance.ContainerGrid == (Object)null)
				{
					Logger.LogWarning("InventoryGui not ready, cannot build death saving grid.");
					return false;
				}
				GameObject val = new GameObject("DL_GridHolder", new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(panel.transform, false);
				RectTransform val2 = (RectTransform)val.transform;
				val2.anchorMin = new Vector2(0.5f, 0.5f);
				val2.anchorMax = new Vector2(0.5f, 0.5f);
				val2.pivot = new Vector2(0.5f, 0.5f);
				val2.sizeDelta = new Vector2(600f, 380f);
				val2.anchoredPosition = new Vector2(0f, -40f);
				GameObject gameObject = ((Component)InventoryGui.instance.ContainerGrid).gameObject;
				GameObject val3 = Object.Instantiate<GameObject>(gameObject, (Transform)(object)val2);
				((Object)val3).name = "DL_SaveGrid";
				val3.SetActive(true);
				RectTransform val4 = (RectTransform)val3.transform;
				((Transform)val4).localScale = Vector3.one;
				((Transform)val4).localRotation = Quaternion.identity;
				val4.anchorMin = Vector2.zero;
				val4.anchorMax = Vector2.one;
				val4.offsetMin = Vector2.zero;
				val4.offsetMax = Vector2.zero;
				grid = val3.GetComponent<InventoryGrid>();
				gridRoot = grid.m_gridRoot;
				if ((Object)(object)gridRoot != (Object)null)
				{
					((Component)gridRoot).gameObject.SetActive(true);
				}
				if ((Object)(object)gridRoot != (Object)null)
				{
					foreach (Transform item in (Transform)gridRoot)
					{
						Transform val5 = item;
						Object.Destroy((Object)(object)((Component)val5).gameObject);
					}
				}
				grid.m_width = 0;
				grid.m_height = 0;
				if (!selectionWired)
				{
					InventoryGrid obj = grid;
					obj.m_onSelected = (Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.Combine(obj.m_onSelected, (Action<InventoryGrid, ItemData, Vector2i, Modifier>)delegate(InventoryGrid g, ItemData item, Vector2i pos, Modifier mod)
					{
						//IL_0002: Unknown result type (might be due to invalid IL or missing references)
						OnItemClicked(item, pos);
					});
					InventoryGrid obj2 = grid;
					obj2.m_onRightClick = (Action<InventoryGrid, ItemData, Vector2i>)Delegate.Combine(obj2.m_onRightClick, (Action<InventoryGrid, ItemData, Vector2i>)delegate
					{
					});
					selectionWired = true;
				}
				return true;
			}

			private void BuildInventory(List<ItemData> items)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				//IL_005e: 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)
				int num