Decompiled source of Deathlink v0.8.0

plugins/Deathlink.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
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;
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.Serialization;
using YamlDotNet.Serialization.NamingConventions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValRougelike")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValRougelike")]
[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]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 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);
			}
		}
	}
	public static class Extensions
	{
		private static readonly List<ItemType> EquipmentTypes = new List<ItemType>
		{
			(ItemType)7,
			(ItemType)12,
			(ItemType)6,
			(ItemType)11,
			(ItemType)4,
			(ItemType)5,
			(ItemType)19,
			(ItemType)17,
			(ItemType)18,
			(ItemType)3,
			(ItemType)14,
			(ItemType)22,
			(ItemType)20,
			(ItemType)24
		};

		public static List<ItemData> GetEquipment(this List<ItemData> list)
		{
			return list.Where((ItemData x) => EquipmentTypes.Contains(x.m_shared.m_itemType)).ToList();
		}

		public static List<ItemData> GetNotEquipment(this List<ItemData> list)
		{
			return list.Where((ItemData x) => !EquipmentTypes.Contains(x.m_shared.m_itemType)).ToList();
		}

		public static bool IsEquipment(this ItemData item)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (EquipmentTypes.Contains(item.m_shared.m_itemType))
			{
				return true;
			}
			return false;
		}
	}
	[BepInPlugin("MidnightsFX.Deathlink", "Deathlink", "0.8.0")]
	[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.8.0";

		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 (BepInExUtils.GetPlugins(false).Keys.Contains("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 (BepInExUtils.GetPlugins(false).Keys.Contains("RustyMods.AlmanacClasses"))
			{
				RustyAlmanacClassesLoaded = true;
			}
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			DeathConfigurationData.Init();
			((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 text3 = Regex.Replace(ReadEmbeddedResourceFile(text2), "\\/\\/.*", "");
				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_0138: Unknown result type (might be due to invalid IL or missing references)
				//IL_0142: 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.SkillModifiers.Count > 0)
				{
					stringBuilder.AppendLine("<size=30><b>Skill Modifiers</b></size>");
					stringBuilder.AppendLine(playerDeathConfiguration.GetSkillModiferDescription());
					stringBuilder.AppendLine();
				}
				if (playerDeathConfiguration.ResourceModifiers.Count > 0)
				{
					stringBuilder.AppendLine("<size=30><b>Resource Modifiers</b></size>");
					stringBuilder.AppendLine(playerDeathConfiguration.GetResourceModiferDescription());
					stringBuilder.AppendLine();
				}
				if (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())));
			}
		}

		private static string specialColor = "#ffa64d";
	}
	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;
				}
				if ((Object)(object)((Component)__instance).gameObject.GetComponent<DeathChoices.DeathChoiceUI>() == (Object)null)
				{
					((Component)__instance).gameObject.AddComponent<DeathChoices.DeathChoiceUI>();
				}
				DeathChoices.DeathChoiceUI.Instance.Show();
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		public static class HideDeathChoiceUI
		{
			public static void Postfix(InventoryGui __instance)
			{
				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 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";

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

			public void Awake()
			{
				CreateStaticUIObjects();
				SetChoiceList();
			}

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

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

			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;
				}
				long playerID = Player.m_localPlayer.GetPlayerID();
				if (DeathConfigurationData.playerSettings.ContainsKey(playerID))
				{
					DeathConfigurationData.playerSettings.Remove(playerID);
				}
				DeathConfigurationData.playerSettings.Add(playerID, new DataObjects.DeathConfiguration
				{
					DeathChoiceLevel = selectedDeathChoice
				});
				Player.m_localPlayer.AddUniqueKeyValue(DataObjects.DeathChoiceKey, selectedDeathChoice);
				DeathConfigurationData.CheckAndSetPlayerDeathConfig();
				DeathConfigurationData.WritePlayerChoices();
				Hide();
			}

			private void SetChoiceList()
			{
				//IL_00d9: 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)
				difficultyToggles.Clear();
				int num = -50;
				foreach (KeyValuePair<string, DataObjects.DeathChoiceLevel> entry in DeathConfigurationData.DeathLevels)
				{
					GameObject obj = Object.Instantiate<GameObject>(ChoicesContainer, ChoicesContent.transform);
					Transform val = obj.transform.Find("selecter");
					((Component)val.Find("Label")).GetComponent<Text>().text = entry.Key;
					((Component)obj.transform.Find("ChoiceName")).GetComponent<Text>().text = entry.Value.DisplayName;
					Toggle component = ((Component)val).GetComponent<Toggle>();
					component.group = choiceGroup;
					((UnityEvent<bool>)(object)component.onValueChanged).AddListener((UnityAction<bool>)delegate
					{
						((Component)DeathPenaltyDescription).GetComponent<Text>().text = entry.Value.GetDeathStyleDescription();
						((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;
					});
					obj.SetActive(true);
					obj.transform.localPosition = new Vector3
					{
						x = 260f,
						y = num
					};
					difficultyToggles.Add(component);
					num -= 50;
				}
			}

			private void CreateStaticUIObjects()
			{
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0123: Unknown result type (might be due to invalid IL or missing references)
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				//IL_0141: Unknown result type (might be due to invalid IL or missing references)
				//IL_0152: 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_01af: Unknown result type (might be due to invalid IL or missing references)
				//IL_01be: 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_0203: Unknown result type (might be due to invalid IL or missing references)
				//IL_020d: Expected O, but got Unknown
				//IL_0240: Unknown result type (might be due to invalid IL or missing references)
				//IL_024f: Unknown result type (might be due to invalid IL or missing references)
				//IL_025e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0274: Unknown result type (might be due to invalid IL or missing references)
				//IL_027a: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02df: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_035f: Unknown result type (might be due to invalid IL or missing references)
				//IL_036e: Unknown result type (might be due to invalid IL or missing references)
				//IL_037d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0393: Unknown result type (might be due to invalid IL or missing references)
				//IL_0399: Unknown result type (might be due to invalid IL or missing references)
				//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_040f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0415: Unknown result type (might be due to invalid IL or missing references)
				//IL_047e: Unknown result type (might be due to invalid IL or missing references)
				//IL_048d: Unknown result type (might be due to invalid IL or missing references)
				//IL_049c: Unknown result type (might be due to invalid IL or missing references)
				//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_050e: Unknown result type (might be due to invalid IL or missing references)
				//IL_051d: Unknown result type (might be due to invalid IL or missing references)
				//IL_052e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0534: Unknown result type (might be due to invalid IL or missing references)
				//IL_059d: Unknown result type (might be due to invalid IL or missing references)
				//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
				//IL_05bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_05d1: Unknown result type (might be due to invalid IL or missing references)
				//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_061e: Unknown result type (might be due to invalid IL or missing references)
				//IL_062d: Unknown result type (might be due to invalid IL or missing references)
				//IL_063c: Unknown result type (might be due to invalid IL or missing references)
				//IL_064d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0653: Unknown result type (might be due to invalid IL or missing references)
				//IL_06bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_06cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_06da: Unknown result type (might be due to invalid IL or missing references)
				//IL_0710: Unknown result type (might be due to invalid IL or missing references)
				//IL_071a: Expected O, but got Unknown
				//IL_0744: Unknown result type (might be due to invalid IL or missing references)
				//IL_0749: Unknown result type (might be due to invalid IL or missing references)
				//IL_076e: Unknown result type (might be due to invalid IL or missing references)
				//IL_078c: Unknown result type (might be due to invalid IL or missing references)
				//IL_078d: Unknown result type (might be due to invalid IL or missing references)
				//IL_07c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_07d3: Expected O, but got Unknown
				//IL_0800: Unknown result type (might be due to invalid IL or missing references)
				//IL_0843: Unknown result type (might be due to invalid IL or missing references)
				//IL_0848: Unknown result type (might be due to invalid IL or missing references)
				//IL_08a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_08b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_08bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_08d5: Unknown result type (might be due to invalid IL or missing references)
				//IL_08db: Unknown result type (might be due to invalid IL or missing references)
				if (GUIManager.Instance == null || !Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront))
				{
					Logger.LogWarning("GUIManager not setup, skipping static object creation.");
					return;
				}
				DeathChoicePanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 800f, 800f, true);
				DeathChoicePanel.SetActive(false);
				((Object)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, 360f), GUIManager.Instance.AveriaSerifBold, 30, GUIManager.Instance.ValheimOrange, true, Color.black, 350f, 40f, false)).name = "DLHeader";
				Text component = 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, 315f), GUIManager.Instance.AveriaSerif, 20, Color.white, true, Color.black, 560f, 60f, false).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, 360f), 60f, 60f);
				Button component2 = manualCloseButton.GetComponent<Button>();
				((Selectable)component2).interactable = true;
				((UnityEvent)component2.onClick).AddListener(new UnityAction(Hide));
				manualCloseButton.SetActive(false);
				((Object)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, 220f), GUIManager.Instance.AveriaSerifBold, 22, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false)).name = "DeathPenaltyTitle";
				GameObject obj = 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(150f, 110f), GUIManager.Instance.AveriaSerifBold, 18, Color.white, true, Color.black, 500f, 200f, false);
				((Object)obj).name = "DeathPenaltyDesc";
				DeathPenaltyDescription = obj.GetComponent<Text>();
				DeathPenaltyDescription.resizeTextForBestFit = true;
				DeathPenaltyDescription.resizeTextMaxSize = 18;
				((Object)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)).name = "xpModifiersTitle";
				GameObject obj2 = 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)obj2).name = "xpModifiersDesc";
				XPModifiersDescription = obj2.GetComponent<Text>();
				XPModifiersDescription.resizeTextForBestFit = true;
				XPModifiersDescription.resizeTextMaxSize = 18;
				((Object)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)).name = "lootModifiersTitle";
				GameObject obj3 = 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)obj3).name = "lootModifersDesc";
				LootModifersDescription = obj3.GetComponent<Text>();
				LootModifersDescription.resizeTextForBestFit = true;
				LootModifersDescription.resizeTextMaxSize = 18;
				((Object)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)).name = "harvestModifiersTitle";
				GameObject obj4 = 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)obj4).name = "harvestModifersDesc";
				HarvestModifiersDescription = obj4.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>();
				((Selectable)component3).interactable = true;
				((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, 200f, 400f);
				ChoicesScrollView.transform.localPosition = Vector2.op_Implicit(new Vector2
				{
					x = -260f,
					y = -30f
				});
				ChoicesContent = ((Component)ChoicesScrollView.GetComponentInChildren<ContentSizeFitter>()).gameObject;
				choiceGroup = ChoicesContent.AddComponent<ToggleGroup>();
				Logger.LogDebug("Setting up death choice template entry");
				ChoicesContainer = new GameObject("DeathChoice");
				ChoicesContainer.transform.SetParent(DeathChoicePanel.transform);
				ChoicesContainer.transform.position = DeathChoicePanel.transform.position;
				ChoicesContainer.SetActive(false);
				GameObject obj5 = GUIManager.Instance.CreateToggle(ChoicesContainer.transform, 40f, 40f);
				obj5.transform.localPosition = Vector2.op_Implicit(new Vector2(-220f, 0f));
				((Object)obj5).name = "selecter";
				((Component)obj5.transform.Find("Label")).gameObject.SetActive(false);
				obj5.GetComponent<Toggle>().isOn = false;
				((Object)GUIManager.Instance.CreateText("Name", ChoicesContainer.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-20f, 0f), GUIManager.Instance.AveriaSerifBold, 20, GUIManager.Instance.ValheimYellow, true, Color.black, 350f, 40f, false)).name = "ChoiceName";
			}
		}
	}
	public static class DeathProgressionSkill
	{
		[HarmonyPatch(typeof(Player), "RaiseSkill")]
		public class Deathskill_EXP_Patch
		{
			public static void Postfix(Player __instance)
			{
				//IL_03b2: 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();
					_bossKills = playerProfile.m_playerStats.m_stats[(PlayerStatType)85];
					_enemykills = playerProfile.m_playerStats.m_stats[(PlayerStatType)6];
					_piecesBuilt = playerProfile.m_playerStats.m_stats[(PlayerStatType)2];
					_treesChopped = playerProfile.m_playerStats.m_stats[(PlayerStatType)27];
					_mineAmount = playerProfile.m_playerStats.m_stats[(PlayerStatType)38];
					_craftAndUpgrades = playerProfile.m_playerStats.m_stats[(PlayerStatType)1];
				}
				if (timeSinceGameStart > lastSkillIncreaseTickTime)
				{
					lastSkillIncreaseTickTime = timeSinceGameStart + ValConfig.SkillProgressUpdateCheckInterval.Value;
					PlayerProfile playerProfile2 = Game.instance.GetPlayerProfile();
					float num = playerProfile2.m_playerStats.m_stats[(PlayerStatType)85];
					float num2 = playerProfile2.m_playerStats.m_stats[(PlayerStatType)6];
					float num3 = playerProfile2.m_playerStats.m_stats[(PlayerStatType)2];
					float num4 = playerProfile2.m_playerStats.m_stats[(PlayerStatType)27];
					float num5 = playerProfile2.m_playerStats.m_stats[(PlayerStatType)38];
					float num6 = playerProfile2.m_playerStats.m_stats[(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 + num10 + num9 + num8 + num7;
					float num14 = (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);
					}
					Logger.LogDebug($"DeathProgression skill bonus from survival (survive time: {__instance.m_timeSinceDeath}) {num14} x {num13} = {num15}");
					((Character)Player.m_localPlayer).RaiseSkill(DeathSkill, num15);
				}
			}
		}

		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;
		}
	}
	public static class HarvestModifiers
	{
		[HarmonyPatch(typeof(TreeLog), "Destroy")]
		public static class IncreaseDropsFromTree
		{
			private static void Postfix(TreeLog __instance, HitData hitData)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				if (Deathlink.pcfg().ResourceModifiers != null && Deathlink.pcfg().ResourceModifiers.Count > 0 && hitData != null && (Object)(object)Player.m_localPlayer != (Object)null && hitData.m_attacker == ((Character)Player.m_localPlayer).GetZDOID())
				{
					IncreaseDrops(__instance.m_dropWhenDestroyed, ((Component)__instance).transform.position);
				}
			}
		}

		[HarmonyPatch(typeof(Pickable), "Drop")]
		public static class IncreaseDropsPickable
		{
			private static void Prefix(Pickable __instance, GameObject prefab, int offset)
			{
				//IL_008f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: 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_00dd: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				if (Deathlink.pcfg().ResourceModifiers == null || Deathlink.pcfg().ResourceModifiers.Count <= 0 || !((Object)(object)Player.m_localPlayer != (Object)null))
				{
					return;
				}
				float num = Deathlink.pcfg().GetResouceEarlyCache(prefab.gameObject) - 1f;
				int num2 = 0;
				while (num > 0f)
				{
					float value = Random.value;
					Logger.LogDebug($"Checking to increase drops {value} <= {num}");
					if (value <= num)
					{
						num2++;
					}
					num -= 1f;
				}
				if (num2 > 0)
				{
					Vector2 val = Random.insideUnitCircle * 0.2f;
					Vector3 val2 = ((Component)__instance).transform.position + Vector3.up * __instance.m_spawnOffset + new Vector3(val.x, 0.5f * (float)offset, val.y);
					Quaternion val3 = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f);
					for (int i = 0; i < num2; i++)
					{
						Object.Instantiate<GameObject>(prefab, val2, val3);
					}
				}
			}
		}

		[HarmonyPatch(typeof(MineRock5), "RPC_SetAreaHealth")]
		public static class Minerock5DestroyPatch
		{
			private static void Postfix(MineRock5 __instance, long sender, int index, float health)
			{
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				if (Deathlink.pcfg().ResourceModifiers != null && Deathlink.pcfg().ResourceModifiers.Count > 0 && (Object)(object)Player.m_localPlayer != (Object)null && health <= 0f)
				{
					IncreaseDrops(__instance.m_dropItems, ((Component)__instance).gameObject.transform.position);
				}
			}
		}

		[HarmonyPatch(typeof(Destructible), "Destroy")]
		public static class IncreaseDropsFromDestructible
		{
			private static void Prefix(Destructible __instance, HitData hit)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				if (Deathlink.pcfg().ResourceModifiers != null && Deathlink.pcfg().ResourceModifiers.Count > 0 && hit != null && (Object)(object)Player.m_localPlayer != (Object)null && hit.m_attacker == ((Character)Player.m_localPlayer).GetZDOID())
				{
					IncreaseDestructibleDrops(__instance);
				}
			}

			public static void IncreaseDestructibleDrops(Destructible destructible)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)destructible.m_spawnWhenDestroyed != (Object)null))
				{
					Vector3 position = ((Component)destructible).transform.position;
					DropOnDestroyed component = ((Component)destructible).GetComponent<DropOnDestroyed>();
					if (!((Object)(object)component == (Object)null) && component.m_dropWhenDestroyed != null)
					{
						IncreaseDrops(component.m_dropWhenDestroyed, position);
					}
				}
			}
		}

		public static void IncreaseDrops(DropTable drops, Vector3 position)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>();
			List<KeyValuePair<GameObject, int>> list2 = Deathlink.pcfg().RollHarvestLoot();
			if (list2.Count > 0)
			{
				list.AddRange(list2);
			}
			int num = Random.Range(drops.m_dropMin, drops.m_dropMax);
			int num2 = drops.m_drops.Count;
			if (num == 0)
			{
				num = 1;
			}
			if (num2 == 0)
			{
				num2 = 1;
			}
			int num3 = Mathf.RoundToInt((float)(num / num2));
			foreach (DropData drop in drops.m_drops)
			{
				float resouceEarlyCache = Deathlink.pcfg().GetResouceEarlyCache(drop.m_item);
				if (resouceEarlyCache != 1f)
				{
					int num4 = Mathf.RoundToInt((float)num3 * resouceEarlyCache);
					if (num4 > 0)
					{
						list.Add(new KeyValuePair<GameObject, int>(drop.m_item, num4));
					}
				}
			}
			if (list.Count <= 0)
			{
				return;
			}
			Logger.LogDebug("Deathlink drop increase.");
			foreach (KeyValuePair<GameObject, int> item in list)
			{
				Quaternion val = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f);
				int maxStackSize = item.Key.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize;
				int num5 = item.Value;
				if (num5 > maxStackSize)
				{
					int num6 = num5 / maxStackSize;
					for (int i = 0; i < num6; i++)
					{
						Object.Instantiate<GameObject>(item.Key, position, val).GetComponent<ItemDrop>().m_itemData.m_stack = maxStackSize;
						Logger.LogDebug($"Dropping {maxStackSize} of {((Object)item.Key).name} to the world.");
					}
					num5 -= maxStackSize * num6;
				}
				Object.Instantiate<GameObject>(item.Key, position, val).GetComponent<ItemDrop>().m_itemData.m_stack = num5;
				Logger.LogDebug($"Dropping {num5} of {((Object)item.Key).name} to the world.");
			}
		}
	}
	public static class LootModifiers
	{
		[HarmonyPatch(typeof(CharacterDrop))]
		public static class CalculateLootByModifiers
		{
			[HarmonyPostfix]
			[HarmonyPatch("GenerateDropList")]
			private static void Postfix(List<KeyValuePair<GameObject, int>> __result, CharacterDrop __instance)
			{
				//IL_00e9: 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)
				if (!__instance.m_character.m_localPlayerHasHit || Deathlink.pcfg().DeathLootModifiers == null || Deathlink.pcfg().DeathLootModifiers.Count == 0)
				{
					return;
				}
				List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>();
				foreach (KeyValuePair<GameObject, int> item in __result)
				{
					float resouceEarlyCache = Deathlink.pcfg().GetResouceEarlyCache(((Object)item.Key).name);
					if (resouceEarlyCache == 1f)
					{
						list.Add(item);
						continue;
					}
					int num = Mathf.RoundToInt((float)item.Value * resouceEarlyCache);
					if (num >= 1)
					{
						list.Add(new KeyValuePair<GameObject, int>(item.Key, num));
					}
				}
				List<KeyValuePair<GameObject, int>> list2 = Deathlink.pcfg().RollKillLoot();
				if (list2.Count > 0)
				{
					foreach (KeyValuePair<GameObject, int> item2 in list2)
					{
						for (int i = 0; i < item2.Value; i++)
						{
							Object.Instantiate<GameObject>(item2.Key, ((Component)__instance).transform.position, Quaternion.identity);
						}
					}
				}
				__result = list;
			}
		}
	}
	public static class SkillsChanges
	{
		[HarmonyPatch(typeof(Skills), "OnDeath")]
		private static class OnDeath_Patch
		{
			private static bool Prefix(Skills __instance)
			{
				if (((Character)__instance.m_player).m_seman.HaveStatusEffect(SEMan.s_statusEffectSoftDeath))
				{
					return false;
				}
				if (Deathlink.pcfg().DeathStyle.skillLossOnDeath)
				{
					float num = Mathf.Lerp(Deathlink.pcfg().DeathStyle.maxSkillLossPercentage, Deathlink.pcfg().DeathStyle.minSkillLossPercentage, DeathProgressionSkill.DeathSkillCalculatePercentWithBonus());
					Logger.LogDebug($"{num}");
					LowerConfigurableSkills(__instance, num);
				}
				return false;
			}

			private static void LowerConfigurableSkills(Skills skills, float factor)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				foreach (KeyValuePair<SkillType, Skill> skillDatum in skills.m_skillData)
				{
					if (skills_to_avoid_standard_death_penalty.Contains(skillDatum.Key))
					{
						Logger.LogDebug($"Skipping lowering skill {skillDatum.Key} current level: {skillDatum.Value.m_level}");
						continue;
					}
					float num = skillDatum.Value.m_level * factor;
					Skill value = skillDatum.Value;
					value.m_level -= num;
					skillDatum.Value.m_accumulator = 0f;
				}
				if (Deathlink.RustyAlmanacClassesLoaded && ValConfig.EnableAlmanacClassesXPLossOnDeath.Value)
				{
					int level = ClassesAPI.GetLevel();
					int num2 = Mathf.RoundToInt((float)level * factor * 500f * ValConfig.AlmanacClassesXPLossScale.Value) * -1;
					Logger.LogDebug($"Almanac (lvl {level}) XP Loss: {num2}");
					ClassesAPI.AddEXP(num2);
				}
				if (Deathlink.WackyMMOLoaded && ValConfig.EnableWackyMMOXPLossOnDeath.Value)
				{
					int level2 = EpicMMOSystem_API.GetLevel();
					int num3 = Mathf.RoundToInt((float)level2 * factor * 500f * ValConfig.WackyMMOXPLossScale.Value) * -1;
					Logger.LogDebug($"WackyMMO (lvl {level2}) XP Loss: {num3}");
					EpicMMOSystem_API.AddExp(num3);
				}
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)1, "$msg_skills_lowered", 0, (Sprite)null);
				}
			}
		}

		[HarmonyPatch(typeof(Skills), "RaiseSkill")]
		private static class SkillRaisePatch
		{
			private static void Prefix(Skills __instance, SkillType skillType, float factor)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				float skillBonusLazyCache = Deathlink.pcfg().GetSkillBonusLazyCache(skillType);
				Logger.LogDebug($"{skillType} skillGain Modified {skillBonusLazyCache}");
				if (skillBonusLazyCache != 0f)
				{
					factor *= skillBonusLazyCache;
				}
			}
		}

		public static List<SkillType> skills_to_avoid_standard_death_penalty = new List<SkillType>();
	}
	public static class OnDeathChanges
	{
		[HarmonyPatch(typeof(Player))]
		public static class OnDeath_Tombstone_Patch
		{
			[HarmonyTranspiler]
			[HarmonyPatch("OnDeath")]
			private static IEnumerable<CodeInstruction> ConstructorTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Expected O, but got Unknown
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Expected O, but got Unknown
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Expected O, but got Unknown
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_0097: Expected O, but got Unknown
				CodeMatcher val = new CodeMatcher(instructions, generator);
				val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2]
				{
					new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null),
					new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "CreateTombStone", (Type[])null, (Type[])null), (string)null)
				}).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate<Action<Player>>((Action<Player>)ModifyDeath) })
					.CreateLabelOffset(out var label, 4)
					.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
					{
						new CodeInstruction(OpCodes.Br, (object)label)
					})
					.ThrowIfNotMatch("Unable to patch Deathlink player death changes.", Array.Empty<CodeMatch>());
				return val.Instructions();
			}

			private static void ModifyDeath(Player __instance)
			{
				TombstoneOnDeath(__instance);
				FoodLossOnDeath(__instance);
			}

			public static void FoodLossOnDeath(Player instance)
			{
				if (!Deathlink.pcfg().DeathStyle.foodLossOnDeath)
				{
					return;
				}
				if (Deathlink.pcfg().DeathStyle.foodLossUsesDeathlink && instance.m_foods.Count > 0)
				{
					float num = DeathProgressionSkill.DeathSkillCalculatePercentWithBonus();
					if (num >= 0.9f)
					{
						return;
					}
					if (num >= 0.6f && num < 0.9f)
					{
						instance.m_foods.Remove(instance.m_foods[0]);
					}
					else if (num > 0.3f && num < 0.6f)
					{
						instance.m_foods.Remove(instance.m_foods[0]);
						if (instance.m_foods.Count > 0)
						{
							instance.m_foods.Remove(instance.m_foods[0]);
						}
					}
					else
					{
						instance.m_foods.Clear();
					}
				}
				else
				{
					instance.m_foods.Clear();
				}
			}

			public static void TombstoneOnDeath(Player instance)
			{
				//IL_0366: Unknown result type (might be due to invalid IL or missing references)
				//IL_0376: 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_04df: Unknown result type (might be due to invalid IL or missing references)
				//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
				List<ItemData> allItems = ((Humanoid)instance).m_inventory.GetAllItems();
				List<ItemData> list = new List<ItemData>();
				List<ItemData> list2 = new List<ItemData>();
				Inventory inventory = ((Humanoid)instance).m_inventory;
				Dictionary<DataObjects.ItemResults, List<ItemData>> dictionary = new Dictionary<DataObjects.ItemResults, List<ItemData>>();
				string[] source = ValConfig.ItemsNotSkillChecked.Value.Split(new char[1] { ',' });
				foreach (ItemData item in allItems)
				{
					if ((Object)(object)item.m_dropPrefab != (Object)null && source.Contains(((Object)item.m_dropPrefab).name))
					{
						list2.Add(item);
					}
					else
					{
						list.Add(item);
					}
				}
				switch (Deathlink.pcfg().DeathStyle.itemLossStyle)
				{
				case DataObjects.ItemLossStyle.None:
					Logger.LogDebug("No items destroyed on death.");
					dictionary.SafeInsertOrAppend(DataObjects.ItemResults.ItemSaved, list);
					break;
				case DataObjects.ItemLossStyle.DestroyNonWeaponArmor:
					Logger.LogDebug("Destroying non Equipment items.");
					dictionary.SafeInsertOrAppend(DataObjects.ItemResults.ItemLost, list.GetNotEquipment());
					dictionary.SafeInsertOrAppend(DataObjects.ItemResults.EquipmentSaved, list.GetEquipment());
					foreach (ItemData item2 in list.GetNotEquipment())
					{
						((Humanoid)instance).m_inventory.RemoveItem(item2);
					}
					if (!Deathlink.AzuEPILoaded)
					{
						break;
					}
					Logger.LogDebug("AzuEPI| Removing non-equipment items from quickslots.");
					foreach (ItemData quickSlotsItem in API.GetQuickSlotsItems())
					{
						if (!quickSlotsItem.IsEquipment())
						{
							((Humanoid)instance).m_inventory.RemoveItem(quickSlotsItem);
							dictionary.SafeInsertOrAppend(DataObjects.ItemResults.ItemLost, quickSlotsItem);
						}
						else
						{
							dictionary.SafeInsertOrAppend(DataObjects.ItemResults.EquipmentSaved, quickSlotsItem);
						}
					}
					break;
				case DataObjects.ItemLossStyle.DestroyAll:
					Logger.LogDebug("Destroying all non skill checked items.");
					dictionary.SafeInsertOrAppend(DataObjects.ItemResults.ItemLost, list);
					foreach (ItemData item3 in list)
					{
						((Humanoid)instance).m_inventory.RemoveItem(item3);
					}
					if (Deathlink.AzuEPILoaded)
					{
						Logger.LogDebug("AzuEPI| Destroying quickslot items.");
						dictionary.SafeInsertOrAppend(DataObjects.ItemResults.ItemLost, API.GetQuickSlotsItems());
						API.GetQuickSlotsItems().ForEach(delegate(ItemData item)
						{
							((Humanoid)instance).m_inventory.RemoveItem(item);
						});
					}
					break;
				case DataObjects.ItemLossStyle.DeathlinkBased:
					Logger.LogDebug("Destroying random items based on deathlink skill");
					dictionary = DetermineItemResultsByDeathlink(instance, list);
					dictionary[DataObjects.ItemResults.EquipmentLost].ForEach(delegate(ItemData item)
					{
						((Humanoid)instance).m_inventory.RemoveItem(item);
					});
					dictionary[DataObjects.ItemResults.ItemLost].ForEach(delegate(ItemData item)
					{
						((Humanoid)instance).m_inventory.RemoveItem(item);
					});
					break;
				}
				if (Deathlink.pcfg().DeathStyle.nonSkillCheckedItemAction == DataObjects.NonSkillCheckedItemAction.Destroy)
				{
					Logger.LogDebug("Non skill checked being destroyed.");
					dictionary.SafeInsertOrAppend(DataObjects.ItemResults.ItemLost, list2);
				}
				if (Deathlink.pcfg().DeathStyle.nonSkillCheckedItemAction == DataObjects.NonSkillCheckedItemAction.Save)
				{
					Logger.LogDebug("Non skill checked items being left on player.");
				}
				if ((!dictionary.ContainsKey(DataObjects.ItemResults.EquipmentSaved) || dictionary[DataObjects.ItemResults.EquipmentSaved].Count <= 0) && (!dictionary.ContainsKey(DataObjects.ItemResults.ItemSaved) || dictionary[DataObjects.ItemResults.ItemSaved].Count <= 0) && (Deathlink.pcfg().DeathStyle.nonSkillCheckedItemAction != DataObjects.NonSkillCheckedItemAction.Tombstone || list2.Count() <= 0))
				{
					return;
				}
				Logger.LogDebug("Tombstone needed");
				GameObject obj = Object.Instantiate<GameObject>(instance.m_tombstone, ((Character)instance).GetCenterPoint(), ((Component)instance).transform.rotation);
				Inventory inventory2 = obj.GetComponent<Container>().GetInventory();
				if (Deathlink.pcfg().DeathStyle.itemSavedStyle == DataObjects.ItemSavedStyle.Tombstone)
				{
					Logger.LogDebug("Adding saved items to tombstone.");
					if (dictionary.ContainsKey(DataObjects.ItemResults.EquipmentSaved) && dictionary[DataObjects.ItemResults.EquipmentSaved].Count > 0)
					{
						AddItemsToTombstone(inventory2, dictionary[DataObjects.ItemResults.EquipmentSaved]);
						dictionary[DataObjects.ItemResults.EquipmentSaved].ForEach(delegate(ItemData item)
						{
							((Humanoid)instance).m_inventory.RemoveItem(item);
						});
					}
					if (dictionary.ContainsKey(DataObjects.ItemResults.ItemSaved) && dictionary[DataObjects.ItemResults.ItemSaved].Count > 0)
					{
						AddItemsToTombstone(inventory2, dictionary[DataObjects.ItemResults.ItemSaved]);
						dictionary[DataObjects.ItemResults.ItemSaved].ForEach(delegate(ItemData item)
						{
							((Humanoid)instance).m_inventory.RemoveItem(item);
						});
					}
				}
				if (Deathlink.pcfg().DeathStyle.nonSkillCheckedItemAction == DataObjects.NonSkillCheckedItemAction.Tombstone)
				{
					Logger.LogDebug("Adding saved non-skill checked items to tombstone.");
					AddItemsToTombstone(inventory2, list2);
					list2.ForEach(delegate(ItemData item)
					{
						((Humanoid)instance).m_inventory.RemoveItem(item);
					});
				}
				TombStone component = obj.GetComponent<TombStone>();
				PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
				string name = playerProfile.GetName();
				long playerID = playerProfile.GetPlayerID();
				component.Setup(name, playerID);
				inventory.Changed();
				if (ValConfig.ShowDeathMapMarker.Value)
				{
					Minimap.instance.AddPin(((Component)instance).transform.position, (PinType)4, $"$hud_mapday {EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds())}", true, false, 0L, default(PlatformUserID));
				}
			}

			public static void AddItemsToTombstone(Inventory tombstone, List<ItemData> transferItems)
			{
				int num = Mathf.RoundToInt(Mathf.Sqrt((float)transferItems.Count())) + 1;
				tombstone.m_width += num;
				tombstone.m_height += num;
				foreach (ItemData transferItem in transferItems)
				{
					tombstone.m_inventory.Add(transferItem);
				}
				tombstone.Changed();
			}

			internal static Dictionary<DataObjects.ItemResults, List<ItemData>> DetermineItemResultsByDeathlink(Player player, List<ItemData> playerItemsWithoutNonSkillCheckedItems)
			{
				float num = DeathProgressionSkill.DeathSkillCalculatePercentWithBonus();
				int num2 = Mathf.RoundToInt((float)(Deathlink.pcfg().DeathStyle.maxItemsKept - Deathlink.pcfg().DeathStyle.minItemsKept) * num + (float)Deathlink.pcfg().DeathStyle.minItemsKept);
				int num3 = Mathf.RoundToInt((float)(Deathlink.pcfg().DeathStyle.maxEquipmentKept - Deathlink.pcfg().DeathStyle.minEquipmentKept) * num + (float)Deathlink.pcfg().DeathStyle.minEquipmentKept);
				int remainingsaves = num2 + num3;
				Dictionary<DataObjects.ItemResults, List<ItemData>> dictionary = new Dictionary<DataObjects.ItemResults, List<ItemData>>
				{
					{
						DataObjects.ItemResults.EquipmentSaved,
						new List<ItemData>()
					},
					{
						DataObjects.ItemResults.EquipmentLost,
						new List<ItemData>()
					},
					{
						DataObjects.ItemResults.ItemSaved,
						new List<ItemData>()
					},
					{
						DataObjects.ItemResults.ItemLost,
						new List<ItemData>()
					}
				};
				int equipment_saved_count = 0;
				foreach (ItemData item in Deathlink.shuffleList(playerItemsWithoutNonSkillCheckedItems.GetEquipment()))
				{
					if (remainingsaves > 0)
					{
						if (RemoveEquipmentByStyle(equipment_saved_count, num3, item, remainingsaves, out remainingsaves, out equipment_saved_count))
						{
							Logger.LogDebug("Save: " + item.m_shared.m_name);
							dictionary[DataObjects.ItemResults.EquipmentSaved].Add(item);
						}
						else
						{
							Logger.LogDebug("Remove by style: " + item.m_shared.m_name);
							dictionary[DataObjects.ItemResults.EquipmentLost].Add(item);
						}
					}
					else
					{
						Logger.LogDebug("Save limit reached, removing: " + item.m_shared.m_name);
						dictionary[DataObjects.ItemResults.EquipmentLost].Add(item);
					}
				}
				if (Deathlink.AzuEPILoaded)
				{
					foreach (ItemData quickSlotsItem in API.GetQuickSlotsItems())
					{
						if (quickSlotsItem.IsEquipment() && remainingsaves > 0)
						{
							remainingsaves--;
							num2--;
							dictionary[DataObjects.ItemResults.EquipmentSaved].Add(quickSlotsItem);
						}
						else if (remainingsaves > 0)
						{
							remainingsaves--;
							num2--;
							dictionary[DataObjects.ItemResults.ItemSaved].Add(quickSlotsItem);
						}
						else
						{
							dictionary[DataObjects.ItemResults.ItemLost].Add(quickSlotsItem);
						}
					}
				}
				List<ItemData> list = Deathlink.shuffleList(playerItemsWithoutNonSkillCheckedItems.GetNotEquipment());
				if (remainingsaves > 0)
				{
					foreach (ItemData item2 in list)
					{
						if (remainingsaves > 0 && num2 > 0)
						{
							Logger.LogDebug("NonEq| Saving: " + item2.m_shared.m_name);
							dictionary[DataObjects.ItemResults.ItemSaved].Add(item2);
							remainingsaves--;
							num2--;
						}
						else
						{
							Logger.LogDebug("NonEq| Removing: " + item2.m_shared.m_name);
							dictionary[DataObjects.ItemResults.ItemLost].Add(item2);
						}
					}
				}
				else
				{
					Logger.LogDebug($"NonEq| Removing: {list.Count} due to no saves remaining.");
					foreach (ItemData item3 in list)
					{
						dictionary[DataObjects.ItemResults.ItemLost].Add(item3);
					}
				}
				return dictionary;
			}

			internal static bool RemoveEquipmentByStyle(int equipment_saved, int max_equipment_savable, ItemData equipment, int numberOfItemsSavable, out int remainingsaves, out int equipment_saved_count)
			{
				equipment_saved_count = 0;
				remainingsaves = 0;
				if (numberOfItemsSavable <= 0)
				{
					return false;
				}
				if (equipment_saved >= max_equipment_savable)
				{
					Logger.LogDebug($"Max equipment retained ({max_equipment_savable}) reached, removing {((Object)equipment.m_dropPrefab).name}");
					return false;
				}
				Logger.LogDebug($"Saving equipment remaining savable?({numberOfItemsSavable}) {((Object)equipment.m_dropPrefab).name}");
				equipment_saved_count = equipment_saved + 1;
				remainingsaves = numberOfItemsSavable - 1;
				return true;
			}
		}
	}
}
namespace Deathlink.Common
{
	public class DataObjects
	{
		public enum ItemLossStyle
		{
			None,
			DestroyNonWeaponArmor,
			DeathlinkBased,
			DestroyAll
		}

