Decompiled source of CreatureLevelAndLootControl PTBR v0.1.0

CreaturePTBR.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ServerSync;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: Guid("6363d416-d2b3-437d-8f72-ed0069245f86")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("CreatureLevelControl")]
[assembly: AssemblyTitle("CreatureLevelControl")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/CreatureLevelAndLootControl")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: <6c79ef52-1d18-4a52-b86b-be9360ea1262>RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<97c74bb4-9272-4b0e-a1bd-099c0a59de49>Embedded]
	internal sealed class <97c74bb4-9272-4b0e-a1bd-099c0a59de49>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[<97c74bb4-9272-4b0e-a1bd-099c0a59de49>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <75b8e597-2006-46dc-8007-b4ba3b036dbf>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <75b8e597-2006-46dc-8007-b4ba3b036dbf>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <75b8e597-2006-46dc-8007-b4ba3b036dbf>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[<97c74bb4-9272-4b0e-a1bd-099c0a59de49>Embedded]
	[CompilerGenerated]
	internal sealed class <a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[<97c74bb4-9272-4b0e-a1bd-099c0a59de49>Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class <6c79ef52-1d18-4a52-b86b-be9360ea1262>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <6c79ef52-1d18-4a52-b86b-be9360ea1262>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CreatureLevelControl
{
	public enum CreatureExtraEffect
	{
		None,
		Aggressive,
		Quick,
		Regenerating,
		Curious,
		Splitting,
		Armored
	}
	public enum CreatureInfusion
	{
		None,
		Lightning,
		Fire,
		Frost,
		Poison,
		Chaos,
		Spirit
	}
	public enum BossAffix
	{
		None,
		Reflective,
		Shielded,
		Mending,
		Summoner,
		Elementalist,
		Enraged,
		Twin
	}
	[PublicAPI]
	[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
	[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)]
	public static class API
	{
		public static bool IsEnabled()
		{
			return true;
		}

		public static bool IsInfusionEnabled()
		{
			return CreatureLevelControl.creatureInfusionEffects.GetToggle();
		}

		public static bool IsExtraEffectEnabled()
		{
			return CreatureLevelControl.creatureSpecialEffects.GetToggle();
		}

		public static bool IsAffixEnabled()
		{
			return CreatureLevelControl.bossSpecialEffects.GetToggle();
		}

		public static int GetWorldLevel()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)Game.instance))
			{
				return 0;
			}
			int result = CreatureLevelControl.worldLevels.Count;
			if (CreatureLevelControl.difficultySecondFactor.Value == CreatureLevelControl.DifficultySecondFactor.Distance)
			{
				Vector3 val = default(Vector3);
				ZoneSystem.instance.GetLocationIcon(Game.instance.m_StartLocation, ref val);
				Player localPlayer = Player.m_localPlayer;
				Vector3 val2 = (Vector3)((localPlayer != null) ? ((Component)localPlayer).transform.localPosition : default(Vector3)) - val;
				float num = Mathf.Sqrt(Mathf.Pow(val2.x, 2f) + Mathf.Pow(val2.z, 2f));
				foreach (ConfigEntry<int> key in CreatureLevelControl.spawnDistance.Keys)
				{
					if (num < (float)key.Value)
					{
						result = CreatureLevelControl.spawnDistance[key];
						break;
					}
				}
			}
			else if (CreatureLevelControl.difficultySecondFactor.Value != CreatureLevelControl.DifficultySecondFactor.Age_of_world)
			{
				result = ((CreatureLevelControl.difficultySecondFactor.Value != CreatureLevelControl.DifficultySecondFactor.BossesKilled) ? 3 : new string[6] { "eikthyr", "gdking", "bonemass", "dragon", "goblinking", "queen" }.Count([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string boss) => ZoneSystem.instance.GetGlobalKey("defeated_" + boss)));
			}
			else
			{
				int day = EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds());
				foreach (ConfigEntry<int> key2 in CreatureLevelControl.worldLevels.Keys)
				{
					if (day < key2.Value)
					{
						result = CreatureLevelControl.worldLevels[key2];
						break;
					}
				}
			}
			return result;
		}

		internal static float[] zeroProbabilities(float[] p, int shift = 0)
		{
			float num = 100f;
			for (int i = 0; i < p.Length; i++)
			{
				num -= p[i];
				if (num < 0f)
				{
					p[i] += num;
					num = 0f;
				}
			}
			float[] array = new float[shift + 1].Concat(p).ToArray();
			array[shift] = num;
			return array;
		}

		public static float[] LevelProbabilities([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] Character character, int worldLevel, bool includeZoneBonusLevel)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			int num;
			if (!includeZoneBonusLevel)
			{
				num = 0;
			}
			else
			{
				object obj;
				if (character == null)
				{
					obj = null;
				}
				else
				{
					ZNetView component = ((Component)character).GetComponent<ZNetView>();
					obj = ((component != null) ? component.GetZDO() : null);
				}
				num = ((obj == null) ? CreatureSector.sectorBonusLevel(((Component)Player.m_localPlayer).GetComponent<ZNetView>().GetZDO().GetSector()) : CreatureSector.sectorBonusLevel(character));
			}
			int num2 = num;
			if ((Object)(object)character != (Object)null)
			{
				float[] array = Utils.ReadWithWorldLevelFromConfig(character, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToStars);
				if (array != null)
				{
					return zeroProbabilities(array, (!character.IsBoss()) ? num2 : 0);
				}
			}
			if (character != null && character.IsBoss() && !CreatureLevelControl.bossLevelUseCreatureLevel.GetToggle())
			{
				return zeroProbabilities(Utils.ParseStringProbabilities(CreatureLevelControl.customBossLevelChances.Value));
			}
			if (CreatureLevelControl.difficulty.Value == CreatureLevelControl.Difficulty.Custom)
			{
				return zeroProbabilities(Utils.ParseStringProbabilities(CreatureLevelControl.customLevelChances[worldLevel].Value), num2);
			}
			if (!CreatureLevelControl.levelConfig.TryGetValue(CreatureLevelControl.difficulty.Value, out var value))
			{
				value = CreatureLevelControl.levelConfig[CreatureLevelControl.Difficulty.Medium];
			}
			float[] source = zeroProbabilities(value[worldLevel], num2);
			int value2 = (int)CreatureLevelControl.minimumLevel.Value;
			int num3 = Math.Max(value2, (int)CreatureLevelControl.maximumLevel.Value);
			float num4 = source.Take(value2).Sum();
			float num5 = source.Skip(1 + num3).Sum();
			source = new float[value2].Concat(source.Skip(value2).Take(1 + num3 - value2)).ToArray();
			source[value2] += num4;
			if (num5 > 0f)
			{
				source = source.Concat(new float[Mathf.Max(0, 1 + num3 - source.Length)]).ToArray();
				source[num3] += num5;
			}
			return source;
		}

		public static int LevelRand(Character character)
		{
			return Utils.LevelFromProbabilities(LevelProbabilities(character, GetWorldLevel(), includeZoneBonusLevel: true));
		}

		public static bool HasAffixBoss(Character character)
		{
			return HasExtraEffectCreature(character);
		}

		public static BossAffix GetAffixBoss(Character character)
		{
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			if (!CreatureLevelControl.bossSpecialEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null)
			{
				return BossAffix.None;
			}
			return (BossAffix)component.GetZDO().GetInt("CL&LC effect", 0);
		}

		public static void SetAffixBoss(Character character, BossAffix affix)
		{
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			string[] source = new string[7] { "Eikthyr", "gd_king", "Bonemass", "Dragon", "GoblinKing", "SeekerQueen", "Fader" };
			if (affix == BossAffix.Summoner && !source.Contains(((Object)character).name.Replace("(Clone)", "")))
			{
				affix = BossAffix.None;
			}
			if (GetAffixBoss(character) == BossAffix.Twin)
			{
				if (affix != BossAffix.Twin)
				{
					Character twinBoss = GetTwinBoss(character);
					GameObject val = ((twinBoss != null) ? ((Component)twinBoss).gameObject : null);
					if (val != null)
					{
						ZNetScene.instance.Destroy(val);
					}
				}
				float num = Utils.ReadValueFromEnumWithWorldLevelAndStarsFromConfig(character, BossAffix.Twin, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 2 })] (CreatureConfig c) => c.worldLevelToBossAffixFactor) ?? (CreatureLevelControl.bossAffixPowerTwin.Value / 100f);
				character.m_health /= num;
				character.SetupMaxHealth();
			}
			else if (affix == BossAffix.Twin)
			{
				if (CreatureLevelControl.bossSpecialEffects.GetToggle())
				{
					float num2 = Utils.ReadValueFromEnumWithWorldLevelAndStarsFromConfig(character, BossAffix.Twin, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 2 })] (CreatureConfig c) => c.worldLevelToBossAffixFactor) ?? (CreatureLevelControl.bossAffixPowerTwin.Value / 100f);
					character.m_health *= num2;
					character.SetupMaxHealth();
					setAffixBossZDO(character, affix);
					ZPackage val2 = new ZPackage();
					character.m_nview.GetZDO().Serialize(val2);
					val2.SetPos(0);
					ZDO val3 = new ZDO();
					val3.Init();
					val3.m_uid = Utils.GenerateNewZDOID();
					val3.Deserialize(val2);
					val3.SetRotation(Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
					val3.SetPosition(((Component)character).transform.localPosition + Random.insideUnitSphere * 0.5f);
					val3.SetOwnerInternal(ZDOMan.GetSessionID());
					ZDOMan.instance.m_objectsByID.Add(val3.m_uid, val3);
					Character component = ZNetScene.instance.CreateObject(val3).GetComponent<Character>();
					Vector3 insideUnitSphere = Random.insideUnitSphere;
					if (insideUnitSphere.y < 0f)
					{
						insideUnitSphere.y = 0f - insideUnitSphere.y;
					}
					((Component)component).GetComponent<Rigidbody>().AddForce(insideUnitSphere * 5f, (ForceMode)2);
					CreatureLevelControl.SetTwinBoss(character, component);
				}
				else
				{
					affix = BossAffix.None;
				}
			}
			setAffixBossZDO(character, affix);
			OriginalCharacterData component2 = ((Component)character).GetComponent<OriginalCharacterData>();
			if (component2 != null)
			{
				component2.Awake();
			}
			else
			{
				((Component)character).gameObject.AddComponent<OriginalCharacterData>();
			}
			CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character);
		}

		private static void setAffixBossZDO(Character character, BossAffix affix)
		{
			((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC effect", (int)affix);
		}

		public static bool HasExtraEffectCreature(Character character)
		{
			return ((Component)character).GetComponent<ZNetView>().GetZDO().GetInt("CL&LC effect", -1) != -1;
		}

		public static CreatureExtraEffect GetExtraEffectCreature(Character character)
		{
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			if (!CreatureLevelControl.creatureSpecialEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null || character.GetLevel() <= 1)
			{
				return CreatureExtraEffect.None;
			}
			return (CreatureExtraEffect)component.GetZDO().GetInt("CL&LC effect", 0);
		}

		public static void SetExtraEffectCreature(Character character)
		{
			float rand;
			HashSet<CreatureExtraEffect> processedProbabilities;
			CreatureExtraEffect? creatureExtraEffect = Utils.RandomWithProbabilityFromConfig(character, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToCreatureEffect, out rand, out processedProbabilities);
			if (!creatureExtraEffect.HasValue)
			{
				creatureExtraEffect = CreatureExtraEffect.None;
				foreach (CreatureExtraEffect key in CreatureLevelControl.customCreatureAffixChances.Keys)
				{
					if (!processedProbabilities.Contains(key))
					{
						rand -= CreatureLevelControl.customCreatureAffixChances[key].Value;
						if (rand < 0f)
						{
							creatureExtraEffect = key;
							break;
						}
					}
				}
			}
			SetExtraEffectCreature(character, creatureExtraEffect.Value);
		}

		public static void SetExtraEffectCreature(Character character, CreatureExtraEffect effect)
		{
			((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC effect", (int)effect);
			CreatureLevelControl.SetPersistedCharacterAttributes(character);
			CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character);
		}

		public static bool HasInfusionCreature(Character character)
		{
			return ((Component)character).GetComponent<ZNetView>().GetZDO().GetInt("CL&LC infusion", -1) != -1;
		}

		public static CreatureInfusion GetInfusionCreature(Character character)
		{
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			if (!CreatureLevelControl.creatureInfusionEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null)
			{
				return CreatureInfusion.None;
			}
			return (CreatureInfusion)component.GetZDO().GetInt("CL&LC infusion", 0);
		}

		public static void SetInfusionCreature(Character character)
		{
			float rand;
			HashSet<CreatureInfusion> processedProbabilities;
			CreatureInfusion? creatureInfusion = Utils.RandomWithProbabilityFromConfig(character, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToInfusion, out rand, out processedProbabilities);
			CreatureInfusion infusion;
			if (creatureInfusion.HasValue)
			{
				infusion = creatureInfusion.GetValueOrDefault();
			}
			else
			{
				infusion = CreatureInfusion.None;
				if (!CreatureLevelControl.infusionProbabilityModifiersByLevel.TryGetValue(character.GetLevel(), out var value))
				{
					value = 1f;
				}
				if (Random.Range(0f, 1f) <= value)
				{
					foreach (CreatureInfusion key in CreatureLevelControl.customCreatureInfusionChances.Keys)
					{
						if (!processedProbabilities.Contains(key))
						{
							rand -= CreatureLevelControl.customCreatureInfusionChances[key].Value;
							if (rand < 0f)
							{
								infusion = key;
								break;
							}
						}
					}
				}
			}
			SetInfusionCreature(character, infusion);
		}

		public static void SetInfusionCreature(Character character, CreatureInfusion infusion)
		{
			((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC infusion", (int)infusion);
			OriginalCharacterData component = ((Component)character).GetComponent<OriginalCharacterData>();
			if (component != null)
			{
				component.immutableExtra = true;
			}
			CreatureLevelControl.AttachInfusionFlames(character);
			CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character);
		}

		[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)]
		public static Character GetTwinBoss(Character boss)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			ZDOID zDOID = ((Component)boss).GetComponent<ZNetView>().GetZDO().GetZDOID("CL&LC twin boss");
			if (ZDOMan.instance.m_objectsByID.TryGetValue(zDOID, out var value) && ZNetScene.s_instance.m_instances.TryGetValue(value, out var value2))
			{
				return ((Component)value2).GetComponent<Character>();
			}
			return null;
		}

		public static bool DropItemOnDeath(ItemData item)
		{
			bool? flag = Utils.ReadWithWorldLevelFromConfig(item, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] (ItemConfig c) => c.worldLevelToItemLoss);
			if (!flag.HasValue)
			{
				if (!item.m_shared.m_questItem)
				{
					return !item.m_equipped;
				}
				return false;
			}
			return flag.GetValueOrDefault();
		}
	}
	[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
	[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
	public class ConfigurationManagerAttributes
	{
		public bool? ShowRangeAsPercent;

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1 })]
		public Action<ConfigEntryBase> CustomDrawer;

		public bool? Browsable;

		public string Category;

		public object DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string Description;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 1 })]
		public Func<object, string> ObjToStr;

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 1 })]
		public Func<string, object> StrToObj;
	}
	[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
	[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)]
	public abstract class ConfigFile
	{
		public interface Loader
		{
			[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)]
			ConfigFile ConfigFile
			{
				[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
				get;
				[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
				set;
			}

			string FilePattern { get; }

			string EditButtonName { get; }

			CustomSyncedValue<List<string>> FileData { get; }

			bool Enabled { get; }

			ConfigFile InstantiateConfig();

			void ProcessConfig();
		}

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
		protected class Section : IDisposable
		{
			[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)]
			private readonly Section lastSection;

			[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
			private readonly Dictionary<string, object> dict;

			public readonly string dictKey;

			private readonly HashSet<string> knownKeys = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);

			private readonly ConfigFile configFile;

			public string Path => ((lastSection == null || lastSection.dictKey == "") ? "" : (lastSection.Path + ".")) + dictKey;

			public Section([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] Dictionary<string, object> dict, string key, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] Section lastSection, ConfigFile file)
			{
				this.dict = dict;
				dictKey = key;
				this.lastSection = lastSection;
				configFile = file;
			}

			[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)]
			public object Get(string key)
			{
				knownKeys.Add(key);
				if (dict.TryGetValue(key, out var value) && value == null)
				{
					configFile.configErrors.Add(Path + "." + key + " cannot be empty");
				}
				return value;
			}

			public IEnumerable<string> KeysWithPrefix(string prefix)
			{
				return dict.Keys.Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string k) => k.StartsWith(prefix));
			}

			public void Dispose()
			{
				IEnumerable<string> enumerable = dict.Keys.Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string key) => !knownKeys.Contains(key)).ToArray();
				if (enumerable.Any())
				{
					configFile.configWarnings.Add(Path + " contains unknown keys " + string.Join(", ", enumerable));
				}
			}
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		protected delegate bool ParserDelegate<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] ref T target, Section sect, string key);

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
		private struct ParseResult<T>
		{
			[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)]
			public T value;

			public string error;
		}

		public static readonly Loader[] loaders = new Loader[2]
		{
			new CreatureConfig.Loader(),
			new ItemConfig.Loader()
		};

		public readonly List<string> configErrors = new List<string>();

		public readonly List<string> configWarnings = new List<string>();

		protected readonly Dictionary<string, List<string>> groups = new Dictionary<string, List<string>>();

		public void DumpWarnings(string prefix)
		{
			if (configWarnings.Count > 0)
			{
				Debug.LogWarning((object)(prefix + ((configErrors.Count > 0) ? "" : " The config file was loaded, but may not yield expected results due to warnings:") + "\n" + string.Join("\n", configWarnings)));
				configWarnings.Clear();
			}
		}

		protected void AssignConfig<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] T>(ref T newConfig, T inConfig) where T : class
		{
			if (newConfig == null)
			{
				newConfig = inConfig;
			}
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		protected void AssignConfig<T>(ref T? newConfig, T? inConfig) where T : struct
		{
			T? val = newConfig;
			if (!val.HasValue)
			{
				newConfig = inConfig;
			}
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
		protected void AssignEnumConfig<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 1, 2 })] ref Dictionary<int, Dictionary<T, float[]>> newConfig, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 1, 2 })] Dictionary<int, Dictionary<T, float[]>> inConfig)
		{
			if (inConfig == null)
			{
				return;
			}
			if (newConfig == null)
			{
				newConfig = inConfig.ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<int, Dictionary<T, float[]>> kv) => kv.Key, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<int, Dictionary<T, float[]>> kv) => kv.Value.ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<T, float[]> k) => k.Key, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<T, float[]> k) => k.Value));
			}
			foreach (KeyValuePair<int, Dictionary<T, float[]>> item in inConfig)
			{
				if (!newConfig.ContainsKey(item.Key))
				{
					newConfig[item.Key] = item.Value;
					continue;
				}
				foreach (KeyValuePair<T, float[]> item2 in item.Value)
				{
					if (!newConfig[item.Key].ContainsKey(item2.Key))
					{
						newConfig[item.Key][item2.Key] = item2.Value;
					}
				}
			}
		}

		protected void resolveGroupsForName(List<string> groupNames, string name)
		{
			foreach (KeyValuePair<string, List<string>> group in groups)
			{
				if (!groupNames.Contains(group.Key) && group.Value.Contains(name))
				{
					groupNames.Add(group.Key);
					resolveGroupsForName(groupNames, group.Key);
				}
			}
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
		protected void fillWorldLevels<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1 })] Dictionary<int, T> config)
		{
			if (config == null)
			{
				return;
			}
			T value = default(T);
			int num = -1;
			for (int i = 0; i <= CreatureLevelControl.defaultWorldLevelDays.Length; i++)
			{
				if (config.TryGetValue(i, out var value2))
				{
					value = value2;
					if (num == -1)
					{
						num = i;
					}
				}
				else if (num != -1)
				{
					config[i] = value;
				}
			}
			for (int j = 0; j < num; j++)
			{
				config[j] = config[num];
			}
		}

		[PublicAPI]
		[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		protected static Dictionary<string, object> castDictToStringDict([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> dict)
		{
			return new Dictionary<string, object>(dict.ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<object, object> kv) => kv.Key.ToString(), [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<object, object> kv) => kv.Value), StringComparer.CurrentCultureIgnoreCase);
		}

		[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)]
		protected Section section(Section parent, string key)
		{
			object obj = parent.Get(key);
			if (obj is Dictionary<object, object> dict)
			{
				return new Section(castDictToStringDict(dict), key, parent, this);
			}
			if (obj != null)
			{
				configWarnings.Add($"Expected a section containing further configuration values, got {obj.GetType()} for {parent.Path}.{key}");
			}
			return null;
		}

		public void Parse(object configObj)
		{
			if (configObj is Dictionary<object, object> dict)
			{
				Dictionary<string, object> dictionary = castDictToStringDict(dict);
				foreach (KeyValuePair<string, object> item2 in dictionary)
				{
					if (item2.Key == "groups")
					{
						if (item2.Value is Dictionary<object, object> dictionary2)
						{
							foreach (KeyValuePair<object, object> item3 in dictionary2)
							{
								string text = item3.Key.ToString();
								List<string> source;
								if (item3.Value is string item)
								{
									source = new List<string> { item };
								}
								else
								{
									if (!(item3.Value is List<object> source2))
									{
										configErrors.Add("groups." + text + " contains an invalid value (" + (item3.Value?.GetType().Name ?? "null") + ")");
										continue;
									}
									source = source2.Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (object s) => s != null).Cast<string>().ToList();
								}
								groups[text.ToLower()] = source.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string s) => s.ToLower()).ToList();
							}
						}
						else
						{
							configErrors.Add("groups must contain a mapping from group to a list of group or creature names");
						}
					}
					else
					{
						Section section = this.section(new Section(dictionary, "", null, this), item2.Key);
						if (section != null)
						{
							ParsePrimarySection(section);
							section.Dispose();
							continue;
						}
						configErrors.Add("All top-level keys must be a mapping. Got unexpected " + (item2.Value?.GetType().ToString() ?? "null") + " for key '" + item2.Key + "'.");
					}
				}
			}
			Verify();
		}

		protected virtual void Verify()
		{
		}

		protected abstract void ParsePrimarySection(Section primarySection);

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		private bool parseScalar<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string input, out T output) where T : struct
		{
			if (typeof(int) == typeof(T))
			{
				if (int.TryParse(input, out var result))
				{
					output = (T)(object)result;
					return true;
				}
			}
			else if (typeof(float) == typeof(T))
			{
				if (float.TryParse(input, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
				{
					output = (T)(object)result2;
					return true;
				}
			}
			else if (typeof(bool) == typeof(T) || typeof(T) == typeof(ItemConfig.Teleportable))
			{
				string[] source = new string[12]
				{
					"0", "false", "off", "no", "nope", "nah", "-", "hell no", "pls dont", "lol no",
					"certainly not", "absolutely not"
				};
				string[] source2 = new string[14]
				{
					"1", "true", "on", "yes", "yep", "yeah", "+", "hell yeah", "ok", "okay",
					"k", "yaaas", "certainly", "absolutely"
				};
				if (source.Contains(input.ToLower()))
				{
					output = ((typeof(ItemConfig.Teleportable) == typeof(T)) ? ((T)(object)default(ItemConfig.Teleportable)) : ((T)(object)false));
					return true;
				}
				if (source2.Contains(input.ToLower()))
				{
					output = ((typeof(ItemConfig.Teleportable) == typeof(T)) ? ((T)(object)new ItemConfig.Teleportable
					{
						amount = int.MaxValue
					}) : ((T)(object)true));
					return true;
				}
			}
			output = default(T);
			return false;
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		protected bool ParseScalarFromObject<T>(ref T target, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] Section sect, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string key) where T : struct
		{
			T? target2 = null;
			if (ParseScalarFromObject(ref target2, sect, key))
			{
				target = target2.Value;
				return true;
			}
			return false;
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		protected bool ParseScalarFromObject<T>(ref T? target, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] Section sect, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string key) where T : struct
		{
			object obj = sect.Get(key);
			if (obj != null)
			{
				if (obj is string input && parseScalar<T>(input, out var output))
				{
					target = output;
					return true;
				}
				configErrors.Add(sect.Path + "." + key + " is not a " + typeof(T).Name + " describing a " + key + " multiplier");
			}
			return false;
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		private bool parseStructFromDict<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> input, out T output, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string path) where T : struct
		{
			output = default(T);
			if (!typeof(T).IsPrimitive && !typeof(T).IsEnum)
			{
				HashSet<string> hashSet = new HashSet<string>();
				FieldInfo[] fields = typeof(T).GetFields();
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!input.TryGetValue(fieldInfo.Name, out var value))
					{
						continue;
					}
					hashSet.Add(fieldInfo.Name);
					object[] array;
					if (fieldInfo.FieldType.IsPrimitive || fieldInfo.FieldType.IsEnum)
					{
						array = new object[2] { value, null };
						if (!(bool)typeof(ConfigFile).GetMethod("parseScalar", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(fieldInfo.FieldType).Invoke(this, array))
						{
							configErrors.Add(path + "." + fieldInfo.Name + " is not " + fieldInfo.FieldType.Name);
							continue;
						}
					}
					else
					{
						array = new object[3]
						{
							value,
							null,
							path + "." + fieldInfo.FieldType.Name
						};
						typeof(ConfigFile).GetMethod("parseStructFromDict", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(fieldInfo.FieldType).Invoke(this, array);
					}
					fieldInfo.SetValue(output, array[1]);
				}
				foreach (object key in input.Keys)
				{
					if (!hashSet.Contains(key))
					{
						configErrors.Add(string.Format("{0} contains invalid key '{1}'. Allowed keys are {2}.", path, key, string.Join(", ", from f in typeof(T).GetFields()
							select f.Name)));
					}
				}
				return true;
			}
			return false;
		}

		[PublicAPI]
		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
		protected float[] ParseProbabilityMap([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string path, object value)
		{
			if (value is List<object> list)
			{
				float[] array = new float[list.Count];
				for (int i = 0; i < list.Count; i++)
				{
					if (list[i] is string s && float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						array[i] = result;
					}
					else
					{
						configErrors.Add($"{path}[{i}] is not a float denoting a probability");
					}
				}
				return array;
			}
			return null;
		}

		protected bool ParseWorldlevelToSingleScalar<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 0 })] ref Dictionary<int, T?> target, Section sect, string key) where T : struct
		{
			string name = typeof(T).Name;
			object obj = sect.Get(key);
			if (obj != null)
			{
				T output;
				if (obj.ToString().ToLower() == "default")
				{
					target = Enumerable.Repeat<T?>(null, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
				}
				else if (obj is string input && parseScalar<T>(input, out output))
				{
					target = Enumerable.Repeat((T?)output, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
				}
				else if (obj is Dictionary<object, object> dictionary)
				{
					target = new Dictionary<int, T?>();
					bool flag = true;
					foreach (KeyValuePair<object, object> item in dictionary)
					{
						if (int.TryParse(item.Key.ToString(), out var result))
						{
							if (item.Value?.ToString().ToLower() == "default")
							{
								target[result] = null;
							}
							else if (item.Value is string input2 && parseScalar<T>(input2, out output))
							{
								target[result] = output;
							}
							else if (item.Value is Dictionary<object, object> input3 && parseStructFromDict<T>(input3, out output, $"{sect.Path}.{key}.{result}"))
							{
								target[result] = output;
							}
							else
							{
								configErrors.Add($"{sect.Path}.{key}.{result} is not 'default' nor {name}");
							}
						}
						else
						{
							if (!flag && !typeof(T).IsPrimitive && !typeof(T).IsEnum && parseStructFromDict<T>(dictionary, out output, sect.Path + "." + key))
							{
								target = Enumerable.Repeat((T?)output, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
								break;
							}
							configErrors.Add($"{sect.Path}.{key} contains a non-integer key {item.Key}");
						}
						flag = false;
					}
				}
				else
				{
					configErrors.Add(sect.Path + "." + key + " is not 'default', " + name + " nor Map");
				}
			}
			return target != null;
		}

		protected bool ParseWorldlevelToFloatMap([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] ref Dictionary<int, float[]> target, Section sect, string key)
		{
			object obj = sect.Get(key);
			if (obj != null)
			{
				int result;
				float result2;
				if (obj.ToString().ToLower() == "default")
				{
					target = Enumerable.Repeat<float[]>(null, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
				}
				else if (key == "stars" && obj is string s && int.TryParse(s, out result))
				{
					float[] element = ((!(sect.dictKey != "sector")) ? ((result < 0) ? Array.Empty<float>() : new float[1] { -result }) : ((result <= 0) ? Array.Empty<float>() : Enumerable.Repeat(0f, result - 1).Concat(new float[1] { 100f }).ToArray()));
					target = Enumerable.Repeat(element, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
				}
				else if (key != "stars" && obj is string s2 && float.TryParse(s2, NumberStyles.Float, CultureInfo.InvariantCulture, out result2))
				{
					target = Enumerable.Repeat(new float[1] { result2 }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
				}
				else
				{
					float[] array = ParseProbabilityMap(sect.Path + "." + key, obj);
					if (array != null)
					{
						target = Enumerable.Repeat(array, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
					}
					else if (obj is Dictionary<object, object> dictionary)
					{
						target = new Dictionary<int, float[]>();
						foreach (KeyValuePair<object, object> item in dictionary)
						{
							if (int.TryParse(item.Key.ToString(), out var result3))
							{
								if (item.Value?.ToString().ToLower() == "default")
								{
									target[result3] = null;
									continue;
								}
								if (key == "stars" && item.Value is string s3 && int.TryParse(s3, out result))
								{
									if (sect.dictKey != "sector")
									{
										target[result3] = ((result <= 0) ? Array.Empty<float>() : Enumerable.Repeat(0f, result - 1).Concat(new float[1] { 100f }).ToArray());
									}
									else
									{
										target[result3] = ((result < 0) ? Array.Empty<float>() : new float[1] { -result });
									}
									continue;
								}
								if (key != "stars" && item.Value is string s4 && float.TryParse(s4, NumberStyles.Float, CultureInfo.InvariantCulture, out var result4))
								{
									target[result3] = new float[1] { result4 };
									continue;
								}
								float[] array2 = ParseProbabilityMap($"{sect.Path}.{key}.{result3}", item.Value);
								if (array2 != null)
								{
									target[result3] = array2;
									continue;
								}
								configErrors.Add(string.Format("{0}.{1}.{2} is not 'default', {3} nor List", sect.Path, key, result3, (key == "stars") ? "integer" : "float"));
							}
							else
							{
								configErrors.Add($"{sect.Path}.{key} contains a non-integer key {item.Key}");
							}
						}
					}
					else
					{
						configErrors.Add(sect.Path + "." + key + " is not 'default', " + ((key == "stars") ? "integer" : "float") + " nor List nor Map");
					}
				}
			}
			return target != null;
		}

		protected bool ParseEnumConfig<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 0, 2 })] ref Dictionary<int, Dictionary<T, float[]>> target, Section sect, string key) where T : struct, IConvertible
		{
			List<T> allEnumValues = ((T[])Enum.GetValues(typeof(T))).Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T t) => t.ToInt32(CultureInfo.InvariantCulture) != 0).ToList();
			object obj = sect.Get(key);
			if (obj != null)
			{
				if (obj.ToString().ToLower() == "default")
				{
					target = Enumerable.Repeat(((IEnumerable<T>)allEnumValues).ToDictionary((Func<T, T>)([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T k) => k), (Func<T, float[]>)([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T _) => null)), CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
				}
				else if (obj is string text)
				{
					if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						target = Enumerable.Repeat(defaultEntryFromProbability(result), CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
					}
					else if (typeof(T) != typeof(CreatureLevelControl.ModifyDamage))
					{
						ParseResult<T> parseResult = ParseEnum(text);
						if (parseResult.error == null)
						{
							target = Enumerable.Repeat(new Dictionary<T, float[]> { 
							{
								parseResult.value,
								new float[1] { 100f }
							} }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
						}
						else
						{
							configErrors.Add(sect.Path + "." + key + " contains invalid value " + text + ", expecting default, float, " + parseResult.error + " or dictionary");
						}
					}
				}
				else
				{
					if (typeof(T) == typeof(CreatureLevelControl.ModifyDamage))
					{
						float[] array = ParseProbabilityMap(sect.Path + "." + key, obj);
						if (array != null)
						{
							target = Enumerable.Repeat(new Dictionary<T, float[]> { 
							{
								(T)(object)CreatureLevelControl.ModifyDamage.All,
								array
							} }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v);
							goto IL_0653;
						}
					}
					if (obj is Dictionary<object, object> dictionary)
					{
						target = new Dictionary<int, Dictionary<T, float[]>>();
						if (dictionary.Count > 0)
						{
							if (int.TryParse(dictionary.Keys.First().ToString(), out var _))
							{
								foreach (KeyValuePair<object, object> item in dictionary)
								{
									if (int.TryParse(item.Key.ToString(), out var result3))
									{
										float result4;
										if (item.Value?.ToString().ToLower() == "default")
										{
											target[result3] = ((IEnumerable<T>)allEnumValues).ToDictionary((Func<T, T>)([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T k) => k), (Func<T, float[]>)([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T _) => null));
										}
										else if (item.Value is string s && float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out result4))
										{
											target[result3] = defaultEntryFromProbability(result4);
										}
										else if (item.Value is Dictionary<object, object> affixes2)
										{
											target[result3] = ParseAffixProbabilities($"{sect.Path}.{key}[{result3}]", affixes2);
										}
										else
										{
											configErrors.Add($"{sect.Path}.{key}[{result3}] is not a mapping from affix names to probabilities");
										}
									}
									else
									{
										configErrors.Add(sect.Path + "." + key + " contains mixed world levels and affix names");
									}
								}
							}
							else
							{
								Dictionary<T, float[]> value = ParseAffixProbabilities(sect.Path + "." + key, dictionary);
								for (int j = 0; j <= CreatureLevelControl.defaultWorldLevelDays.Length; j++)
								{
									target[j] = value;
								}
							}
						}
					}
					else
					{
						configErrors.Add(sect.Path + "." + key + " is not integer" + ((typeof(T) == typeof(CreatureLevelControl.ModifyDamage)) ? ", List" : "") + ", 'default' nor Map");
					}
				}
			}
			goto IL_0653;
			IL_0653:
			return target != null;
			[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
			[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0, 2 })]
			Dictionary<T, float[]> ParseAffixProbabilities([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string path, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> affixes)
			{
				Dictionary<T, float[]> affixProbabilities = new Dictionary<T, float[]>();
				bool hasOther = false;
				float[] otherValue = null;
				foreach (KeyValuePair<object, object> affix in affixes)
				{
					bool isOther = affix.Key.ToString().ToLower() == "other";
					ParseResult<T> result5 = ParseEnum(affix.Key.ToString());
					if (isOther || result5.error == null)
					{
						float result6;
						if (affix.Value?.ToString().ToLower() == "default")
						{
							assign(null);
						}
						else if (affix.Value is string s2 && float.TryParse(s2, NumberStyles.Float, CultureInfo.InvariantCulture, out result6))
						{
							assign(new float[1] { result6 });
						}
						else
						{
							float[] array2 = ParseProbabilityMap($"{path}.{affix.Key}", affix.Value);
							if (array2 != null)
							{
								assign(array2);
							}
							else
							{
								configErrors.Add(string.Format("{0}.{1} (value '{2}') is not a float or list of floats denoting probabilities", path, affix.Key, (affix.Value is string) ? affix.Value : (affix.Value?.GetType().Name ?? "null")));
							}
						}
					}
					else
					{
						configErrors.Add($"{path} contains unexpected affix key {affix.Key}, expecting either other, {result5.error}");
					}
					[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
					void assign([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] float[] probabilityArray)
					{
						if (isOther)
						{
							hasOther = true;
							otherValue = probabilityArray;
						}
						else
						{
							affixProbabilities[result5.value] = probabilityArray;
						}
					}
				}
				if (hasOther)
				{
					int undefinedValueCount = allEnumValues.Count - affixProbabilities.Count;
					if (otherValue != null && undefinedValueCount > 0)
					{
						otherValue = otherValue.Select((float p) => p / (float)undefinedValueCount).ToArray();
					}
					foreach (T item2 in allEnumValues)
					{
						if (!affixProbabilities.ContainsKey(item2))
						{
							affixProbabilities[item2] = otherValue;
						}
					}
				}
				return affixProbabilities;
			}
			[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
			ParseResult<T> ParseEnum([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string name)
			{
				ParseResult<T> result8;
				if (!Enum.TryParse<T>(name, ignoreCase: true, out var result7))
				{
					result8 = default(ParseResult<T>);
					result8.error = string.Join(", ", allEnumValues.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T t) => t.ToString()));
					return result8;
				}
				result8 = default(ParseResult<T>);
				result8.value = result7;
				return result8;
			}
			[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
			[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0, 2 })]
			Dictionary<T, float[]> defaultEntryFromProbability(float probability)
			{
				if (!(typeof(T) == typeof(CreatureLevelControl.ModifyDamage)))
				{
					return allEnumValues.ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T k) => k, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T _) => new float[1] { probability });
				}
				return new Dictionary<T, float[]> { 
				{
					(T)(object)CreatureLevelControl.ModifyDamage.All,
					new float[1] { probability }
				} };
			}
		}
	}
	[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
	[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)]
	public class CreatureConfig
	{
		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		[Flags]
		public enum CreatureMode
		{
			Default = 0,
			Tamed = 1,
			Day = 2,
			Night = 4,
			Dungeon = 8,
			Override = 0x10
		}

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
		public struct CreatureFilter : IComparable
		{
			public CreatureMode Mode;

			[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1 })]
			public Dictionary<string, bool> GlobalKeys;

			private string globalKeys()
			{
				return "Globalkeys " + string.Join(", ", GlobalKeys.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<string, bool> kv) => (kv.Value ? "" : "!") + kv.Key));
			}

			public override string ToString()
			{
				if (Mode == CreatureMode.Default)
				{
					return globalKeys();
				}
				if (GlobalKeys != null)
				{
					return $"{Mode}, {globalKeys()}";
				}
				return Mode.ToString();
			}

			public int CompareTo(object obj)
			{
				if (obj is CreatureFilter creatureFilter)
				{
					int num = 0;
					if ((Mode & CreatureMode.Override) == 0 == ((creatureFilter.Mode & CreatureMode.Override) == 0))
					{
						if (GlobalKeys == null != (creatureFilter.GlobalKeys == null))
						{
							if (GlobalKeys != null)
							{
								return -1;
							}
							return 1;
						}
						if (GlobalKeys != null && GlobalKeys.Count != creatureFilter.GlobalKeys.Count)
						{
							if (GlobalKeys.Count <= creatureFilter.GlobalKeys.Count)
							{
								return 1;
							}
							return -1;
						}
					}
					CreatureMode[] modePriorities = CreatureConfig.modePriorities;
					foreach (CreatureMode creatureMode in modePriorities)
					{
						if ((Mode & creatureMode) == 0 != ((creatureFilter.Mode & creatureMode) == 0))
						{
							if ((Mode & creatureMode) != 0)
							{
								return -1;
							}
							return 1;
						}
						if (num == 0 && (Mode & creatureMode) != (creatureFilter.Mode & creatureMode))
						{
							num = ((Mode >= creatureFilter.Mode) ? 1 : (-1));
						}
					}
					if (num == 0 && GlobalKeys != null && creatureFilter.GlobalKeys != null)
					{
						List<KeyValuePair<string, bool>> list = GlobalKeys.OrderBy([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<string, bool> kv) => kv.Key).ToList();
						List<KeyValuePair<string, bool>> list2 = creatureFilter.GlobalKeys.OrderBy([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<string, bool> kv) => kv.Key).ToList();
						for (int j = 0; j < list.Count; j++)
						{
							int num2 = string.Compare(list[j].Key, list2[j].Key, StringComparison.Ordinal);
							if (num2 != 0)
							{
								return num2;
							}
							if (list[j].Value != list2[j].Value)
							{
								if (!list[j].Value)
								{
									return 1;
								}
								return -1;
							}
						}
					}
					return num;
				}
				return 1;
			}
		}

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
		public class ConfigFile : global::CreatureLevelControl.ConfigFile
		{
			[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
			private delegate void Assigner<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] T>(ref T current, T input);

			private readonly Dictionary<string, CreatureConfig> configs = new Dictionary<string, CreatureConfig>();

			private static List<string> prefabLocalizations(Character prefab)
			{
				return new List<string>
				{
					((Object)prefab).name.ToLower(),
					prefab.m_name.ToLower(),
					Localization.instance.Localize(prefab.m_name).ToLower(),
					CreatureLevelControl.englishLocalization.Localize(prefab.m_name).ToLower()
				};
			}

			private static List<string> biomeLocalizations(Biome biome)
			{
				return new string[3]
				{
					((object)(Biome)(ref biome)).ToString().ToLower(),
					Localization.instance.Localize("$biome_" + ((object)(Biome)(ref biome)).ToString().ToLower()).ToLower(),
					CreatureLevelControl.englishLocalization.Localize("$biome_" + ((object)(Biome)(ref biome)).ToString().ToLower()).ToLower()
				}.Distinct().ToList();
			}

			public Dictionary<string, CreatureConfig> Process()
			{
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
				//IL_0100: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
				Dictionary<string, CreatureConfig> dictionary = new Dictionary<string, CreatureConfig>();
				Biome[] array = new Biome[9];
				RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
				Biome[] biomeOrder = (Biome[])(object)array;
				biomeOrder = biomeOrder.Concat(knownBiomes.Where((Biome b) => !biomeOrder.Contains(b))).ToArray();
				Dictionary<Biome, List<GameObject>> dictionary2 = new Dictionary<Biome, List<GameObject>>();
				foreach (IGrouping<string, SpawnData> item in ZNetScene.instance.GetPrefab("_ZoneCtrl").GetComponent<SpawnSystem>().m_spawnLists.SelectMany([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (SpawnSystemList s) => from p in s.m_spawners
					where p.m_requiredGlobalKey == "" && Object.op_Implicit((Object)(object)p.m_prefab.gameObject.GetComponent<Character>())
					group p by ((Object)p.m_prefab).name))
				{
					Biome val = item.Aggregate((Biome)0, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Biome a, SpawnData p) => (Biome)(a | p.m_biome));
					Biome[] array2 = biomeOrder;
					foreach (Biome val2 in array2)
					{
						if (((Enum)val).HasFlag((Enum)(object)val2))
						{
							if (!dictionary2.TryGetValue(val2, out var value))
							{
								List<GameObject> list2 = (dictionary2[val2] = new List<GameObject>());
								value = list2;
							}
							value.Add(item.First().m_prefab);
							break;
						}
					}
				}
				foreach (KeyValuePair<Biome, List<GameObject>> item2 in dictionary2)
				{
					List<string> value2 = item2.Value.SelectMany([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (GameObject prefab) => prefabLocalizations(prefab.GetComponent<Character>())).ToList();
					foreach (string item3 in from biomeName in biomeLocalizations(item2.Key)
						where !groups.ContainsKey(biomeName)
						select biomeName)
					{
						groups[item3] = value2;
					}
				}
				foreach (Character item4 in from p in ZNetScene.instance.m_prefabs
					select p.GetComponent<Character>() into c
					where Object.op_Implicit((Object)(object)c) && !c.IsPlayer()
					select c)
				{
					List<string> list3 = prefabLocalizations(item4);
					string[] array3 = list3.ToArray();
					foreach (string name in array3)
					{
						resolveGroupsForName(list3, name);
					}
					list3.Add(item4.IsBoss() ? "boss" : "creature");
					list3.Add("all");
					foreach (string item5 in list3)
					{
						if (configs.TryGetValue(item5, out var value3))
						{
							if (!dictionary.TryGetValue(item4.m_name, out var value4))
							{
								CreatureConfig creatureConfig2 = (dictionary[item4.m_name] = new CreatureConfig());
								value4 = creatureConfig2;
							}
							AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.worldLevelToStars, value3.worldLevelToStars);
							AssignCreatureModeConfigStruct<float>(value4.sizeScalingFactor, value3.sizeScalingFactor);
							AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseHealth, value3.baseHealth);
							AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.healthGainPerStar, value3.healthGainPerStar);
							AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(base.AssignConfig, value4.baseDamage, value3.baseDamage);
							AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.damageGainPerStar, value3.damageGainPerStar);
							AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.attackSpeedGainPerStar, value3.attackSpeedGainPerStar);
							AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.movementSpeedGainPerStar, value3.movementSpeedGainPerStar);
							AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseMovementSpeed, value3.baseMovementSpeed);
							AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseAttackSpeed, value3.baseAttackSpeed);
							AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.spawnAmount, value3.spawnAmount);
							AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.sectorCount, value3.sectorCount);
							AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.sectorStars, value3.sectorStars);
							AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.worldLevelToLootAmount, value3.worldLevelToLootAmount);
							AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.worldLevelToLootPerStar, value3.worldLevelToLootPerStar);
							AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(base.AssignEnumConfig, value4.worldLevelToCreatureEffect, value3.worldLevelToCreatureEffect);
							AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(base.AssignEnumConfig, value4.worldLevelToCreatureEffectFactor, value3.worldLevelToCreatureEffectFactor);
							AssignEnumConfig(ref value4.worldLevelToBoss, value3.worldLevelToBoss);
							AssignEnumConfig(ref value4.worldLevelToBossAffixFactor, value3.worldLevelToBossAffixFactor);
							AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureInfusion, float[]>>>(base.AssignEnumConfig, value4.worldLevelToInfusion, value3.worldLevelToInfusion);
							AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(base.AssignEnumConfig, value4.worldLevelToDamageTakenModifier, value3.worldLevelToDamageTakenModifier);
						}
					}
					if (dictionary.TryGetValue(item4.m_name, out var value5))
					{
						fillModeWorldLevels<float[]>(value5.worldLevelToStars);
						fillModeWorldLevels<Dictionary<CreatureExtraEffect, float[]>>(value5.worldLevelToCreatureEffect);
						fillModeWorldLevels<Dictionary<CreatureExtraEffect, float[]>>(value5.worldLevelToCreatureEffectFactor);
						fillWorldLevels(value5.worldLevelToBoss);
						fillWorldLevels(value5.worldLevelToBossAffixFactor);
						fillModeWorldLevels<Dictionary<CreatureInfusion, float[]>>(value5.worldLevelToInfusion);
						fillModeWorldLevels<Dictionary<CreatureLevelControl.ModifyDamage, float[]>>(value5.worldLevelToDamageTakenModifier);
						fillModeWorldLevels<float[]>(value5.baseHealth);
						fillModeWorldLevels<float?>(value5.healthGainPerStar);
						fillModeWorldLevels<Dictionary<CreatureLevelControl.ModifyDamage, float[]>>(value5.baseDamage);
						fillModeWorldLevels<float?>(value5.damageGainPerStar);
						fillModeWorldLevels<float[]>(value5.baseMovementSpeed);
						fillModeWorldLevels<float?>(value5.movementSpeedGainPerStar);
						fillModeWorldLevels<float[]>(value5.baseAttackSpeed);
						fillModeWorldLevels<float?>(value5.attackSpeedGainPerStar);
						fillModeWorldLevels<float[]>(value5.spawnAmount);
						fillModeWorldLevels<float[]>(value5.sectorCount);
						fillModeWorldLevels<float[]>(value5.sectorStars);
						fillModeWorldLevels<float[]>(value5.worldLevelToLootAmount);
						fillModeWorldLevels<float?>(value5.worldLevelToLootPerStar);
					}
				}
				return dictionary;
				static void AssignCreatureModeConfig<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] Assigner<T> assigner, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> newConfig, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> inConfig) where T : class
				{
					foreach (CreatureFilter item6 in newConfig.Keys.Concat(inConfig.Keys).ToList())
					{
						T value9;
						if (!newConfig.TryGetValue(item6, out var value7))
						{
							if (inConfig.TryGetValue(item6, out var value8))
							{
								newConfig[item6] = value8;
							}
						}
						else if (inConfig.TryGetValue(item6, out value9))
						{
							assigner(ref value7, value9);
							newConfig[item6] = value7;
						}
					}
				}
				static void AssignCreatureModeConfigStruct<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> newConfig, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> inConfig) where T : struct
				{
					foreach (CreatureFilter item7 in newConfig.Keys.Concat(inConfig.Keys).ToList())
					{
						if (!newConfig.ContainsKey(item7) && inConfig.TryGetValue(item7, out var value6))
						{
							newConfig[item7] = value6;
						}
					}
				}
				void fillModeWorldLevels<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 0 })] SortedDictionary<CreatureFilter, Dictionary<int, T>> config)
				{
					config.Values.ToList().ForEach(base.fillWorldLevels);
				}
			}

			private SortedDictionary<CreatureFilter, Section> getSections(Section parentSection)
			{
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
				SortedDictionary<CreatureFilter, Section> sections = new SortedDictionary<CreatureFilter, Section> { 
				{
					default(CreatureFilter),
					parentSection
				} };
				foreach (CreatureMode item in ((CreatureMode[])Enum.GetValues(typeof(CreatureMode))).Where((CreatureMode v) => v != CreatureMode.Default))
				{
					creatureModeSection(item, new string[1] { item.ToString().ToLower() });
				}
				Biome[] knownBiomes = CreatureConfig.knownBiomes;
				foreach (Biome biome in knownBiomes)
				{
					creatureModeSection(biomeToCreatureMode(biome), biomeLocalizations(biome));
				}
				readGlobalkeys("key_", present: true);
				readGlobalkeys("nokey_", present: false);
				return sections;
				void creatureModeSection(CreatureMode mode, IEnumerable<string> localizations)
				{
					Section section3 = localizations.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string localizedKey) => section(parentSection, localizedKey)).FirstOrDefault([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Section section) => section != null);
					if (section3 != null)
					{
						foreach (KeyValuePair<CreatureFilter, Section> section4 in getSections(section3))
						{
							CreatureFilter key2 = section4.Key;
							key2.Mode |= mode;
							sections[key2] = section4.Value;
						}
					}
				}
				void readGlobalkeys(string prefix, bool present)
				{
					foreach (string item2 in parentSection.KeysWithPrefix(prefix))
					{
						Section section2 = section(parentSection, item2);
						if (section2 != null)
						{
							foreach (KeyValuePair<CreatureFilter, Section> section5 in getSections(section2))
							{
								CreatureFilter key = section5.Key;
								key.GlobalKeys = ((key.GlobalKeys != null) ? new Dictionary<string, bool>(key.GlobalKeys) : new Dictionary<string, bool>());
								key.GlobalKeys[item2.Substring(prefix.Length)] = present;
								sections[key] = section5.Value;
							}
						}
					}
				}
			}

			protected override void ParsePrimarySection(Section creatureSection)
			{
				string key = creatureSection.dictKey.ToLower();
				if (!configs.TryGetValue(key, out var value))
				{
					value = (configs[key] = new CreatureConfig());
				}
				SortedDictionary<CreatureFilter, Section> sections = getSections(creatureSection);
				AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.worldLevelToStars, sections, "stars");
				AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.worldLevelToLootAmount, sections, "loot");
				AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.worldLevelToLootPerStar, sections, "loot per star");
				AssignCreatureMode(base.ParseScalarFromObject, value.sizeScalingFactor, sections, "size");
				AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseHealth, sections, "health");
				AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.healthGainPerStar, sections, "health per star");
				AssignCreatureMode(base.ParseEnumConfig, value.baseDamage, sections, "damage");
				AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.damageGainPerStar, sections, "damage per star");
				AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseAttackSpeed, sections, "attack speed");
				AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.attackSpeedGainPerStar, sections, "attack speed per star");
				AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseMovementSpeed, sections, "movement speed");
				AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.movementSpeedGainPerStar, sections, "movement speed per star");
				AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToDamageTakenModifier, sections, "damage taken");
				AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.spawnAmount, sections, "amount");
				AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToCreatureEffect, sections, "effect");
				AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToCreatureEffectFactor, sections, "effect power");
				ParseEnumConfig(ref value.worldLevelToBoss, creatureSection, "affix");
				ParseEnumConfig(ref value.worldLevelToBossAffixFactor, creatureSection, "affix power");
				AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToInfusion, sections, "infusion");
				using Section section = base.section(creatureSection, "sector");
				if (section != null)
				{
					SortedDictionary<CreatureFilter, Section> sections2 = getSections(section);
					AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.sectorCount, sections2, "count");
					AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.sectorStars, sections2, "stars");
				}
				sections.Remove(default(CreatureFilter));
				foreach (Section value2 in sections.Values)
				{
					value2.Dispose();
				}
			}

			private static void AssignCreatureMode<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] T>(ParserDelegate<T> parser, SortedDictionary<CreatureFilter, T> target, SortedDictionary<CreatureFilter, Section> sections, string key)
			{
				foreach (KeyValuePair<CreatureFilter, Section> section in sections)
				{
					target.TryGetValue(default(CreatureFilter), out var value);
					if (parser(ref value, section.Value, key))
					{
						target[section.Key] = value;
					}
				}
			}

			protected override void Verify()
			{
				foreach (KeyValuePair<string, CreatureConfig> config in configs)
				{
					KeyValuePair<string, CreatureConfig> configKv = config;
					foreach (KeyValuePair<CreatureFilter, Dictionary<int, float[]>> worldLevelToStar in configKv.Value.worldLevelToStars)
					{
						float[] array = null;
						foreach (KeyValuePair<int, float[]> item in worldLevelToStar.Value)
						{
							float[] value = item.Value;
							if (value != null && value.Sum() > 100.0001f && (array == null || !array.SequenceEqual(item.Value)))
							{
								array = item.Value;
								configWarnings.Add(string.Format("{0}{1} has a sum of probabilities greater than 100% for its 'stars' setting at world level {2}. Note that the sum of probabilites for individual star levels MUST be equal or lower than 100%, otherwise probabilities exceeding 100% will be ignored.\nWith the current configuration this group would have the following base probabilities: {3}.", configKv.Key, worldLevelToStar.Key.Equals(default(CreatureFilter)) ? "" : $" in {worldLevelToStar.Key} mode", item.Key, string.Join(", ", API.zeroProbabilities(item.Value).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float p, int i) => $"{i} stars: {p}%"))));
							}
						}
					}
					checkEffectProbabilities<CreatureExtraEffect>(configKv.Value.worldLevelToCreatureEffect, CreatureLevelControl.customCreatureAffixChances, "creature special effect");
					checkEffectProbabilities<CreatureInfusion>(configKv.Value.worldLevelToInfusion, CreatureLevelControl.customCreatureInfusionChances, "creature infusion");
					SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<BossAffix, float[]>>> sortedDictionary = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<BossAffix, float[]>>>();
					if (configKv.Value.worldLevelToBoss != null)
					{
						sortedDictionary[default(CreatureFilter)] = configKv.Value.worldLevelToBoss;
					}
					checkEffectProbabilities<BossAffix>(sortedDictionary, CreatureLevelControl.customBossAffixChances, "boss affix");
					void checkEffectProbabilities<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 0, 2 })] SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<T, float[]>>> dict, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0, 1 })] Dictionary<T, ConfigEntry<float>> defaultsDict, string nameString) where T : struct, IConvertible
					{
						foreach (KeyValuePair<CreatureFilter, Dictionary<int, Dictionary<T, float[]>>> item2 in dict)
						{
							Dictionary<T, float> dictionary = null;
							foreach (KeyValuePair<int, Dictionary<T, float[]>> item3 in item2.Value)
							{
								int num = item3.Value.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<T, float[]> v) => (v.Value ?? new float[1]).Length).DefaultIfEmpty(1).Max();
								for (int j = 0; j < num; j++)
								{
									bool flag = false;
									Dictionary<T, float> dictionary2 = new Dictionary<T, float>();
									Dictionary<T, float> dictionary3 = new Dictionary<T, float>();
									foreach (T item4 in ((T[])Enum.GetValues(typeof(T))).Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T e) => e.ToInt32(CultureInfo.InvariantCulture) != 0))
									{
										float num3;
										if (item3.Value.TryGetValue(item4, out var value2) && value2 != null && value2.Length != 0)
										{
											num3 = (dictionary3[item4] = value2[(j < value2.Length) ? j : (value2.Length - 1)]);
										}
										else
										{
											num3 = defaultsDict[item4].Value;
											if (num3 > 0f)
											{
												flag = true;
											}
										}
										dictionary2[item4] = num3;
									}
									if (dictionary2.Values.Sum() > 101.1f && Mathf.Abs(dictionary3.Values.Sum() - 100f) > 1.1f && (dictionary == null || !dictionary.SequenceEqual(dictionary2)))
									{
										bool flag2 = dictionary3.Values.Sum() < 100f;
										dictionary = dictionary2;
										configWarnings.Add(string.Format("{0}{1} has a sum of {2} chances greater than 100% for {3} stars at world level {4}{5}. Some effects may not happen at all with the current configuration. Specified chances are: {6}.", configKv.Key, item2.Key.Equals(default(CreatureFilter)) ? "" : $" in configuration {item2.Key}", nameString, j, item3.Key, (flag && flag2) ? " (including default probabilities from config)" : "", string.Join(", ", (flag2 ? dictionary2 : dictionary3).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<T, float> kv) => $"{kv.Key}: {kv.Value}%"))));
									}
								}
							}
						}
					}
				}
			}
		}

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
		public class Loader : global::CreatureLevelControl.ConfigFile.Loader
		{
			[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)]
			public global::CreatureLevelControl.ConfigFile ConfigFile
			{
				[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
				get
				{
					return CreatureLevelControl.creatureConfigFile;
				}
				[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)]
				set
				{
					CreatureLevelControl.creatureConfigFile = (ConfigFile)value;
				}
			}

			public string FilePattern => "CreatureConfig*.yml";

			public string EditButtonName => LocalizationWrapper.getTranslation("Edit Creature YAML config");

			public CustomSyncedValue<List<string>> FileData => CreatureLevelControl.creatureConfigFileData;

			public bool Enabled => CreatureLevelControl.creatureConfigFileActive.GetToggle();

			public global::CreatureLevelControl.ConfigFile InstantiateConfig()
			{
				return new ConfigFile();
			}

			public void ProcessConfig()
			{
				CreatureLevelControl.PrefabConfig = CreatureLevelControl.creatureConfigFile.Process();
			}
		}

		private const int BiomeOffset = 5;

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> worldLevelToStars = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>> worldLevelToCreatureEffect = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>> worldLevelToCreatureEffectFactor = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureInfusion, float[]>>> worldLevelToInfusion = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureInfusion, float[]>>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 2 })]
		public Dictionary<int, Dictionary<BossAffix, float[]>> worldLevelToBoss;

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 2 })]
		public Dictionary<int, Dictionary<BossAffix, float[]>> worldLevelToBossAffixFactor;

		public readonly SortedDictionary<CreatureFilter, float> sizeScalingFactor = new SortedDictionary<CreatureFilter, float>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseHealth = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>();

		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> healthGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>> baseDamage = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>();

		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> damageGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseMovementSpeed = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>();

		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> movementSpeedGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseAttackSpeed = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>();

		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> attackSpeedGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> spawnAmount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> sectorCount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> sectorStars = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>> worldLevelToDamageTakenModifier = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>();

		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })]
		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> worldLevelToLootAmount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>();

		public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> worldLevelToLootPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>();

		private static Biome[] knownBiomes => ((Biome[])Enum.GetValues(typeof(Biome))).Where((Biome b) => (int)b > 0).ToArray();

		private static CreatureMode[] modePriorities
		{
			get
			{
				CreatureMode[] obj = new CreatureMode[5]
				{
					CreatureMode.Override,
					CreatureMode.Tamed,
					CreatureMode.Dungeon,
					CreatureMode.Default,
					CreatureMode.Day | CreatureMode.Night
				};
				obj[3] = knownBiomes.Aggregate(CreatureMode.Default, (CreatureMode a, Biome m) => a | biomeToCreatureMode(m));
				return obj;
			}
		}

		public static CreatureMode biomeToCreatureMode(Biome biome)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Expected I4, but got Unknown
			return (CreatureMode)(biome << 5);
		}
	}
	[BepInPlugin("org.bepinex.plugins.creaturelevelcontrol", "Creature Level & Loot Control", "4.6.4")]
	[BepInIncompatibility("org.bepinex.plugins.valheim_plus")]
	[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)]
	[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class CreatureLevelControl : BaseUnityPlugin
	{
		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		public enum Difficulty
		{
			[LocalizationWrapper.Localized(Difficulty.Custom)]
			Custom,
			[LocalizationWrapper.Localized(Difficulty.Very_easy)]
			Very_easy,
			[LocalizationWrapper.Localized(Difficulty.Easy)]
			Easy,
			[LocalizationWrapper.Localized(Difficulty.Medium)]
			Medium,
			[LocalizationWrapper.Localized(Difficulty.Hard)]
			Hard,
			[LocalizationWrapper.Localized(Difficulty.Very_hard)]
			Very_hard,
			[LocalizationWrapper.Localized(Difficulty.Insane)]
			Insane
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		public enum CreatureSectorAnnouncementScope
		{
			[LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Local)]
			Local,
			[LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Global)]
			Global,
			[LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Off)]
			Off
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		public enum LootSystem
		{
			[LocalizationWrapper.Localized(LootSystem.Vanilla)]
			Vanilla,
			[LocalizationWrapper.Localized(LootSystem.Linear)]
			Linear,
			[LocalizationWrapper.Localized(LootSystem.CalculateChance)]
			CalculateChance,
			[LocalizationWrapper.Localized(LootSystem.CalculateAmount)]
			CalculateAmount
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		private enum VisualLevelIndicator
		{
			[LocalizationWrapper.Localized(VisualLevelIndicator.Off)]
			Off,
			[LocalizationWrapper.Localized(VisualLevelIndicator.On)]
			On,
			[LocalizationWrapper.Localized(VisualLevelIndicator.BossesOff)]
			BossesOff,
			[LocalizationWrapper.Localized(VisualLevelIndicator.CreaturesOff)]
			CreaturesOff
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		private enum AllowedConsoleCommands
		{
			[LocalizationWrapper.Localized(AllowedConsoleCommands.CreatureCommands)]
			CreatureCommands,
			[LocalizationWrapper.Localized(AllowedConsoleCommands.InformationCommands)]
			InformationCommands,
			[LocalizationWrapper.Localized(AllowedConsoleCommands.None)]
			None
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		private enum VisualExtraEffectIndicator
		{
			[LocalizationWrapper.Localized(VisualExtraEffectIndicator.Color)]
			Color,
			[LocalizationWrapper.Localized(VisualExtraEffectIndicator.Text)]
			Text,
			[LocalizationWrapper.Localized(VisualExtraEffectIndicator.Both)]
			Both
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		public enum DifficultySecondFactor
		{
			[LocalizationWrapper.Localized(DifficultySecondFactor.None)]
			None,
			[LocalizationWrapper.Localized(DifficultySecondFactor.Age_of_world)]
			Age_of_world,
			[LocalizationWrapper.Localized(DifficultySecondFactor.Distance)]
			Distance,
			[LocalizationWrapper.Localized(DifficultySecondFactor.BossesKilled)]
			BossesKilled
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		public enum SpawnLevel
		{
			[LocalizationWrapper.Localized(SpawnLevel.None)]
			None,
			[LocalizationWrapper.Localized(SpawnLevel.One)]
			One,
			[LocalizationWrapper.Localized(SpawnLevel.Two)]
			Two,
			[LocalizationWrapper.Localized(SpawnLevel.Three)]
			Three,
			[LocalizationWrapper.Localized(SpawnLevel.Four)]
			Four,
			[LocalizationWrapper.Localized(SpawnLevel.Five)]
			Five
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		public enum CreatureSectorWorldLevel
		{
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.Disabled)]
			Disabled = -1,
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.None)]
			None,
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.One)]
			One,
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.Two)]
			Two,
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.Three)]
			Three,
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.Four)]
			Four,
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.Five)]
			Five,
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.Six)]
			Six,
			[LocalizationWrapper.Localized(CreatureSectorWorldLevel.Seven)]
			Seven
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		public enum ModifyDamage
		{
			All,
			Fire,
			Frost,
			Poison,
			Lightning,
			Spirit,
			Elemental,
			Blunt,
			Slash,
			Pierce,
			Chop,
			Physical,
			Knives,
			Bows,
			Crossbows,
			ElementalMagic,
			BloodMagic,
			Swords,
			Spears,
			Pickaxes,
			Axes,
			Clubs,
			Polearms,
			Weapons,
			Unarmed
		}

		[HarmonyPatch(typeof(Game), "GetPlayerDifficulty")]
		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		private class PatchPlayerCount
		{
			[UsedImplicitly]
			private static void Postfix(ref int __result)
			{
				__result = Mathf.Min(maximumMultiplayerPlayerCount.Value, Mathf.Max(minimumMultiplayerPlayerCount.Value, additionalMultiplayerPlayerCount.Value + __result));
			}
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		[HarmonyPatch(typeof(Terminal), "TryRunCommand")]
		private class PatchTerminal
		{
			[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)]
			[UsedImplicitly]
			private static bool Prefix(Terminal __instance, string text)
			{
				//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_04a8: 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_04b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
				if (!text.ToLower().StartsWith("cllc"))
				{
					return true;
				}
				bool flag = true;
				string[] array = text.ToLower().Split(new char[1] { ' ' });
				bool flag2 = !configSync.IsLocked;
				bool flag3 = false;
				if (array.Length > 1 && array[1] == "killhighstars")
				{
					flag = false;
					if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands)
					{
						if (array.Length <= 2 || !int.TryParse(array[2], out var result))
						{
							result = 6;
						}
						Character[] array2 = Object.FindObjectsOfType<Character>();
						foreach (Character val in array2)
						{
							if (val.IsPlayer() || val.GetLevel() - 1 < result)
							{
								continue;
							}
							ZNetView component = ((Component)val).GetComponent<ZNetView>();
							if (component != null)
							{
								ZDO zDO = component.GetZDO();
								if (zDO != null)
								{
									zDO.SetOwner(ZDOMan.instance.m_sessionID);
								}
							}
							Object.Destroy((Object)(object)((Component)val).GetComponent<CharacterDrop>());
							ZNetScene.instance.Destroy(((Component)val).gameObject);
						}
						__instance.AddString("Removed all nearby creatures with at least " + result + " stars");
					}
					else
					{
						flag3 = true;
					}
				}
				else if (array.Length > 1 && array[1] == "killall")
				{
					flag = false;
					if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands)
					{
						Character[] array2 = Object.FindObjectsOfType<Character>();
						foreach (Character val2 in array2)
						{
							if (val2.IsPlayer())
							{
								continue;
							}
							ZNetView component2 = ((Component)val2).GetComponent<ZNetView>();
							if (component2 != null)
							{
								ZDO zDO2 = component2.GetZDO();
								if (zDO2 != null)
								{
									zDO2.SetOwner(ZDOMan.instance.m_sessionID);
								}
							}
							Object.Destroy((Object)(object)((Component)val2).GetComponent<CharacterDrop>());
							ZNetScene.instance.Destroy(((Component)val2).gameObject);
						}
						__instance.AddString("Removed all nearby creatures");
					}
					else
					{
						flag3 = true;
					}
				}
				else if (array.Length > 1 && array[1] == "worldlevel")
				{
					flag = false;
					if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None)
					{
						__instance.AddString("Current world level: " + API.GetWorldLevel());
					}
					else
					{
						flag3 = true;
					}
				}
				else if (array.Length > 1 && array[1] == "sectorkills")
				{
					flag = false;
					if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None)
					{
						__instance.AddString("Kills in the current sector: " + (CreatureSector.currentSector(((Component)Player.m_localPlayer).GetComponent<ZNetView>())?.sectorKills ?? 0f));
					}
					else
					{
						flag3 = true;
					}
				}
				else if (array.Length > 1 && array[1] == "resetsector")
				{
					flag = false;
					if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands)
					{
						CreatureSector.resetSectorKills(((Component)Player.m_localPlayer).GetComponent<ZNetView>());
						__instance.AddString("Reset all nearby creature sectors");
					}
					else
					{
						flag3 = true;
					}
				}
				else if (array.Length > 1 && array[1] == "starchance")
				{
					flag = false;
					if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None)
					{
						object obj;
						if (array.Length <= 2)
						{
							obj = null;
						}
						else
						{
							GameObject prefab = ZNetScene.instance.GetPrefab(text.Split(new char[1] { ' ' })[2]);
							obj = ((prefab != null) ? prefab.GetComponent<Character>() : null);
						}
						Character val3 = (Character)obj;
						int num = 0;
						__instance.AddString("Current star chances" + ((val3 == null) ? "" : (" for " + Localization.instance.Localize(val3.m_name))) + ":");
						float[] array3 = API.LevelProbabilities(val3, API.GetWorldLevel(), includeZoneBonusLevel: true);
						foreach (float num2 in array3)
						{
							__instance.AddString(num++ + " star: " + num2.ToString(CultureInfo.InvariantCulture) + "%");
						}
					}
					else
					{
						flag3 = true;
					}
				}
				else if (array.Length > 2 && array[1] == "spawn")
				{
					flag = false;
					if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands)
					{
						string text2 = text.Split(new char[1] { ' ' })[2];
						GameObject prefab2 = ZNetScene.instance.GetPrefab(text2);
						if ((Object)(object)prefab2 == (Object)null || !Object.op_Implicit((Object)(object)prefab2.GetComponent<Character>()))
						{
							__instance.AddString(text2 + " is not a creature");
							return false;
						}
						((Character)Player.m_localPlayer).Message((MessageType)1, "Spawning object " + ((Object)prefab2).name, 0, (Sprite)null);
						Transform transform = ((Component)Player.m_localPlayer).transform;
						Character character = Object.Instantiate<GameObject>(prefab2, transform.position + transform.forward * 2f + Vector3.up, Quaternion.identity).GetComponent<Character>();
						foreach (string item in array.Skip(3))
						{
							string effectName = item;
							if (int.TryParse(effectName, out var result2))
							{
								character.SetLevel(result2);
								continue;
							}
							bool matched = false;
							if (character.IsBoss())
							{
								loop<BossAffix>(delegate(BossAffix affix)
								{
									API.SetAffixBoss(character, affix);
								});
							}
							else
							{
								loop<CreatureInfusion>(delegate(CreatureInfusion infusion)
								{
									API.SetInfusionCreature(character, infusion);
								});
								loop<CreatureExtraEffect>(delegate(CreatureExtraEffect effect)
								{
									API.SetExtraEffectCreature(character, effect);
								});
							}
							if (!matched)
							{
								__instance.AddString("Unknown effect " + effectName);
							}
							void loop<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] Action<T> apply)
							{
								T[] array4 = (T[])Enum.GetValues(typeof(T));
								for (int j = 0; j < array4.Length; j++)
								{
									T obj2 = array4[j];
									if (string.Equals(obj2.ToString(), effectName, StringComparison.CurrentCultureIgnoreCase))
									{
										apply(obj2);
										matched = true;
									}
								}
							}
						}
					}
					else
					{
						flag3 = true;
					}
				}
				if (flag)
				{
					__instance.AddString("CLLC console commands - use 'cllc' followed by one of the following options");
					__instance.AddString("killhighstars [stars] - removes all nearby creatures with at least stars. Default stars is 6.");
					__instance.AddString("killall - removes all nearby creatures");
					__instance.AddString("worldlevel - displays the current world level");
					__instance.AddString("sectorkills - displays the creatures killed in the current sector");
					__instance.AddString("resetsector - resets all nearby creature sectors");
					__instance.AddString("starchance [creature] - displays the current star chances. Optionally for a specific creature.");
					__instance.AddString("spawn [creature] [level] [affix] [extraeffect] [infusion] - spawns a creature with the provided properties.");
				}
				if (flag3)
				{
					__instance.AddString("You are not allowed to use this command on this server.");
				}
				return false;
			}
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		[HarmonyPatch(typeof(Game), "GetDifficultyDamageScalePlayer")]
		private class PatchDamageFactor
		{
			[UsedImplicitly]
			private static void Postfix(ref float __result)
			{
				__result = (float)((double)(__result - 1f) / 0.04 * (double)multiplayerDMGfactor.Value / 100.0) + 1f;
			}
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		[HarmonyPatch(typeof(Game), "GetDifficultyDamageScaleEnemy")]
		private class PatchHealthFactor
		{
			[UsedImplicitly]
			private static void Postfix(ref float __result)
			{
				__result = 1f / ((float)((double)(1f / __result - 1f) / 0.4 * (double)multiplayerHPfactor.Value / 100.0) + 1f);
			}
		}

		[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)]
		[HarmonyPatch(typeof(Attack), "GetLevelDamageFactor")]
		private class PatchDamageStarFactor
		{
			[UsedImplicitly]
			[<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)]
			private static void Postfix(Attack __instance, ref float __result)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Character)(Humanoid)AccessTools.DeclaredField(typeof(Attack), "m_character").GetValue(__instance)).IsPlayer())
				{
					__result = 1f;
				}
			}
		}

		[HarmonyPatch(typeof(Character), "SetupMaxHealth")]
		[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
		private class PatchHealthStarFactor
		{
			[CompilerGenerated]
			private sealed class <Transpiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private CodeInstruction <>2__current;

				private int <>l__initialThreadId;

				[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 0, 1 })]
				private IEnumerable<CodeInstruction> instructions;

				[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 0, 1 })]
				public IEnumerable<CodeInstruction> <>3__instructions;

				[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 0, 1 })]
				private IEnumerator<CodeInstruction> <>7__wrap1;

				[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
				private CodeInstruction <instruction>5__3;

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

				object IEnumerator.Current
				{
					[DebuggerHidden]
					[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <Transpiler>d__2(int <>1__state)
				{
					this.<>1__state = <>1__state;
					<>l__initialThreadId = Environment.CurrentManagedThreadId;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					int num = <>1__state;
					if (num == -3 || (uint)(num - 1) <= 2u)
					{
						try
						{
						}
						finally
						{
							<>m__Finally1();
						}
					}
					<>7__wrap1 = null;
					<instruction>5__3 = null;
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
					//IL_00cc: Expected O, but got Unknown
					//IL_009a: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a4: Expected O, but got Unknown
					try
					{
						switch (<>1__state)
						{
						default:
							return false;
						case 0:
							<>1__state = -1;
							<>7__wrap1 = instructions.GetEnumerator();
							<>1__state = -3;
							break;
						case 1:
							<>1__state = -3;
							if (<instruction>5__3.opcode == OpCodes.Conv_R4)
							{
								<>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
								<>1__state = 2;
								return true;
							}
							goto IL_00df;
						case 2:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Call, (object)HealthFactorApplier);
							<>1__state = 3;
							return true;
						case 3:
							{
								<>1__state = -3;
								goto IL_00df;
							}
							IL_00df:
							<instruction>5__3 = null;
							break;
						}
						if (<>7__wrap1.MoveNext())
						{
							<instruction>5__3 = <>7__wrap1.Current;
							<>2__current = <instruction>5__3;
							<>1__state = 1;
							return true;
						}
						<>m__Finally1();
						<>7__wrap1 = null;
						return false;
					}
					catch
					{
						//try-fault
						((IDisposable)this).Dispose();
						throw;
					}
				}

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

				private void <>m__Finally1()
				{
					<>1__state = -1;
					if (<>7__wrap1 != null)
					{
						<>7__wrap1.Dispose();
					}
				}

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

				[DebuggerHidden]
				[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
				IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
				{
					<Transpiler>d__2 <Transpiler>d__;
					if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
					{
						<>1__state = 0;
						<Transpiler>d__ = this;
					}
					else
					{
						<Transpiler>d__ = new <Transpiler>d__2(0);
					}
					<Transpiler>d__.instructions = <>3__instructions;
					return <Transpiler>d__;
				}

				[DebuggerHidden]
				[return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)]
				IEnumerator IEnumerable.GetEnumerator()
				{
					return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
				}
			}

			private static readonly MethodInfo HealthFactorApplier = AccessTools.DeclaredMethod(typeof(PatchHealthStarFactor), "applyHealthFactor", (Type[])null, (Type[])null);

			private static float applyHealthFactor(float level, Character character)
			{
				int usedStars;
				float num = Utils.ReadWithWorldLevelAndStarsFromConfig