		public enum ItemResults
		{
			EquipmentSaved,
			EquipmentLost,
			ItemSaved,
			ItemLost
		}

		public enum ItemSavedStyle
		{
			OnCharacter,
			Tombstone
		}

		public enum ResourceGainTypes
		{
			Kills,
			Harvesting
		}

		public enum NonSkillCheckedItemAction
		{
			Destroy,
			Tombstone,
			Save
		}

		public class DeathProgressionDetails
		{
			public bool foodLossOnDeath = true;

			public bool foodLossUsesDeathlink = true;

			public int minItemsKept;

			public int maxItemsKept;

			public int minEquipmentKept;

			public int maxEquipmentKept;

			public bool skillLossOnDeath = true;

			public float maxSkillLossPercentage;

			public float minSkillLossPercentage;

			public ItemLossStyle itemLossStyle;

			public ItemSavedStyle itemSavedStyle;

			public NonSkillCheckedItemAction nonSkillCheckedItemAction = NonSkillCheckedItemAction.Tombstone;
		}

		public class DeathResourceModifier
		{
			public bool skillInfluence { get; set; } = true;


			public List<string> prefabs { get; set; }

			public float bonusModifer { get; set; }

			public List<ResourceGainTypes> bonusActions { get; set; }
		}

		public class DeathSkillModifier
		{
			public bool skillInfluence { get; set; } = true;


			public SkillType skill { get; set; }

			public float bonusModifer { get; set; }
		}

		public class DeathLootModifier
		{
			private bool skillInfluence { get; set; } = true;


			public string prefab { get; set; }

			public float chance { get; set; }

			public int amount { get; set; } = 1;


			public List<ResourceGainTypes> bonusActions { get; set; }
		}

		public class DeathChoiceLevel
		{
			private Dictionary<SkillType, float> CalculatedSkillMods = new Dictionary<SkillType, float>();

			private Dictionary<string, float> CalculatedResourceMods = new Dictionary<string, float>();

			private bool CalculatedResourceModsCached;

			private Dictionary<GameObject, Tuple<float, int>> KillLootModifiers = new Dictionary<GameObject, Tuple<float, int>>();

			private bool CalculatedKillLootModifiersCached;

			private Dictionary<GameObject, Tuple<float, int>> ResourceLootModifiers = new Dictionary<GameObject, Tuple<float, int>>();

			private bool CalculatedHarvestLootModifiersCached;

			public string DisplayName { get; set; }

			public DeathProgressionDetails DeathStyle { get; set; }

			public float DeathSkillRate { get; set; } = 1f;


			public Dictionary<string, DeathResourceModifier> ResourceModifiers { get; set; }

			public Dictionary<string, DeathSkillModifier> SkillModifiers { get; set; }

			public Dictionary<string, DeathLootModifier> DeathLootModifiers { get; set; }

			public List<KeyValuePair<GameObject, int>> RollKillLoot()
			{
				if (!CalculatedKillLootModifiersCached)
				{
					if (DeathLootModifiers != null && DeathLootModifiers.Count > 0)
					{
						foreach (KeyValuePair<string, DeathLootModifier> deathLootModifier in DeathLootModifiers)
						{
							if (deathLootModifier.Value.bonusActions.Contains(ResourceGainTypes.Kills))
							{
								GameObject prefab = PrefabManager.Instance.GetPrefab(deathLootModifier.Value.prefab);
								if ((Object)(object)prefab == (Object)null)
								{
									Logger.LogWarning("Could not find prefab " + deathLootModifier.Value.prefab + " while building kill loot table, it will be skipped.");
								}
								else
								{
									KillLootModifiers.Add(prefab, new Tuple<float, int>(deathLootModifier.Value.chance, deathLootModifier.Value.amount));
								}
							}
						}
					}
					CalculatedKillLootModifiersCached = true;
				}
				List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>();
				foreach (KeyValuePair<GameObject, Tuple<float, int>> killLootModifier in KillLootModifiers)
				{
					float value = Random.value;
					Logger.LogDebug($"Rolling chance loot for: {((Object)killLootModifier.Key.gameObject).name} {value} < {killLootModifier.Value.Item1}");
					if (value < killLootModifier.Value.Item1)
					{
						list.Add(new KeyValuePair<GameObject, int>(killLootModifier.Key, killLootModifier.Value.Item2));
					}
				}
				return list;
			}

			public List<KeyValuePair<GameObject, int>> RollHarvestLoot()
			{
				if (!CalculatedHarvestLootModifiersCached)
				{
					if (DeathLootModifiers != null && DeathLootModifiers.Count > 0)
					{
						foreach (KeyValuePair<string, DeathLootModifier> deathLootModifier in DeathLootModifiers)
						{
							if (deathLootModifier.Value.bonusActions.Contains(ResourceGainTypes.Harvesting))
							{
								GameObject prefab = PrefabManager.Instance.GetPrefab(deathLootModifier.Value.prefab);
								if ((Object)(object)prefab == (Object)null)
								{
									Logger.LogWarning("Could not find prefab " + deathLootModifier.Value.prefab + " while building harvest loot table, it will be skipped.");
								}
								else
								{
									ResourceLootModifiers.Add(prefab, new Tuple<float, int>(deathLootModifier.Value.chance, deathLootModifier.Value.amount));
								}
							}
						}
					}
					CalculatedHarvestLootModifiersCached = true;
				}
				List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>();
				foreach (KeyValuePair<GameObject, Tuple<float, int>> resourceLootModifier in ResourceLootModifiers)
				{
					if (Random.value < resourceLootModifier.Value.Item1)
					{
						list.Add(new KeyValuePair<GameObject, int>(resourceLootModifier.Key, resourceLootModifier.Value.Item2));
					}
				}
				return list;
			}

			public float GetResouceEarlyCache(string prefab)
			{
				if (!CalculatedResourceModsCached)
				{
					Logger.LogDebug("Building cache entry for " + prefab);
					if (ResourceModifiers != null)
					{
						foreach (KeyValuePair<string, DeathResourceModifier> resourceModifier in ResourceModifiers)
						{
							if (resourceModifier.Value.prefabs == null)
							{
								continue;
							}
							foreach (string prefab2 in resourceModifier.Value.prefabs)
							{
								Logger.LogDebug($"Building cache entry for {prefab2} - {resourceModifier.Value.bonusModifer}");
								CalculatedResourceMods.Add(prefab2, resourceModifier.Value.bonusModifer);
							}
						}
					}
					CalculatedResourceModsCached = true;
				}
				if (CalculatedResourceMods.ContainsKey(prefab))
				{
					return CalculatedResourceMods[prefab];
				}
				return 1f;
			}

			public float GetResouceEarlyCache(GameObject prefab)
			{
				if ((Object)(object)prefab == (Object)null)
				{
					return 1f;
				}
				return GetResouceEarlyCache(((Object)prefab).name);
			}

			public float GetSkillBonusLazyCache(SkillType skilltype)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Invalid comparison between Unknown and I4
				//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)
				if (CalculatedSkillMods.TryGetValue(skilltype, out var value))
				{
					return value;
				}
				float num = 0f;
				if (SkillModifiers != null && SkillModifiers.Count > 0)
				{
					foreach (KeyValuePair<string, DeathSkillModifier> skillModifier in SkillModifiers)
					{
						if ((int)skillModifier.Value.skill == 999 || skillModifier.Value.skill == skilltype)
						{
							num += skillModifier.Value.bonusModifer;
						}
					}
				}
				CalculatedSkillMods.Add(skilltype, num);
				return num;
			}

			public string GetLootModifiersDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				foreach (KeyValuePair<string, DeathLootModifier> deathLootModifier in DeathLootModifiers)
				{
					stringBuilder.AppendLine(Localization.instance.Localize(string.Format("<color={0}>{1}%</color> $loot_desc_pt1 {2} $loot_desc_pt2 {3}", "#b9f2ff", deathLootModifier.Value.chance * 100f, deathLootModifier.Key, string.Join(",", deathLootModifier.Value.bonusActions))));
				}
				return stringBuilder.ToString();
			}

			public string GetSkillModiferDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				foreach (KeyValuePair<string, DeathSkillModifier> skillModifier in SkillModifiers)
				{
					if (skillModifier.Value.bonusModifer > 1f)
					{
						stringBuilder.AppendLine(Localization.instance.Localize(string.Format("{0} +<color={1}>{2}%</color> $xp", skillModifier.Key, "#b9f2ff", Mathf.Round((skillModifier.Value.bonusModifer - 1f) * 100f))));
					}
					else
					{
						stringBuilder.AppendLine(Localization.instance.Localize(string.Format("{0} -<color={1}>{2}%</color> $xp", skillModifier.Key, "#ff4040", Mathf.Round((1f - skillModifier.Value.bonusModifer) * 100f))));
					}
				}
				return stringBuilder.ToString();
			}

			public string GetResourceModiferDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				foreach (KeyValuePair<string, DeathResourceModifier> resourceModifier in ResourceModifiers)
				{
					if (resourceModifier.Value.bonusModifer > 1f)
					{
						stringBuilder.AppendLine(Localization.instance.Localize(string.Format("{0} $drops <color={1}>{2}%</color> $more {3}", resourceModifier.Key, "#b9f2ff", (resourceModifier.Value.bonusModifer - 1f) * 100f, string.Join(",", resourceModifier.Value.bonusActions))));
					}
					else
					{
						stringBuilder.AppendLine(Localization.instance.Localize(string.Format("{0} $drops <color={1}{2}%</color> $less {3}", resourceModifier.Key, "#ff4040", (1f - resourceModifier.Value.bonusModifer) * 100f, string.Join(",", resourceModifier.Value.bonusActions))));
					}
				}
				return stringBuilder.ToString();
			}

			public string GetDeathStyleDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				switch (DeathStyle.itemLossStyle)
				{
				case ItemLossStyle.None:
					stringBuilder.AppendLine(Localization.instance.Localize("$no_item_loss"));
					break;
				case ItemLossStyle.DestroyNonWeaponArmor:
					stringBuilder.AppendLine(Localization.instance.Localize("$no_equipment_loss"));
					break;
				case ItemLossStyle.DestroyAll:
					stringBuilder.AppendLine(Localization.instance.Localize("$all_item_loss"));
					break;
				case ItemLossStyle.DeathlinkBased:
					stringBuilder.AppendLine(Localization.instance.Localize("$limited_saved_deathlink"));
					stringBuilder.AppendLine(Localization.instance.Localize(string.Format("$equipment_kept <color={0}>{1}</color> - <color={2}>{3}</color>", "#b9f2ff", DeathStyle.minEquipmentKept, "#b9f2ff", DeathStyle.maxEquipmentKept)));
					stringBuilder.AppendLine(Localization.instance.Localize(string.Format("$items_kept <color={0}>{1}</color> - <color={2}>{3}</color>", "#b9f2ff", DeathStyle.minItemsKept, "#b9f2ff", DeathStyle.maxItemsKept)));
					break;
				}
				if (DeathStyle.itemLossStyle != ItemLossStyle.DestroyAll)
				{
					if (DeathStyle.itemSavedStyle == ItemSavedStyle.OnCharacter)
					{
						stringBuilder.AppendLine(Localization.instance.Localize("$saved_to_character"));
					}
					else
					{
						stringBuilder.AppendLine(Localization.instance.Localize("$saved_to_tombstone"));
					}
					if (DeathStyle.nonSkillCheckedItemAction == NonSkillCheckedItemAction.Tombstone)
					{
						stringBuilder.AppendLine(Localization.instance.Localize("$non_skill_items_tombstone"));
					}
					if (DeathStyle.nonSkillCheckedItemAction == NonSkillCheckedItemAction.Save)
					{
						stringBuilder.AppendLine(Localization.instance.Localize("$non_skill_items_character"));
					}
					if (DeathStyle.nonSkillCheckedItemAction == NonSkillCheckedItemAction.Destroy)
					{
						stringBuilder.AppendLine(Localization.instance.Localize("$non_skill_items_destroy"));
					}
				}
				if (DeathStyle.foodLossOnDeath)
				{
					if (DeathStyle.foodLossUsesDeathlink)
					{
						stringBuilder.AppendLine(Localization.instance.Localize("$food_loss_deathlink"));
					}
					else
					{
						stringBuilder.AppendLine(Localization.instance.Localize("$food_loss"));
					}
				}
				if (DeathStyle.maxSkillLossPercentage == DeathStyle.minSkillLossPercentage)
				{
					stringBuilder.AppendLine(Localization.instance.Localize(string.Format("$skill_loss_desc <color={0}>{1}%</color>", "#ff4040", DeathStyle.maxSkillLossPercentage * 100f)));
				}
				else
				{
					stringBuilder.AppendLine(Localization.instance.Localize(string.Format("$skill_loss_desc <color={0}>{1}%</color> - <color={2}>{3}%</color> $influenced_by_deathlink", "#ff4040", DeathStyle.maxSkillLossPercentage * 100f, "#ff4040", DeathStyle.minSkillLossPercentage * 100f)));
				}
				return stringBuilder.ToString();
			}
		}

		public class DeathConfiguration
		{
			public string DeathChoiceLevel { get; set; }
		}

		public class PlayerDeathConfiguration
		{
			public Dictionary<long, DeathConfiguration> selectedDeathStyle { get; set; }
		}

		public abstract class ZNetProperty<T>
		{
			protected readonly ZNetView zNetView;

			public string Key { get; private set; }

			public T DefaultValue { get; private set; }

			protected ZNetProperty(string key, ZNetView zNetView, T defaultValue)
			{
				Key = key;
				DefaultValue = defaultValue;
				this.zNetView = zNetView;
			}

			private void ClaimOwnership()
			{
				if (!zNetView.IsOwner())
				{
					zNetView.ClaimOwnership();
				}
			}

			public void Set(T value)
			{
				SetValue(value);
			}

			public void ForceSet(T value)
			{
				ClaimOwnership();
				Set(value);
			}

			public abstract T Get();

			protected abstract void SetValue(T value);
		}

		public class BoolZNetProperty : ZNetProperty<bool>
		{
			public BoolZNetProperty(string key, ZNetView zNetView, bool defaultValue)
				: base(key, zNetView, defaultValue)
			{
			}

			public override bool Get()
			{
				return zNetView.GetZDO().GetBool(base.Key, base.DefaultValue);
			}

			protected override void SetValue(bool value)
			{
				zNetView.GetZDO().Set(base.Key, value);
			}
		}

		public class IntZNetProperty : ZNetProperty<int>
		{
			public IntZNetProperty(string key, ZNetView zNetView, int defaultValue)
				: base(key, zNetView, defaultValue)
			{
			}

			public override int Get()
			{
				return zNetView.GetZDO().GetInt(base.Key, base.DefaultValue);
			}

			protected override void SetValue(int value)
			{
				zNetView.GetZDO().Set(base.Key, value);
			}
		}

		public class StringZNetProperty : ZNetProperty<string>
		{
			public StringZNetProperty(string key, ZNetView zNetView, string defaultValue)
				: base(key, zNetView, defaultValue)
			{
			}

			public override string Get()
			{
				return zNetView.GetZDO().GetString(base.Key, base.DefaultValue);
			}

			protected override void SetValue(string value)
			{
				zNetView.GetZDO().Set(base.Key, value);
			}
		}

		public class Vector3ZNetProperty : ZNetProperty<Vector3>
		{
			public Vector3ZNetProperty(string key, ZNetView zNetView, Vector3 defaultValue)
				: base(key, zNetView, defaultValue)
			{
			}//IL_0003: Unknown result type (might be due to invalid IL or missing references)


			public override Vector3 Get()
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				return zNetView.GetZDO().GetVec3(base.Key, base.DefaultValue);
			}

			protected override void SetValue(Vector3 value)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				zNetView.GetZDO().Set(base.Key, value);
			}
		}

		public class DictionaryZNetProperty : ZNetProperty<Dictionary<SkillType, float>>
		{
			private BinaryFormatter binFormatter = new BinaryFormatter();

			public DictionaryZNetProperty(string key, ZNetView zNetView, Dictionary<SkillType, float> defaultValue)
				: base(key, zNetView, defaultValue)
			{
			}

			public override Dictionary<SkillType, float> Get()
			{
				byte[] byteArray = zNetView.GetZDO().GetByteArray(base.Key, (byte[])null);
				if (byteArray == null)
				{
					return new Dictionary<SkillType, float>();
				}
				MemoryStream serializationStream = new MemoryStream(byteArray);
				return (Dictionary<SkillType, float>)binFormatter.Deserialize(serializationStream);
			}

			protected override void SetValue(Dictionary<SkillType, float> value)
			{
				MemoryStream memoryStream = new MemoryStream();
				binFormatter.Serialize(memoryStream, value);
				zNetView.GetZDO().Set(base.Key, memoryStream.ToArray());
			}

			public void UpdateDictionary()
			{
			}
		}

		public class ZDOIDZNetProperty : ZNetProperty<ZDOID>
		{
			public ZDOIDZNetProperty(string key, ZNetView zNetView, ZDOID defaultValue)
				: base(key, zNetView, defaultValue)
			{
			}//IL_0003: Unknown result type (might be due to invalid IL or missing references)


			public override ZDOID Get()
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				return zNetView.GetZDO().GetZDOID(base.Key);
			}

			protected override void SetValue(ZDOID value)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				zNetView.GetZDO().Set(base.Key, value);
			}
		}

		public static IDeserializer yamldeserializer = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build();

		public static ISerializer yamlserializer = ((BuilderSkeleton<SerializerBuilder>)new SerializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).DisableAliases().ConfigureDefaultValuesHandling((DefaultValuesHandling)2)
			.Build();

		public static readonly string DeathChoiceKey = "DL_DeathChoice";

		private const string color_good = "#b9f2ff";

		private const string color_bad = "#ff4040";
	}
	internal static class DeathConfigurationData
	{
		[HarmonyPatch(typeof(Player))]
		public static class SetupPlayerDeathlink
		{
			[HarmonyPostfix]
			[HarmonyPatch("OnSpawned")]
			private static void Postfix(Player __instance)
			{
				CheckAndSetPlayerDeathConfig();
			}
		}

		public static readonly Dictionary<string, DataObjects.DeathChoiceLevel> defaultDeathLevels = new Dictionary<string, DataObjects.DeathChoiceLevel>
		{
			{
				"Vanilla",
				new DataObjects.DeathChoiceLevel
				{
					DisplayName = "Vanilla",
					DeathStyle = new DataObjects.DeathProgressionDetails
					{
						itemLossStyle = DataObjects.ItemLossStyle.None,
						foodLossOnDeath = true,
						itemSavedStyle = DataObjects.ItemSavedStyle.Tombstone,
						minSkillLossPercentage = 0.05f,
						maxSkillLossPercentage = 0.05f
					},
					DeathLootModifiers = new Dictionary<string, DataObjects.DeathLootModifier>(),
					ResourceModifiers = new Dictionary<string, DataObjects.DeathResourceModifier>(),
					SkillModifiers = new Dictionary<string, DataObjects.DeathSkillModifier>()
				}
			},
			{
				"Rougelike1",
				new DataObjects.DeathChoiceLevel
				{
					DisplayName = "ShieldBearer",
					DeathStyle = new DataObjects.DeathProgressionDetails
					{
						itemLossStyle = DataObjects.ItemLossStyle.DeathlinkBased,
						foodLossUsesDeathlink = true,
						itemSavedStyle = DataObjects.ItemSavedStyle.Tombstone,
						minEquipmentKept = 3,
						maxEquipmentKept = 9,
						minItemsKept = 3,
						maxItemsKept = 15,
						minSkillLossPercentage = 0.03f,
						maxSkillLossPercentage = 0.13f
					},
					DeathLootModifiers = new Dictionary<string, DataObjects.DeathLootModifier>(),
					ResourceModifiers = new Dictionary<string, DataObjects.DeathResourceModifier> { 
					{
						"Wood",
						new DataObjects.DeathResourceModifier
						{
							prefabs = new List<string> { "Wood", "FineWood", "RoundLog", "YggdrasilWood", "Blackwood" },
							bonusModifer = 1.1f,
							bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Harvesting }
						}
					} },
					SkillModifiers = new Dictionary<string, DataObjects.DeathSkillModifier> { 
					{
						"All",
						new DataObjects.DeathSkillModifier
						{
							bonusModifer = 1.05f,
							skill = (SkillType)999
						}
					} }
				}
			},
			{
				"Rougelike2",
				new DataObjects.DeathChoiceLevel
				{
					DisplayName = "Raider",
					DeathStyle = new DataObjects.DeathProgressionDetails
					{
						itemLossStyle = DataObjects.ItemLossStyle.DeathlinkBased,
						itemSavedStyle = DataObjects.ItemSavedStyle.Tombstone,
						minEquipmentKept = 2,
						maxEquipmentKept = 6,
						minSkillLossPercentage = 0.02f,
						maxSkillLossPercentage = 0.14f
					},
					DeathLootModifiers = new Dictionary<string, DataObjects.DeathLootModifier>(),
					ResourceModifiers = new Dictionary<string, DataObjects.DeathResourceModifier>
					{
						{
							"Wood",
							new DataObjects.DeathResourceModifier
							{
								prefabs = new List<string> { "Wood", "FineWood", "RoundLog", "YggdrasilWood", "Blackwood" },
								bonusModifer = 1.2f,
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Harvesting }
							}
						},
						{
							"Ore",
							new DataObjects.DeathResourceModifier
							{
								prefabs = new List<string> { "CopperOre", "TinOre", "IronScrap", "SilverOre", "BlackMetalScrap", "CopperScrap", "FlametalOreNew" },
								bonusModifer = 1.2f,
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Harvesting }
							}
						}
					},
					SkillModifiers = new Dictionary<string, DataObjects.DeathSkillModifier> { 
					{
						"All",
						new DataObjects.DeathSkillModifier
						{
							bonusModifer = 1.1f,
							skill = (SkillType)999
						}
					} }
				}
			},
			{
				"Rougelike3",
				new DataObjects.DeathChoiceLevel
				{
					DisplayName = "Berserker",
					DeathStyle = new DataObjects.DeathProgressionDetails
					{
						itemLossStyle = DataObjects.ItemLossStyle.DeathlinkBased,
						itemSavedStyle = DataObjects.ItemSavedStyle.OnCharacter,
						minEquipmentKept = 0,
						maxEquipmentKept = 3,
						minSkillLossPercentage = 0.05f,
						maxSkillLossPercentage = 0.2f
					},
					DeathLootModifiers = new Dictionary<string, DataObjects.DeathLootModifier> { 
					{
						"AmberPearl",
						new DataObjects.DeathLootModifier
						{
							chance = 0.05f,
							prefab = "AmberPearl",
							bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Kills }
						}
					} },
					ResourceModifiers = new Dictionary<string, DataObjects.DeathResourceModifier>
					{
						{
							"Wood",
							new DataObjects.DeathResourceModifier
							{
								prefabs = new List<string> { "Wood", "FineWood", "RoundLog", "YggdrasilWood", "Blackwood" },
								bonusModifer = 1.5f,
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Harvesting }
							}
						},
						{
							"Ore",
							new DataObjects.DeathResourceModifier
							{
								prefabs = new List<string> { "CopperOre", "TinOre", "IronScrap", "SilverOre", "BlackMetalScrap", "CopperScrap", "FlametalOreNew" },
								bonusModifer = 1.5f,
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Harvesting }
							}
						}
					},
					SkillModifiers = new Dictionary<string, DataObjects.DeathSkillModifier> { 
					{
						"All",
						new DataObjects.DeathSkillModifier
						{
							bonusModifer = 1.2f,
							skill = (SkillType)999
						}
					} }
				}
			},
			{
				"Hardcore",
				new DataObjects.DeathChoiceLevel
				{
					DisplayName = "Deathbringer",
					DeathStyle = new DataObjects.DeathProgressionDetails
					{
						itemLossStyle = DataObjects.ItemLossStyle.DestroyAll,
						minSkillLossPercentage = 0.05f,
						maxSkillLossPercentage = 0.25f
					},
					DeathLootModifiers = new Dictionary<string, DataObjects.DeathLootModifier>
					{
						{
							"AmberPearl",
							new DataObjects.DeathLootModifier
							{
								chance = 0.05f,
								prefab = "AmberPearl",
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Kills }
							}
						},
						{
							"SmallHealthPotion",
							new DataObjects.DeathLootModifier
							{
								chance = 0.01f,
								prefab = "MeadHealthMinor",
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Kills }
							}
						}
					},
					ResourceModifiers = new Dictionary<string, DataObjects.DeathResourceModifier>
					{
						{
							"Wood",
							new DataObjects.DeathResourceModifier
							{
								prefabs = new List<string> { "Wood", "FineWood", "RoundLog", "YggdrasilWood", "Blackwood" },
								bonusModifer = 2f,
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Harvesting }
							}
						},
						{
							"Stone",
							new DataObjects.DeathResourceModifier
							{
								prefabs = new List<string> { "Flint", "Stone", "BlackMarble", "Grausten" },
								bonusModifer = 2f,
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Harvesting }
							}
						},
						{
							"Ore",
							new DataObjects.DeathResourceModifier
							{
								prefabs = new List<string> { "CopperOre", "TinOre", "IronScrap", "SilverOre", "BlackMetalScrap", "CopperScrap", "FlametalOreNew" },
								bonusModifer = 2f,
								bonusActions = new List<DataObjects.ResourceGainTypes> { DataObjects.ResourceGainTypes.Harvesting }
							}
						}
					},
					SkillModifiers = new Dictionary<string, DataObjects.DeathSkillModifier> { 
					{
						"All",
						new DataObjects.DeathSkillModifier
						{
							bonusModifer = 1.3f,
							skill = (SkillType)999
						}
					} }
				}
			}
		};

		public static Dictionary<long, DataObjects.DeathConfiguration> playerSettings = new Dictionary<long, DataObjects.DeathConfiguration>();

		public static Dictionary<string, DataObjects.DeathChoiceLevel> DeathLevels = defaultDeathLevels;

		public static DataObjects.DeathChoiceLevel playerDeathConfiguration = new DataObjects.DeathChoiceLevel
		{
			DeathStyle = new DataObjects.DeathProgressionDetails
			{
				foodLossOnDeath = true,
				foodLossUsesDeathlink = false,
				itemLossStyle = DataObjects.ItemLossStyle.None,
				minItemsKept = 0,
				maxItemsKept = 0,
				minEquipmentKept = 0,
				maxEquipmentKept = 0,
				skillLossOnDeath = true,
				maxSkillLossPercentage = 0.05f,
				minSkillLossPercentage = 0.05f,
				itemSavedStyle = DataObjects.ItemSavedStyle.Tombstone,
				nonSkillCheckedItemAction = DataObjects.NonSkillCheckedItemAction.Tombstone
			}
		};

		internal static void Init()
		{
			try
			{
				UpdateDeathLevelsConfig(File.ReadAllText(ValConfig.deathChoicesPath));
			}
			catch (Exception arg)
			{
				Logger.LogWarning((object)$"There was an error updating the Death choice Level values, defaults will be used. Exception: {arg}");
			}
			try
			{
				UpdatePlayerConfigSettings(File.ReadAllText(ValConfig.playerSettingsPath));
			}
			catch (Exception arg2)
			{
				Logger.LogWarning((object)$"There was an error updating the player choice configs, defaults will be used. Exception: {arg2}");
			}
		}

		public static void CheckAndSetPlayerDeathConfig()
		{
			Player localPlayer = Player.m_localPlayer;
			if (ValConfig.UsePrivateKeysForDeathChoice.Value && (Object)(object)localPlayer != (Object)null)
			{
				Logger.LogDebug("Checking private keys configurations for Deathlink");
				if (localPlayer.PlayerHasUniqueKey(DataObjects.DeathChoiceKey))
				{
					string text = default(string);
					localPlayer.TryGetUniqueKeyValue(DataObjects.DeathChoiceKey, ref text);
					if (DeathLevels.ContainsKey(text))
					{
						Logger.LogDebug("Player deathlink configurations set " + text);
						playerDeathConfiguration = DeathLevels[text];
					}
					else
					{
						Logger.LogDebug("Player preference setting is not an available config, removing player choice.");
						localPlayer.PlayerRemoveUniqueKey(DataObjects.DeathChoiceKey);
						CheckAndSetPlayerDeathConfig();
					}
				}
				else
				{
					Logger.LogDebug("No private key set for deathlink configuration, checking yaml config fallback");
					CheckYamlConfig();
				}
			}
			else
			{
				CheckYamlConfig();
			}
		}

		internal static void CheckYamlConfig()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				Logger.LogWarning("Local player not defined, skipping setup.");
				Logger.LogDebug("Player preference setting is not an available config, using fallback " + DeathLevels.First().Key);
				playerDeathConfiguration = DeathLevels.First().Value;
				return;
			}
			long playerID = Player.m_localPlayer.GetPlayerID();
			Logger.LogDebug($"Setting up Deathlink player configuration with id {playerID}");
			Logger.LogDebug(string.Format("Checking stored configurations for {0} {1}", playerID, string.Join(",", playerSettings.Keys)));
			if (playerSettings.ContainsKey(playerID))
			{
				string deathChoiceLevel = playerSettings[playerID].DeathChoiceLevel;
				if (DeathLevels.ContainsKey(deathChoiceLevel))
				{
					Logger.LogDebug("Player deathlink configurations set " + deathChoiceLevel);
					playerDeathConfiguration = DeathLevels[deathChoiceLevel];
				}
				else
				{
					Logger.LogDebug("Player preference setting is not an available config, using fallback");
					playerDeathConfiguration = DeathLevels.First().Value;
				}
			}
		}

		public static string PlayerSettingsDefaultConfig()
		{
			return DataObjects.yamlserializer.Serialize((object)playerSettings);
		}

		public static string DeathLevelsYamlDefaultConfig()
		{
			return DataObjects.yamlserializer.Serialize((object)DeathLevels);
		}

		public static void WriteDeathChoices()
		{
			File.WriteAllText(ValConfig.deathChoicesPath, DataObjects.yamlserializer.Serialize((object)DeathLevels));
		}

		public static void WritePlayerChoices()
		{
			File.WriteAllText(ValConfig.playerSettingsPath, DataObjects.yamlserializer.Serialize((object)playerSettings));
		}

		public static void UpdateDeathLevelsConfig(string rawyaml)
		{
			DeathLevels = DataObjects.yamldeserializer.Deserialize<Dictionary<string, DataObjects.DeathChoiceLevel>>(rawyaml);
		}

		public static void UpdatePlayerConfigSettings(string rawyaml)
		{
			foreach (KeyValuePair<long, DataObjects.DeathConfiguration> item in DataObjects.yamldeserializer.Deserialize<Dictionary<long, DataObjects.DeathConfiguration>>(rawyaml))
			{
				if (!playerSettings.ContainsKey(item.Key))
				{
					playerSettings.Add(item.Key, item.Value);
				}
			}
		}
	}
	internal static class Utils
	{
		public static CodeMatcher CreateLabelOffset(this CodeMatcher matcher, out Label label, int offset = 0)
		{
			return matcher.CreateLabelAt(matcher.Pos + offset, ref label);
		}

		public static bool PlayerHasUniqueKey(this Player player, string key)
		{
			foreach (string uniqueKey in player.GetUniqueKeys())
			{
				if (uniqueKey.StartsWith(key))
				{
					return true;
				}
			}
			return false;
		}

		public static bool PlayerRemoveUniqueKey(this Player player, string key)
		{
			foreach (string uniqueKey in player.GetUniqueKeys())
			{
				if (uniqueKey.StartsWith(key))
				{
					((Humanoid)player).RemoveUniqueKey(uniqueKey);
					return true;
				}
			}
			return false;
		}

		public static void SafeInsertOrAppend(this Dictionary<DataObjects.ItemResults, List<ItemData>> dict, DataObjects.ItemResults key, List<ItemData> value)
		{
			if (!dict.ContainsKey(key))
			{
				dict.Add(key, value);
			}
			else
			{
				dict[key].AddRange(value);
			}
		}

		public static void SafeInsertOrAppend(this Dictionary<DataObjects.ItemResults, List<ItemData>> dict, DataObjects.ItemResults key, ItemData value)
		{
			if (!dict.ContainsKey(key))
			{
				dict.Add(key, new List<ItemData> { value });
			}
			else
			{
				dict[key].Add(value);
			}
		}
	}
	public class ValConfig
	{
		[CompilerGenerated]
		private sealed class <OnClientReceiveDeathChoiceConfigs>d__31 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public ZPackage package;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <OnClientReceiveDeathChoiceConfigs>d__31(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					DeathConfigurationData.UpdateDeathLevelsConfig(package.ReadString());
					DeathConfigurationData.WriteDeathChoices();
					DeathConfigurationData.CheckAndSetPlayerDeathConfig();
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <OnClientReceivePlayerSettingsConfigs>d__34 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public ZPackage package;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <OnClientReceivePlayerSettingsConfigs>d__34(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					DeathConfigurationData.UpdatePlayerConfigSettings(package.ReadString());
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed