Decompiled source of Skalds Board v1.5.0

LemyChadPack.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ConditionalConfigSync;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using LemyChadPack.Altar;
using LemyChadPack.BloodMoon;
using LemyChadPack.Caravan;
using LemyChadPack.Contracts;
using LemyChadPack.Invasions;
using LemyChadPack.Legends;
using LemyChadPack.Models;
using LemyChadPack.Storage;
using LemyChadPack.UI;
using LemyChadPack.Ward;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LemyChadPack
{
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? ShowRangeAsPercent;

		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;

		public Func<object, string> ObjToStr;

		public Func<string, object> StrToObj;
	}
	internal static class PackConfig
	{
		internal static ConfigEntry<bool> LockConfig;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<LanguageChoice> Language;

		internal static ConfigEntry<string> StorageTableRecipe;

		internal static ConfigEntry<string> LevelRadii;

		internal static ConfigEntry<string> LevelRequests;

		internal static ConfigEntry<float> ExtensionRange;

		internal static ConfigEntry<string> ScalesRecipe;

		internal static ConfigEntry<string> VaultRecipe;

		internal static ConfigEntry<string> ShelfRecipe;

		internal static ConfigEntry<int> RequestContractsMax;

		internal static ConfigEntry<bool> SearchEnabled;

		internal static ConfigEntry<bool> SummaryEnabled;

		internal static ConfigEntry<bool> RequestsEnabled;

		internal static ConfigEntry<bool> ReserveEnabled;

		internal static ConfigEntry<int> ReserveExpiryDays;

		internal static ConfigEntry<bool> LabelsEnabled;

		internal static ConfigEntry<bool> ContractsEnabled;

		internal static ConfigEntry<string> BoardRecipe;

		internal static ConfigEntry<int> GroupContractsOnBoard;

		internal static ConfigEntry<int> PersonalOffers;

		internal static ConfigEntry<int> PersonalMaxActive;

		internal static ConfigEntry<int> PersonalRerollsPerDay;

		internal static ConfigEntry<int> RefreshEveryDays;

		internal static ConfigEntry<float> GroupAmountPerPlayer;

		internal static ConfigEntry<float> RequestContractRewardShare;

		internal static ConfigEntry<bool> ChainsEnabled;

		internal static ConfigEntry<bool> WeeklyEnabled;

		internal static ConfigEntry<int> WeeklyLengthDays;

		internal static ConfigEntry<float> CoinMultiplier;

		internal static ConfigEntry<float> MaterialMultiplier;

		internal static ConfigEntry<int> DailyMaterialCapPerPlayer;

		internal static ConfigEntry<float> RunestoneChance;

		internal static ConfigEntry<float> WeeklyRewardMultiplier;

		internal static ConfigEntry<bool> IgnoreTamed;

		internal static ConfigEntry<bool> IgnoreSummoned;

		internal static ConfigEntry<float> MinDamageShareForKill;

		internal static ConfigEntry<int> DepositCooldownMinutes;

		internal static ConfigEntry<bool> IgnoreSelfDroppedPickups;

		internal static ConfigEntry<bool> IgnoreDeconstructedPieces;

		internal static ConfigEntry<bool> LegendsEnabled;

		internal static ConfigEntry<float> LegendCheckMinutes;

		internal static ConfigEntry<float> LegendSpawnChance;

		internal static ConfigEntry<int> LegendLifetimeDays;

		internal static ConfigEntry<float> LegendAreaRadius;

		internal static ConfigEntry<float> LegendRewardMultiplier;

		internal static ConfigEntry<float> LegendHealthPerPlayer;

		internal static ConfigEntry<float> LegendPower;

		internal static ConfigEntry<bool> InvasionsEnabled;

		internal static ConfigEntry<float> InvasionCheckMinutes;

		internal static ConfigEntry<float> InvasionChance;

		internal static ConfigEntry<float> InvasionCooldownHours;

		internal static ConfigEntry<int> InvasionMinPlayers;

		internal static ConfigEntry<float> InvasionPrepMinutes;

		internal static ConfigEntry<float> InvasionMarchMinutes;

		internal static ConfigEntry<float> InvasionDistance;

		internal static ConfigEntry<float> InvasionBaseRadius;

		internal static ConfigEntry<float> InvasionInterceptRadius;

		internal static ConfigEntry<float> InvasionSizePerPlayer;

		internal static ConfigEntry<float> InvasionRewardMultiplier;

		internal static ConfigEntry<int> InvasionMinStars;

		internal static ConfigEntry<float> InvasionExtraStarChance;

		internal static ConfigEntry<bool> CaravanEnabled;

		internal static ConfigEntry<int> CaravanIntervalDays;

		internal static ConfigEntry<float> CaravanStayMinutes;

		internal static ConfigEntry<int> CaravanMinPlayers;

		internal static ConfigEntry<int> CaravanOffers;

		internal static ConfigEntry<float> CaravanBuyPriceMultiplier;

		internal static ConfigEntry<float> CaravanSellPriceMultiplier;

		internal static ConfigEntry<int> CaravanGearOffers;

		internal static ConfigEntry<int> CaravanPurse;

		internal static ConfigEntry<float> CaravanGearPriceMultiplier;

		internal static ConfigEntry<bool> AltarEnabled;

		internal static ConfigEntry<string> AltarRecipe;

		internal static ConfigEntry<float> FavorMultiplier;

		internal static ConfigEntry<float> BlessingStrength;

		internal static ConfigEntry<float> BlessingMinutes;

		internal static ConfigEntry<bool> WardEnabled;

		internal static ConfigEntry<string> WardRecipe;

		internal static ConfigEntry<string> WardRecipe2;

		internal static ConfigEntry<string> WardRecipe3;

		internal static ConfigEntry<string> WardRecipe4;

		internal static ConfigEntry<string> WardRadii;

		internal static ConfigEntry<bool> WardScareWeak;

		internal static ConfigEntry<float> WardBuildingProtection;

		internal static ConfigEntry<bool> WardWarnings;

		internal static ConfigEntry<bool> BloodMoonEnabled;

		internal static ConfigEntry<float> BloodMoonChance;

		internal static ConfigEntry<int> BloodMoonMinDays;

		internal static ConfigEntry<float> BloodMoonMonsterDamage;

		internal static ConfigEntry<float> BloodMoonStarChance;

		internal static ConfigEntry<int> BloodMoonLoot;

		internal static ConfigEntry<int> BloodMoonContracts;

		internal static ConfigEntry<float> BloodMoonTrophies;

		internal static ConfigEntry<bool> BloodMoonNoSleep;

		internal static ConfigEntry<bool> BloodMoonRedSky;

		internal static ConfigEntry<bool> BloodMoonMusic;

		private static readonly (string key, string ru, string en) General = (key: "1. Общее", ru: "1. Общее", en: "1. General");

		private static readonly (string key, string ru, string en) Storage = (key: "2. Склад", ru: "2. Склад", en: "2. Storage");

		private static readonly (string key, string ru, string en) Contracts = (key: "3. Контракты", ru: "3. Контракты", en: "3. Contracts");

		private static readonly (string key, string ru, string en) Rewards = (key: "4. Награды", ru: "4. Награды", en: "4. Rewards");

		private static readonly (string key, string ru, string en) AntiAbuse = (key: "5. Защита от абуза", ru: "5. Защита от абуза", en: "5. Anti-abuse");

		private static readonly (string key, string ru, string en) Legends = (key: "6. Именные чудовища", ru: "6. Именные чудовища", en: "6. Legends");

		private static readonly (string key, string ru, string en) Invasions = (key: "7. Вторжения", ru: "7. Вторжения", en: "7. Invasions");

		private static readonly (string key, string ru, string en) Caravan = (key: "8. Караван", ru: "8. Караван", en: "8. Caravan");

		private static readonly (string key, string ru, string en) Altar = (key: "9. Алтарь богов", ru: "9. Алтарь богов", en: "9. Gods' altar");

		private static readonly (string key, string ru, string en) WardSection = (key: "10. Оберег", ru: "10. Оберег", en: "10. Ward");

		private static readonly (string key, string ru, string en) BloodMoonSection = (key: "11. Кровавая луна", ru: "11. Кровавая луна", en: "11. Blood moon");

		private const string RecipeRu = "Предмет:количество через запятую. Применяется после перезапуска мира.";

		private const string RecipeEn = "Item:amount, comma separated. Applies after the world is restarted.";

		private static ConfigFile _config;

		private static int _order;

		private static (string key, string ru, string en) _section;

		private const int CurrentConfigVersion = 1;

		internal static ConfigSync Sync { get; private set; }

		internal static void Bind(ConfigFile config)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			_config = config;
			Sync = new ConfigSync("lemychad.utilsandextras")
			{
				DisplayName = "Skald's Board",
				CurrentVersion = "1.5.0",
				MinimumRequiredVersion = "1.5.0",
				ModRequired = true
			};
			Section(General);
			Language = Add("Language", LanguageChoice.Auto, (ru: "Язык", en: "Language"), (ru: "Auto — по языку игры: русский и белорусский → русский; украинский, французский, немецкий, польский — свои; остальные → английский. Переводы — в BepInEx/config/LemyChadPack/lang/, их можно править.", en: "Auto follows the game language: Russian and Belarusian → Russian; Ukrainian, French, German, Polish → their own; anything else → English. Translations are in BepInEx/config/LemyChadPack/lang/ and can be edited."), null, (ConfigSyncMode)2);
			LockConfig = Add("LockConfig", defaultValue: true, (ru: "Блокировка настроек", en: "Lock settings"), (ru: "Если включено, менять серверные настройки могут только администраторы сервера.", en: "When on, only server administrators can change server-side settings."), null, (ConfigSyncMode)0);
			((ConditionalConfigSync)Sync).AddLockingConfigEntry<bool>(LockConfig);
			Enabled = Add("Enabled", defaultValue: true, (ru: "Мод включён", en: "Mod enabled"), (ru: "Главный выключатель всех функций мода.", en: "Master switch for every feature of the mod."), null, (ConfigSyncMode)0);
			Section(Storage);
			StorageTableRecipe = Add("StorageTableRecipe", "FineWood:8,BronzeNails:10", (ru: "Рецепт стола склада", en: "Storage table recipe"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира. Раскладку по сундукам делает SmartContainers.", en: "Item:amount, comma separated. Applies after the world is restarted. Sorting items into chests is done by SmartContainers."), null, (ConfigSyncMode)0);
			LevelRadii = Add("LevelRadii", "30,40,55,70", (ru: "Радиус базы по уровням, м", en: "Base radius per level, m"), (ru: "Через запятую, для уровней стола 1–4. Сводка, поиск и заявки видят только сундуки в этом радиусе. Удалённого доступа к сундукам нет — только просмотр.", en: "Comma separated, for table levels 1–4. Overview, search and requests only see chests within this radius. Chests are never accessed remotely — view only."), null, (ConfigSyncMode)0);
			LevelRequests = Add("LevelRequests", "2,4,6,8", (ru: "Заявок по уровням", en: "Requests per level"), (ru: "Через запятую, для уровней стола 1–4: сколько заявок может быть открыто одновременно.", en: "Comma separated, for table levels 1–4: how many requests can be open at once."), null, (ConfigSyncMode)0);
			ExtensionRange = Add("ExtensionRange", 5f, (ru: "Дальность расширений, м", en: "Extension range, m"), (ru: "Расширение поднимает уровень стола, если стоит не дальше этого.", en: "An extension raises the table level if it stands within this distance."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 15f), (ConfigSyncMode)0);
			ScalesRecipe = Add("ScalesRecipe", "FineWood:6,Bronze:4", (ru: "Рецепт «Счётные весы» (уровень 2)", en: "\"Counting scales\" recipe (level 2)"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			VaultRecipe = Add("VaultRecipe", "RoundLog:10,Iron:6", (ru: "Рецепт «Сундук-сейф» (уровень 3)", en: "\"Strongbox\" recipe (level 3)"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			ShelfRecipe = Add("ShelfRecipe", "FineWood:10,Silver:6", (ru: "Рецепт «Стеллаж с картой» (уровень 4)", en: "\"Map shelf\" recipe (level 4)"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			RequestContractsMax = Add("RequestContractsMax", 6, (ru: "Контрактов из заявок на доске", en: "Request contracts on the board"), (ru: "Со 3-го уровня стола заявки попадают на доску как групповые контракты на поставку; не больше стольких одновременно.", en: "From table level 3, requests go up on the board as group delivery contracts; at most this many at once."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), (ConfigSyncMode)0);
			SearchEnabled = Add("SearchEnabled", defaultValue: true, (ru: "Поиск по складу", en: "Storage search"), (ru: "Поиск предмета по сундукам базы с подсветкой найденных.", en: "Search the base chests for an item and highlight where it is."), null, (ConfigSyncMode)0);
			SummaryEnabled = Add("SummaryEnabled", defaultValue: true, (ru: "Сводка склада", en: "Storage overview"), (ru: "Таблица: сколько каждого ресурса во всех сундуках базы.", en: "A table of how much of every resource is in all base chests."), null, (ConfigSyncMode)0);
			RequestsEnabled = Add("RequestsEnabled", defaultValue: true, (ru: "Заявки", en: "Requests"), (ru: "Строители указывают, что нужно для проекта, сводка показывает дефицит.", en: "Builders list what a project needs; the overview shows what is missing."), null, (ConfigSyncMode)0);
			ReserveEnabled = Add("ReserveEnabled", defaultValue: true, (ru: "Резерв под заявки", en: "Reserves for requests"), (ru: "Со 2-го уровня стола ресурсы можно отложить под заявку: забрать их может только автор заявки или администратор.", en: "From table level 2, resources can be set aside for a request: only its author or an administrator can take them."), null, (ConfigSyncMode)0);
			ReserveExpiryDays = Add("ReserveExpiryDays", 5, (ru: "Срок резерва, игровых дней", en: "Reserve duration, game days"), (ru: "Через сколько игровых дней резерв снимается сам, если заявку не закрыли.", en: "After how many game days a reserve lifts by itself if the request is still open."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), (ConfigSyncMode)0);
			LabelsEnabled = Add("LabelsEnabled", defaultValue: true, (ru: "Содержимое сундуков", en: "Chest contents"), (ru: "Показывать при наведении на сундук, что в нём лежит.", en: "Show what a chest holds when you hover over it."), null, (ConfigSyncMode)0);
			Section(Contracts);
			ContractsEnabled = Add("ContractsEnabled", defaultValue: true, (ru: "Доска контрактов включена", en: "Contract board enabled"), (ru: "", en: ""), null, (ConfigSyncMode)0);
			BoardRecipe = Add("BoardRecipe", "Wood:10,FineWood:4,Resin:4", (ru: "Рецепт доски контрактов", en: "Contract board recipe"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			GroupContractsOnBoard = Add("GroupContractsOnBoard", 4, (ru: "Групповых контрактов на доске", en: "Group contracts on the board"), (ru: "Сколько групповых контрактов висит на доске одновременно.", en: "How many group contracts are on the board at once."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), (ConfigSyncMode)0);
			PersonalOffers = Add("PersonalOffers", 6, (ru: "Личных предложений", en: "Personal offers"), (ru: "Из скольких личных контрактов игрок выбирает.", en: "How many personal contracts a player chooses from."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), (ConfigSyncMode)0);
			PersonalMaxActive = Add("PersonalMaxActive", 3, (ru: "Личных контрактов одновременно", en: "Personal contracts at once"), (ru: "Сколько личных контрактов игрок может держать взятыми.", en: "How many personal contracts a player can hold."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), (ConfigSyncMode)0);
			PersonalRerollsPerDay = Add("PersonalRerollsPerDay", 1, (ru: "Перебросов в день", en: "Rerolls per day"), (ru: "Сколько раз за игровой день игрок может обновить личные предложения.", en: "How many times per game day a player can refresh personal offers."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 5), (ConfigSyncMode)0);
			RefreshEveryDays = Add("RefreshEveryDays", 1, (ru: "Обновление доски, игровых дней", en: "Board refresh, game days"), (ru: "Как часто доска выдаёт новые контракты.", en: "How often the board hands out new contracts."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), (ConfigSyncMode)0);
			GroupAmountPerPlayer = Add("GroupAmountPerPlayer", 0.6f, (ru: "Рост объёма за игрока", en: "Amount growth per player"), (ru: "Групповой объём = базовый × (1 + это × (игроков онлайн − 1)). 0 — объём не зависит от онлайна.", en: "Group amount = base × (1 + this × (players online − 1)). 0 makes it independent of who is online."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), (ConfigSyncMode)0);
			RequestContractRewardShare = Add("RequestContractRewardShare", 0.5f, (ru: "Награда за контракты из заявок", en: "Request contract reward"), (ru: "Доля обычной награды для контрактов, созданных из заявок склада: свои же нужды базы не должны быть фермой наград.", en: "Share of the normal reward for contracts made from storage requests: the base's own needs should not be a reward farm."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (ConfigSyncMode)0);
			ChainsEnabled = Add("ChainsEnabled", defaultValue: true, (ru: "Цепочки контрактов", en: "Contract chains"), (ru: "Связанные контракты из нескольких шагов.", en: "Linked contracts of several steps."), null, (ConfigSyncMode)0);
			WeeklyEnabled = Add("WeeklyEnabled", defaultValue: true, (ru: "Контракт недели", en: "Weekly contract"), (ru: "Один большой групповой контракт на неделю.", en: "One big group contract per week."), null, (ConfigSyncMode)0);
			WeeklyLengthDays = Add("WeeklyLengthDays", 7, (ru: "Длина «недели», реальных дней", en: "\"Week\" length, real days"), (ru: "Сколько реальных дней длится контракт недели.", en: "How many real days the weekly contract lasts."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 14), (ConfigSyncMode)0);
			Section(Rewards);
			CoinMultiplier = Add("CoinMultiplier", 1f, (ru: "Множитель монет", en: "Coin multiplier"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), (ConfigSyncMode)0);
			MaterialMultiplier = Add("MaterialMultiplier", 1f, (ru: "Множитель материалов зачарования", en: "Enchanting material multiplier"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), (ConfigSyncMode)0);
			DailyMaterialCapPerPlayer = Add("DailyMaterialCapPerPlayer", 20, (ru: "Лимит материалов в день на игрока", en: "Daily material cap per player"), (ru: "Сколько материалов EpicLoot (пыль, эссенция, реагенты) игрок может получить с контрактов за реальные сутки. Сверх лимита награда выдаётся монетами.", en: "How many EpicLoot materials (dust, essence, reagents) a player can earn from contracts per real day. Beyond the cap the reward is paid in coins."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 500), (ConfigSyncMode)0);
			RunestoneChance = Add("RunestoneChance", 0.1f, (ru: "Шанс руны за сложный контракт", en: "Runestone chance for hard contracts"), (ru: "Шанс получить руну EpicLoot за контракт высокой сложности.", en: "Chance of an EpicLoot runestone for a hard contract."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (ConfigSyncMode)0);
			WeeklyRewardMultiplier = Add("WeeklyRewardMultiplier", 3f, (ru: "Множитель награды контракта недели", en: "Weekly contract reward multiplier"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), (ConfigSyncMode)0);
			Section(AntiAbuse);
			IgnoreTamed = Add("IgnoreTamed", defaultValue: true, (ru: "Не засчитывать прирученных", en: "Ignore tamed creatures"), (ru: "Убийства прирученных существ не идут в контракты.", en: "Killing tamed creatures does not count for contracts."), null, (ConfigSyncMode)0);
			IgnoreSummoned = Add("IgnoreSummoned", defaultValue: true, (ru: "Не засчитывать призванных", en: "Ignore summoned creatures"), (ru: "Убийства призванных и выведенных игроками существ не идут в контракты.", en: "Killing creatures summoned or bred by players does not count for contracts."), null, (ConfigSyncMode)0);
			MinDamageShareForKill = Add("MinDamageShareForKill", 0.1f, (ru: "Минимальная доля урона", en: "Minimum damage share"), (ru: "Какую долю здоровья моба надо снять, чтобы убийство засчиталось в контракт.", en: "Share of a creature's health you must deal for its kill to count for a contract."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (ConfigSyncMode)0);
			DepositCooldownMinutes = Add("DepositCooldownMinutes", 30, (ru: "Защита от «положил-забрал», мин", en: "Take-and-return guard, minutes"), (ru: "Предметы, забранные со склада, не засчитываются как вклад, если их снова положить в течение этого времени.", en: "Items taken from storage do not count as a contribution if they are put back within this time."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 240), (ConfigSyncMode)0);
			IgnoreSelfDroppedPickups = Add("IgnoreSelfDroppedPickups", defaultValue: true, (ru: "Не засчитывать выброшенное", en: "Ignore dropped items"), (ru: "Подобранные предметы, которые игроки сами выбросили, не считаются добычей.", en: "Picking up items that players dropped themselves does not count as gathering."), null, (ConfigSyncMode)0);
			IgnoreDeconstructedPieces = Add("IgnoreDeconstructedPieces", defaultValue: true, (ru: "Стройка: учитывать сносы", en: "Building: count demolitions"), (ru: "Снесённые постройки вычитаются из контрактов на стройку.", en: "Demolished pieces are subtracted from building contracts."), null, (ConfigSyncMode)0);
			Section(Legends);
			LegendsEnabled = Add("LegendsEnabled", defaultValue: true, (ru: "Именные чудовища включены", en: "Legends enabled"), (ru: "Легендарные существа с именами изредка появляются рядом с игроками. Список — в BepInEx/config/LemyChadPack/legends.yaml.", en: "Named legendary creatures now and then appear near players. The list is in BepInEx/config/LemyChadPack/legends.yaml."), null, (ConfigSyncMode)0);
			LegendCheckMinutes = Add("LegendCheckMinutes", 20f, (ru: "Проверка появления, минут", en: "Spawn check, minutes"), (ru: "Как часто (в реальных минутах) сервер решает, не появиться ли легенде.", en: "How often (in real minutes) the server decides whether a legend appears."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 240f), (ConfigSyncMode)0);
			LegendSpawnChance = Add("LegendSpawnChance", 0.35f, (ru: "Шанс появления", en: "Spawn chance"), (ru: "Шанс при каждой проверке, если сейчас нет живой легенды.", en: "Chance at each check while no legend is alive."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (ConfigSyncMode)0);
			LegendLifetimeDays = Add("LegendLifetimeDays", 2, (ru: "Сколько живёт легенда, игровых дней", en: "Legend lifetime, game days"), (ru: "Если её не убили за это время, она уходит.", en: "If nobody kills it within this time, it leaves."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), (ConfigSyncMode)0);
			LegendAreaRadius = Add("LegendAreaRadius", 120f, (ru: "Радиус области на карте, м", en: "Map area radius, m"), (ru: "Метка на карте — область, где-то внутри которой бродит легенда.", en: "The map mark is an area somewhere inside which the legend roams."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 400f), (ConfigSyncMode)0);
			LegendRewardMultiplier = Add("LegendRewardMultiplier", 1f, (ru: "Множитель награды", en: "Reward multiplier"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), (ConfigSyncMode)0);
			LegendHealthPerPlayer = Add("LegendHealthPerPlayer", 0.35f, (ru: "Здоровье за игрока онлайн", en: "Health per player online"), (ru: "Здоровье легенды × (1 + это × (игроков онлайн − 1)): на десятерых при 0.35 — примерно вчетверо больше. 0 — не зависит от онлайна.", en: "Legend health × (1 + this × (players online − 1)): with ten players at 0.35, about four times as much. 0 makes it independent of who is online."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), (ConfigSyncMode)0);
			LegendPower = Add("LegendPower", 1.1f, (ru: "Сила легенд", en: "Legend power"), (ru: "Множитель здоровья и урона всех легенд (поверх legends.yaml и потолка max_health). 1.1 — на 10% сильнее.", en: "Multiplies every legend's health and damage (on top of legends.yaml and its max_health cap). 1.1 is 10% stronger."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f), (ConfigSyncMode)0);
			Section(Invasions);
			InvasionsEnabled = Add("InvasionsEnabled", defaultValue: true, (ru: "Вторжения включены", en: "Invasions enabled"), (ru: "Отряды врагов текущего биома идут на базу — к столу склада. Составы — в BepInEx/config/LemyChadPack/invasions.yaml.", en: "Warbands of the current biome march on a base — a storage table. Their make-up is in BepInEx/config/LemyChadPack/invasions.yaml."), null, (ConfigSyncMode)0);
			InvasionCheckMinutes = Add("InvasionCheckMinutes", 120f, (ru: "Проверка вторжения, минут", en: "Invasion check, minutes"), (ru: "Как часто (в реальных минутах) сервер решает, не начать ли вторжение. Для сравнения: ванильные рейды — раз в 46 минут с шансом около 20%.", en: "How often (in real minutes) the server decides whether an invasion starts. For comparison, vanilla raids roll every 46 minutes at about 20%."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 1440f), (ConfigSyncMode)0);
			InvasionChance = Add("InvasionChance", 0.15f, (ru: "Шанс вторжения", en: "Invasion chance"), (ru: "Шанс при каждой проверке, если сейчас нет вторжения.", en: "Chance at each check while no invasion is under way."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (ConfigSyncMode)0);
			InvasionCooldownHours = Add("InvasionCooldownHours", 12f, (ru: "Перерыв между вторжениями, часов", en: "Cooldown between invasions, hours"), (ru: "Сколько реальных часов после конца вторжения новое не начнётся само. Переживает перезапуск сервера. Команда lc_invasion start его не учитывает.", en: "Real hours after an invasion ends before another can start by itself. Survives server restarts. The lc_invasion start command ignores it."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 168f), (ConfigSyncMode)0);
			InvasionMinPlayers = Add("InvasionMinPlayers", 2, (ru: "Минимум игроков онлайн", en: "Minimum players online"), (ru: "Сколько игроков должно быть в игре, чтобы вторжение могло начаться само.", en: "How many players must be online for an invasion to start by itself."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), (ConfigSyncMode)0);
			InvasionPrepMinutes = Add("InvasionPrepMinutes", 3f, (ru: "Время на подготовку, минут", en: "Preparation time, minutes"), (ru: "Сколько реальных минут проходит от объявления до выступления отряда.", en: "Real minutes between the announcement and the warband setting off."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), (ConfigSyncMode)0);
			InvasionMarchMinutes = Add("InvasionMarchMinutes", 15f, (ru: "Время марша, минут", en: "March time, minutes"), (ru: "За сколько реальных минут отряд доходит до базы.", en: "Real minutes the warband needs to reach the base."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), (ConfigSyncMode)0);
			InvasionDistance = Add("InvasionDistance", 1200f, (ru: "Откуда идёт отряд, м", en: "Starting distance, m"), (ru: "На каком расстоянии от базы отряд выступает. Если там только море, берётся точка ближе (до 40% этого).", en: "How far from the base the warband sets off. If there is only sea out there, a closer point is taken (down to 40% of this)."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(200f, 4000f), (ConfigSyncMode)0);
			InvasionBaseRadius = Add("InvasionBaseRadius", 120f, (ru: "Где отряд встаёт у базы, м", en: "Where the warband halts at the base, m"), (ru: "На каком расстоянии от стола склада отряд останавливается и появляется, если его не перехватили. Бой начинается, когда игрок ближе к столу, чем это + 90 м.", en: "How far from the storage table the warband halts and appears if nobody intercepted it. The fight starts once a player is closer to the table than this + 90 m."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 150f), (ConfigSyncMode)0);
			InvasionInterceptRadius = Add("InvasionInterceptRadius", 80f, (ru: "Радиус перехвата, м", en: "Interception radius, m"), (ru: "Как близко к идущему отряду нужно подойти, чтобы он вступил в бой. Нужно видеть отряд: холм или гора между вами и отрядом не дают перехвата, как и большой перепад высоты (больше 25 м).", en: "How close to the marching warband a player must come for it to engage. The warband must be in sight: a hill or mountain between you, or more than 25 m of height difference, means no interception."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 150f), (ConfigSyncMode)0);
			InvasionSizePerPlayer = Add("InvasionSizePerPlayer", 0.5f, (ru: "Размер отряда за игрока", en: "Warband size per player"), (ru: "Число врагов × (1 + это × (игроков онлайн − 1)).", en: "Number of enemies × (1 + this × (players online − 1))."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), (ConfigSyncMode)0);
			InvasionRewardMultiplier = Add("InvasionRewardMultiplier", 1f, (ru: "Множитель награды", en: "Reward multiplier"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), (ConfigSyncMode)0);
			InvasionMinStars = Add("InvasionMinStars", 5, (ru: "Минимум звёзд у бойцов", en: "Minimum stars per invader"), (ru: "Сколько звёзд PathOfValheiman получает каждый боец отряда как минимум (с ними — его надбавки и модификаторы). Предводитель — на 2 больше.", en: "The fewest PathOfValheiman stars every invader gets (with its scaling and modifiers). The leader gets 2 more."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), (ConfigSyncMode)0);
			InvasionExtraStarChance = Add("InvasionExtraStarChance", 0.5f, (ru: "Шанс каждой следующей звезды", en: "Chance of each further star"), (ru: "Сверх минимума каждая следующая звезда выпадает с этим шансом, пока не выпадет промах. Сверху ограничивает только «Max stars» PathOfValheiman.", en: "Above the minimum, each further star comes with this chance until a roll fails. Only PathOfValheiman's \"Max stars\" caps it."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.95f), (ConfigSyncMode)0);
			Section(Caravan);
			CaravanEnabled = Add("CaravanEnabled", defaultValue: true, (ru: "Караван торговца включён", en: "Merchant caravan enabled"), (ru: "Раз в несколько игровых дней к столу склада приезжает торговец: скупает излишки за монеты и продаёт редкий товар. Товары — в BepInEx/config/LemyChadPack/caravan.yaml.", en: "Every few in-game days a merchant comes to a storage table: buys surplus goods for coins and sells rare ones. The goods are in BepInEx/config/LemyChadPack/caravan.yaml."), null, (ConfigSyncMode)0);
			CaravanIntervalDays = Add("CaravanIntervalGameDays", 14, (ru: "Караван приходит раз в, игровых дней", en: "Caravan comes every, in-game days"), (ru: "Игровых дней (суток Valheim, около 30 реальных минут каждые) между приездами. Если в срок никого нет, караван приедет, когда кто-нибудь зайдёт.", en: "In-game days (Valheim days, about 30 real minutes each) between visits. If nobody is on when it is due, it comes once someone joins."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), (ConfigSyncMode)0);
			CaravanStayMinutes = Add("CaravanStayMinutes", 60f, (ru: "Караван стоит, минут", en: "Caravan stays, minutes"), (ru: "Сколько минут игры торговец стоит у базы. Пока на сервере никого нет, время не идёт.", en: "Minutes of play the merchant stays at the base. The clock stops while nobody is on."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 600f), (ConfigSyncMode)0);
			CaravanMinPlayers = Add("CaravanMinPlayers", 1, (ru: "Минимум игроков для приезда", en: "Players needed for a visit"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), (ConfigSyncMode)0);
			CaravanOffers = Add("CaravanOffers", 20, (ru: "Товаров за приезд", en: "Goods per visit"), (ru: "Сколько разных товаров привозит торговец. Покупает он всё из списка wants открытых ступеней.", en: "How many different goods the merchant brings. He buys everything in the wants list of the unlocked tiers."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), (ConfigSyncMode)0);
			CaravanBuyPriceMultiplier = Add("CaravanBuyPriceMultiplier", 1f, (ru: "Множитель цен торговца", en: "Merchant price multiplier"), (ru: "Во сколько раз дороже или дешевле продаёт торговец.", en: "How much more or less the merchant charges."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), (ConfigSyncMode)0);
			CaravanSellPriceMultiplier = Add("CaravanSellPriceMultiplier", 1f, (ru: "Множитель цен скупки", en: "Buy-back price multiplier"), (ru: "Во сколько раз больше или меньше торговец платит за ваши ресурсы.", en: "How much more or less the merchant pays for your resources."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), (ConfigSyncMode)0);
			CaravanPurse = Add("CaravanPurse", 300, (ru: "Кошелёк торговца", en: "Merchant's purse"), (ru: "Сколько монет торговец может заплатить группе за ресурсы за один приезд, всего: это × «монеты за очко» текущего биома (Луга — 300, Болото — 540, Пепельные земли — 1320). 0 — без ограничения.", en: "Coins the merchant can pay the group for resources in one visit, in total: this × the current biome's coins per point (Meadows 300, Swamp 540, Ashlands 1320). 0 means no limit."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), (ConfigSyncMode)0);
			CaravanGearOffers = Add("CaravanGearOffers", 4, (ru: "Зачарованных вещей за приезд", en: "Enchanted gear per visit"), (ru: "Оружие и броня текущего биома, зачарованные EpicLoot при покупке: в первых двух биомах — магические, дальше редкие, эпические, легендарные; каждая четвёртая на ступень лучше. Без EpicLoot их нет.", en: "Weapons and armour of the current biome, enchanted by EpicLoot when bought: Magic in the first two biomes, then Rare, Epic, Legendary; one in four is a step better. None without EpicLoot."), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 12), (ConfigSyncMode)0);
			CaravanGearPriceMultiplier = Add("CaravanGearPriceMultiplier", 1f, (ru: "Множитель цен на снаряжение", en: "Gear price multiplier"), (ru: "Цена вещи = 150 / 300 / 600 / 1100 / 1800 / 2800 монет по редкости × монет за очко текущего биома × это.", en: "Price of a piece = 150 / 300 / 600 / 1100 / 1800 / 2800 coins by rarity × the current biome's coins per point × this."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), (ConfigSyncMode)0);
			Section(Altar);
			AltarEnabled = Add("AltarEnabled", defaultValue: true, (ru: "Алтарь богов включён", en: "Gods' altar enabled"), (ru: "Дары богам и благословения группы. Боги, дары и благословения — в BepInEx/config/LemyChadPack/gods.yaml.", en: "Offerings to the gods and group blessings. Gods, offerings and blessings are in BepInEx/config/LemyChadPack/gods.yaml."), null, (ConfigSyncMode)0);
			AltarRecipe = Add("AltarRecipe", "Stone:30,FineWood:10,Resin:10", (ru: "Рецепт алтаря", en: "Altar recipe"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			FavorMultiplier = Add("FavorMultiplier", 1f, (ru: "Множитель нужной благосклонности", en: "Favour needed multiplier"), (ru: "Больше — благословения реже: нужно больше даров.", en: "Higher means rarer blessings: more offerings are needed."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), (ConfigSyncMode)0);
			BlessingStrength = Add("BlessingStrength", 1f, (ru: "Сила благословений", en: "Blessing strength"), (ru: "Множитель всех бонусов благословений (кроме сопротивлений).", en: "Scales every blessing bonus (except resistances)."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), (ConfigSyncMode)0);
			BlessingMinutes = Add("BlessingMinutes", 30f, (ru: "Длительность благословения, минут", en: "Blessing length, minutes"), (ru: "Сколько минут игры длится благословение — одинаково, когда бы шкала ни заполнилась. Время идёт, только пока кто-то в игре; сон его не съедает. Повторное наполнение добавляет столько же, до двойного запаса.", en: "Minutes of play a blessing lasts — the same whenever the bar fills. It only runs while someone is on, and sleeping does not eat it. Filling the bar again adds as much once more, up to twice the length in store."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 240f), (ConfigSyncMode)0);
			Section(WardSection);
			WardEnabled = Add("WardEnabled", defaultValue: true, (ru: "Оберег включён", en: "Ward enabled"), (ru: "Постройка, в радиусе которой мобы не появляются. Ванильные рейды по-прежнему приходят, но их мобы появляются за краем радиуса; вторжения и легенды оберег не трогает.", en: "A piece within whose radius creatures do not spawn. Vanilla raids still come, but their creatures appear beyond the edge of the radius; invasions and legends are not affected."), null, (ConfigSyncMode)0);
			WardRecipe = Add("WardRecipe", "Stone:30,FineWood:15,Bronze:5,SurtlingCore:5", (ru: "Рецепт малого оберега", en: "Lesser ward recipe"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			WardRecipe2 = Add("WardRecipe2", "Stone:40,ElderBark:20,Iron:10,SurtlingCore:8", (ru: "Рецепт оберега", en: "Ward recipe"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			WardRecipe3 = Add("WardRecipe3", "Obsidian:20,Silver:10,Crystal:5,Iron:10", (ru: "Рецепт большого оберега", en: "Greater ward recipe"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			WardRecipe4 = Add("WardRecipe4", "BlackMetal:15,LinenThread:20,Silver:10,Crystal:10", (ru: "Рецепт великого оберега", en: "Grand ward recipe"), (ru: "Предмет:количество через запятую. Применяется после перезапуска мира.", en: "Item:amount, comma separated. Applies after the world is restarted."), null, (ConfigSyncMode)0);
			WardRadii = Add("WardRadii", "75,100,125,150", (ru: "Радиусы оберегов, м", en: "Ward radii, m"), (ru: "Малый, обычный, большой и великий оберег, через запятую.", en: "Lesser, normal, greater and grand ward, comma separated."), null, (ConfigSyncMode)0);
			WardScareWeak = Add("WardScareWeak", defaultValue: true, (ru: "Отпугивать слабых мобов", en: "Scare off weak creatures"), (ru: "Мобы без звёзд, зашедшие в радиус, убегают. Рейды, вторжения, легенды и боссы не боятся.", en: "Creatures without stars that walk into the radius flee. Raids, invasions, legends and bosses are not scared."), null, (ConfigSyncMode)0);
			WardBuildingProtection = Add("WardBuildingProtection", 0.5f, (ru: "Защита построек", en: "Building protection"), (ru: "Насколько меньше урона мобы наносят постройкам в радиусе (0.5 — вдвое меньше). Урон от рейдов, вторжений и игроков не меняется.", en: "How much less damage creatures deal to buildings in the radius (0.5 is half). Damage from raids, invasions and players is unchanged."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (ConfigSyncMode)0);
			WardWarnings = Add("WardWarnings", defaultValue: true, (ru: "Предупреждать о врагах", en: "Warn about enemies"), (ru: "Сообщение, когда враг заходит в радиус оберега (тем, кто на базе).", en: "A message when an enemy enters the ward's radius (to those at the base)."), null, (ConfigSyncMode)2);
			Section(BloodMoonSection);
			BloodMoonEnabled = Add("BloodMoonEnabled", defaultValue: true, (ru: "Кровавая луна включена", en: "Blood moon enabled"), (ru: "Редкая ночь, о которой предупреждают днём: мобы злее, зато добыча, контракты и трофеи богаче.", en: "A rare night announced in the afternoon: creatures are fiercer, but loot, contracts and trophies are richer."), null, (ConfigSyncMode)0);
			BloodMoonChance = Add("BloodMoonChance", 0.12f, (ru: "Шанс кровавой луны", en: "Blood moon chance"), (ru: "Шанс каждого вечера, если с прошлой прошло достаточно дней.", en: "Chance each evening, once enough days have passed since the last one."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (ConfigSyncMode)0);
			BloodMoonMinDays = Add("BloodMoonMinDays", 7, (ru: "Не чаще, чем раз в, игровых дней", en: "No more often than every, in-game days"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), (ConfigSyncMode)0);
			BloodMoonMonsterDamage = Add("BloodMoonMonsterDamage", 1.5f, (ru: "Урон мобов", en: "Creature damage"), (ru: "Множитель урона мобов в кровавую луну.", en: "Creature damage multiplier under the blood moon."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), (ConfigSyncMode)0);
			BloodMoonStarChance = Add("BloodMoonStarChance", 2f, (ru: "Шанс звёзд", en: "Star chance"), (ru: "Во сколько раз чаще появляющиеся мобы получают звёзды.", en: "How many times more often spawning creatures get stars."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), (ConfigSyncMode)0);
			BloodMoonLoot = Add("BloodMoonLoot", 2, (ru: "Множитель добычи", en: "Loot multiplier"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), (ConfigSyncMode)0);
			BloodMoonContracts = Add("BloodMoonContracts", 2, (ru: "Множитель убийств для контрактов", en: "Kills count for contracts ×"), (ru: "", en: ""), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), (ConfigSyncMode)0);
			BloodMoonTrophies = Add("BloodMoonTrophies", 3f, (ru: "Трофеи для богов ×", en: "Trophies for the gods ×"), (ru: "Во сколько раз больше благосклонности дают трофеи, принесённые в кровавую луну.", en: "How much more favour trophies bring when offered under the blood moon."), (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), (ConfigSyncMode)0);
			BloodMoonNoSleep = Add("BloodMoonNoSleep", defaultValue: true, (ru: "Нельзя проспать", en: "Cannot be slept through"), (ru: "В кровавую луну кровати не дают уснуть.", en: "Beds do not let anyone sleep under the blood moon."), null, (ConfigSyncMode)0);
			BloodMoonRedSky = Add("BloodMoonRedSky", defaultValue: true, (ru: "Красное небо", en: "Red sky"), (ru: "Окрашивать ночь в красный (у каждого игрока своё).", en: "Tint the night red (each player decides)."), null, (ConfigSyncMode)2);
			BloodMoonMusic = Add("BloodMoonMusic", defaultValue: true, (ru: "Музыка при восходе", en: "Music when it rises"), (ru: "Один раз проиграть свой трек, когда восходит луна. Файл: BepInEx/config/LemyChadPack/music/bloodmoon.ogg (или .wav, .mp3).", en: "Play your own track once when the moon rises. File: BepInEx/config/LemyChadPack/music/bloodmoon.ogg (or .wav, .mp3)."), null, (ConfigSyncMode)2);
			Migrate();
		}

		private static void Migrate()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			ConfigEntry<int> val = _config.Bind<int>("1. Общее", "ConfigVersion", 0, new ConfigDescription("Internal: settings migrations already applied. Do not edit.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			if (val.Value >= 1)
			{
				return;
			}
			int num = 0;
			if (val.Value < 1)
			{
				num += Step(InvasionCheckMinutes, 60f, 120f);
				num += Step(InvasionChance, 0.3f, 0.15f);
				num += Step(InvasionDistance, 600f, 1200f);
				num += Step(InvasionMarchMinutes, 10f, 15f);
				num += Step(InvasionSizePerPlayer, 0.3f, 0.5f);
				if (CaravanOffers.Value == 16)
				{
					CaravanOffers.Value = 20;
					num++;
				}
			}
			val.Value = 1;
			_config.Save();
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"Settings: {num} old default values moved to the new defaults");
			}
		}

		private static int Step(ConfigEntry<float> entry, float oldDefault, float newDefault)
		{
			if (Math.Abs(entry.Value - oldDefault) > 0.0001f)
			{
				return 0;
			}
			entry.Value = newDefault;
			return 1;
		}

		private static void Section((string key, string ru, string en) section)
		{
			_section = section;
		}

		private static ConfigEntry<T> Add<T>(string key, T defaultValue, (string ru, string en) name, (string ru, string en) description, AcceptableValueBase acceptable = null, ConfigSyncMode mode = (ConfigSyncMode)0)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				DispName = Loc.T(name.ru, name.en),
				Category = Loc.T(_section.ru, _section.en),
				Order = (_order -= 1)
			};
			ConfigEntry<T> val = _config.Bind<T>(_section.key, key, defaultValue, new ConfigDescription(Loc.T(description.ru, description.en), acceptable, new object[1] { configurationManagerAttributes }));
			((ConditionalConfigSync)Sync).AddConfigEntry<T>(val, mode);
			return val;
		}
	}
	internal static class DataFiles
	{
		internal static string PathOf(string fileName)
		{
			return Path.Combine(Paths.ConfigPath, "LemyChadPack", fileName);
		}

		internal static bool Ensure(string fileName, string resourceName)
		{
			string text;
			using (Stream stream = typeof(DataFiles).Assembly.GetManifestResourceStream(resourceName))
			{
				using StreamReader streamReader = new StreamReader(stream);
				text = streamReader.ReadToEnd();
			}
			string text2 = PathOf(fileName);
			Directory.CreateDirectory(Path.GetDirectoryName(text2));
			bool result = false;
			if (File.Exists(text2))
			{
				int num = VersionOf(File.ReadAllText(text2));
				int num2 = VersionOf(text);
				if (num >= num2)
				{
					return false;
				}
				File.Copy(text2, text2 + $".v{num}.bak", overwrite: true);
				result = true;
				Plugin.Log.LogInfo((object)$"{fileName} updated from version {num} to {num2}; the old file was kept as .bak");
			}
			File.WriteAllText(text2, text);
			return result;
		}

		private static int VersionOf(string yaml)
		{
			Match match = Regex.Match(yaml, "^version:\\s*(\\d+)", RegexOptions.Multiline);
			if (!match.Success)
			{
				return 0;
			}
			return int.Parse(match.Groups[1].Value);
		}
	}
	internal enum Lang
	{
		Ru,
		En,
		Uk,
		Fr,
		De,
		Pl
	}
	internal static class Loc
	{
		private const char Separator = '\u001f';

		private static readonly Regex ItemToken = new Regex("\\{item:([^}]+)\\}");

		internal static readonly string[] FileLanguages = new string[4] { "uk", "fr", "de", "pl" };

		internal static Lang Current
		{
			get
			{
				switch (PackConfig.Language?.Value)
				{
				case LanguageChoice.Russian:
					return Lang.Ru;
				case LanguageChoice.English:
					return Lang.En;
				case LanguageChoice.Ukrainian:
					return Lang.Uk;
				case LanguageChoice.French:
					return Lang.Fr;
				case LanguageChoice.German:
					return Lang.De;
				case LanguageChoice.Polish:
					return Lang.Pl;
				default:
					switch ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : PlayerPrefs.GetString("language", "English"))
					{
					case "Russian":
					case "Belarusian":
						return Lang.Ru;
					case "Ukrainian":
						return Lang.Uk;
					case "French":
						return Lang.Fr;
					case "German":
						return Lang.De;
					case "Polish":
						return Lang.Pl;
					default:
						return Lang.En;
					}
				}
			}
		}

		internal static bool Russian => Current == Lang.Ru;

		internal static void Init()
		{
			string[] fileLanguages = FileLanguages;
			foreach (string text in fileLanguages)
			{
				try
				{
					DataFiles.Ensure("lang/" + text + ".yaml", "LemyChadPack.lang." + text + ".yaml");
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Localization: lang/" + text + ".yaml not written: " + ex.Message));
				}
			}
		}

		internal static string T(string ru, string en)
		{
			Lang current = Current;
			return current switch
			{
				Lang.En => en, 
				Lang.Ru => ru, 
				_ => Translations.Translate(current, en), 
			};
		}

		internal static string Both(string ru, string en)
		{
			return ru + "\u001f" + (en ?? ru ?? "");
		}

		internal static string Pick(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text ?? "";
			}
			int num = text.IndexOf('\u001f');
			if (num < 0)
			{
				return text;
			}
			Lang current = Current;
			if (current == Lang.Ru)
			{
				return text.Substring(0, num);
			}
			string text2 = text.Substring(num + 1);
			if (current != Lang.En)
			{
				return Translations.Translate(current, text2);
			}
			return text2;
		}

		internal static string Ru(string text)
		{
			int num = (text ?? "").IndexOf('\u001f');
			if (num >= 0)
			{
				return text.Substring(0, num);
			}
			return text ?? "";
		}

		internal static string En(string text)
		{
			int num = (text ?? "").IndexOf('\u001f');
			if (num >= 0)
			{
				return text.Substring(num + 1);
			}
			return text ?? "";
		}

		internal static string Render(string text)
		{
			return ItemToken.Replace(Pick(text), (Match m) => ItemNames.Get(m.Groups[1].Value));
		}

		internal static string Item(string prefab)
		{
			return "{item:" + prefab + "}";
		}
	}
	internal static class Translations
	{
		private sealed class LangFile
		{
			public int Version { get; set; }

			public string Language { get; set; }

			public Dictionary<string, string> Strings { get; set; } = new Dictionary<string, string>();
		}

		private sealed class Template
		{
			public Regex Pattern;

			public int[] Slots;

			public string Probe;

			public string Translation;
		}

		private static Lang _loaded = Lang.En;

		private static Dictionary<string, string> _exact = new Dictionary<string, string>();

		private static List<Template> _templates = new List<Template>();

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

		private static readonly Regex Placeholder = new Regex("\\{(\\d+)\\}");

		private static readonly Regex PlainValue = new Regex("^[\\s\\d.,:%/+\\-−×()]*$");

		private static string CodeOf(Lang lang)
		{
			return lang.ToString().ToLowerInvariant();
		}

		internal static string Translate(Lang lang, string en, int depth = 0)
		{
			if (string.IsNullOrEmpty(en))
			{
				return en ?? "";
			}
			if (lang != _loaded)
			{
				Load(lang);
			}
			if (depth == 0 && Cache.TryGetValue(en, out var value))
			{
				return value;
			}
			string text = Find(en, depth) ?? en;
			if (depth == 0)
			{
				if (Cache.Count > 5000)
				{
					Cache.Clear();
				}
				Cache[en] = text;
			}
			return text;
		}

		private static string Find(string en, int depth)
		{
			if (_exact.TryGetValue(en, out var value))
			{
				return value;
			}
			foreach (Template template in _templates)
			{
				if (template.Probe.Length > 0 && en.IndexOf(template.Probe, StringComparison.Ordinal) < 0)
				{
					continue;
				}
				Match match = template.Pattern.Match(en);
				if (match.Success)
				{
					Dictionary<int, string> values = new Dictionary<int, string>();
					for (int i = 0; i < template.Slots.Length; i++)
					{
						string value2 = match.Groups[i + 1].Value;
						values[template.Slots[i]] = ((depth < 3 && !PlainValue.IsMatch(value2)) ? Translate(_loaded, value2, depth + 1) : value2);
					}
					string value3;
					return Placeholder.Replace(template.Translation, (Match p) => (!values.TryGetValue(int.Parse(p.Groups[1].Value), out value3)) ? p.Value : value3);
				}
			}
			return null;
		}

		internal static void Load(Lang lang)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			_loaded = lang;
			Cache.Clear();
			_exact = new Dictionary<string, string>();
			_templates = new List<Template>();
			if (lang == Lang.Ru || lang == Lang.En)
			{
				return;
			}
			string text = DataFiles.PathOf("lang/" + CodeOf(lang) + ".yaml");
			try
			{
				foreach (KeyValuePair<string, string> item in ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(UnderscoredNamingConvention.Instance).IgnoreUnmatchedProperties().Build()
					.Deserialize<LangFile>(File.ReadAllText(text))?.Strings ?? new Dictionary<string, string>())
				{
					if (string.IsNullOrEmpty(item.Key) || string.IsNullOrEmpty(item.Value))
					{
						continue;
					}
					if (Placeholder.IsMatch(item.Key))
					{
						Template template = Build(item.Key, item.Value);
						if (template != null)
						{
							_templates.Add(template);
						}
					}
					else
					{
						_exact[item.Key] = item.Value;
					}
				}
				_templates = _templates.OrderByDescending((Template t) => t.Pattern.ToString().Length).ToList();
				Plugin.Log.LogInfo((object)$"Localization: {CodeOf(lang)} — {_exact.Count} texts, {_templates.Count} templates");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Localization: " + text + " not read (" + ex.Message + "); showing English"));
			}
		}

		private static Template Build(string key, string translation)
		{
			string[] array = Placeholder.Split(key);
			List<int> list = new List<int>();
			StringBuilder stringBuilder = new StringBuilder("^");
			string text = "";
			int num = 0;
			for (int i = 0; i < array.Length; i++)
			{
				if (i % 2 == 0)
				{
					stringBuilder.Append(Regex.Escape(array[i]));
					num += array[i].Count((char c) => !char.IsWhiteSpace(c));
					if (array[i].Length > text.Length)
					{
						text = array[i];
					}
				}
				else
				{
					list.Add(int.Parse(array[i]));
					stringBuilder.Append("(.+?)");
				}
			}
			stringBuilder.Append("$");
			if (num < 2)
			{
				return null;
			}
			return new Template
			{
				Pattern = new Regex(stringBuilder.ToString(), RegexOptions.Singleline | RegexOptions.CultureInvariant),
				Slots = list.ToArray(),
				Probe = text,
				Translation = translation
			};
		}
	}
	internal enum LanguageChoice
	{
		Auto,
		Russian,
		English,
		Ukrainian,
		French,
		German,
		Polish
	}
	internal static class PieceUtil
	{
		internal static void StripInteraction(GameObject prefab)
		{
			foreach (MonoBehaviour item in (from c in prefab.GetComponentsInChildren<MonoBehaviour>(true)
				where c is Interactable || c is Hoverable || c is TextReceiver
				select c).ToList())
			{
				Object.DestroyImmediate((Object)(object)item, true);
			}
		}

		internal static void RenderIcon(Piece piece)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			if ((Object)(object)piece == (Object)null || (int)SystemInfo.graphicsDeviceType == 4)
			{
				return;
			}
			try
			{
				Sprite val = RenderManager.Instance.Render(new RenderRequest(((Component)piece).gameObject)
				{
					Rotation = RenderManager.IsometricRotation,
					Width = 128,
					Height = 128,
					UseCache = false
				});
				if ((Object)(object)val != (Object)null)
				{
					piece.m_icon = val;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Icon for " + ((Object)piece).name + " not rendered: " + ex.Message));
			}
		}
	}
	[BepInPlugin("lemychad.utilsandextras", "Skald's Board", "1.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "lemychad.utilsandextras";

		public const string Name = "Skald's Board";

		public const string Version = "1.5.0";

		internal const string ConditionalConfigSyncGuid = "_shudnal.ConditionalConfigSync";

		internal const string EpicLootGuid = "randyknapp.mods.epicloot";

		internal const string SmartContainersGuid = "flueno.SmartContainers";

		internal const string YamlDotNetDetectorGuid = "com.ValheimModding.YamlDotNetDetector";

		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Loc.Init();
			PackConfig.Bind(((BaseUnityPlugin)this).Config);
			StoragePieces.Register();
			ContractCatalog.Init();
			LegendCatalog.Init();
			LegendCommand.Register();
			InvasionCatalog.Init();
			InvasionCommand.Register();
			CaravanCatalog.Init();
			CaravanCommand.Register();
			CaravanMerchant.Register();
			AltarCatalog.Init();
			AltarCommand.Register();
			GodsAltar.Register();
			LemyChadPack.Ward.Ward.Register();
			WardWatch.Ensure();
			BloodMoonCommand.Register();
			BloodMoonMusic.Init();
			_harmony = new Harmony("lemychad.utilsandextras");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"Skald's Board 1.5.0 loaded");
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class UiState
	{
		internal static bool AnyOpen
		{
			get
			{
				if (!StorageWindow.IsOpen)
				{
					return BoardWindow.IsOpen;
				}
				return true;
			}
		}
	}
}
namespace LemyChadPack.Ward
{
	[HarmonyPatch]
	internal sealed class Ward : MonoBehaviour, Hoverable, Interactable
	{
		internal sealed class Tier
		{
			public int Level;

			public string Prefab;

			public string NameRu;

			public string NameEn;

			public string Station;

			public string Trophy;

			public string[] Flames;

			public float PoleHeight;
		}

		private const string BasePrefab = "piece_table";

		private const float RaidSpawnMargin = 8f;

		internal static readonly Tier[] Tiers = new Tier[4]
		{
			new Tier
			{
				Level = 1,
				Prefab = "LC_Ward",
				NameRu = "Малый оберег",
				NameEn = "Lesser ward",
				Station = CraftingStations.Workbench,
				Trophy = "TrophyEikthyr",
				Flames = new string[1] { "piece_groundtorch_wood" },
				PoleHeight = 2.2f
			},
			new Tier
			{
				Level = 2,
				Prefab = "LC_Ward2",
				NameRu = "Оберег",
				NameEn = "Ward",
				Station = CraftingStations.Forge,
				Trophy = "TrophyTheElder",
				Flames = new string[2] { "piece_groundtorch_green", "piece_groundtorch_wood" },
				PoleHeight = 2.6f
			},
			new Tier
			{
				Level = 3,
				Prefab = "LC_Ward3",
				NameRu = "Большой оберег",
				NameEn = "Greater ward",
				Station = CraftingStations.Forge,
				Trophy = "TrophyBonemass",
				Flames = new string[3] { "piece_groundtorch_blue", "piece_groundtorch_green", "piece_groundtorch_wood" },
				PoleHeight = 3f
			},
			new Tier
			{
				Level = 4,
				Prefab = "LC_Ward4",
				NameRu = "Великий оберег",
				NameEn = "Grand ward",
				Station = CraftingStations.Forge,
				Trophy = "TrophyDragonQueen",
				Flames = new string[3] { "piece_groundtorch_mist", "piece_groundtorch_blue", "piece_groundtorch_wood" },
				PoleHeight = 3.4f
			}
		};

		internal static readonly List<Ward> Loaded = new List<Ward>();

		public int Level = 1;

		private ZNetView _nview;

		private CircleProjector _marker;

		private float _nextMarkerCheck;

		private static bool Active
		{
			get
			{
				if (PackConfig.Enabled.Value)
				{
					return PackConfig.WardEnabled.Value;
				}
				return false;
			}
		}

		internal float Radius => RadiusOf(Level);

		private Tier TierInfo => Tiers[Mathf.Clamp(Level, 1, Tiers.Length) - 1];

		private bool IsValid
		{
			get
			{
				if ((Object)(object)_nview != (Object)null)
				{
					return _nview.IsValid();
				}
				return false;
			}
		}

		internal static void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable += AddPieces;
		}

		private static void AddPieces()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= AddPieces;
			Tier[] tiers = Tiers;
			for (int i = 0; i < tiers.Length; i++)
			{
				AddPiece(tiers[i]);
			}
		}

		private static void AddPiece(Tier tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			PieceConfig val = new PieceConfig
			{
				Name = Loc.T(tier.NameRu, tier.NameEn),
				Description = Loc.T($"Радиус {RadiusOf(tier.Level):0} м: мобы не появляются, слабые убегают, постройки получают меньше урона.", $"Radius {RadiusOf(tier.Level):0} m: creatures do not spawn, weak ones flee, buildings take less damage."),
				PieceTable = PieceTables.Hammer,
				Category = PieceCategories.Misc,
				CraftingStation = tier.Station,
				Requirements = StoragePieces.ParseRecipe(RecipeOf(tier.Level))
			};
			CustomPiece val2 = new CustomPiece(tier.Prefab, "piece_table", val);
			if (!val2.IsValid())
			{
				Plugin.Log.LogError((object)("Could not create " + tier.Prefab + " from piece_table"));
				return;
			}
			GameObject piecePrefab = val2.PiecePrefab;
			PieceUtil.StripInteraction(piecePrefab);
			WardModel.Build(piecePrefab, tier);
			AddMarker(piecePrefab);
			piecePrefab.AddComponent<Ward>().Level = tier.Level;
			PieceUtil.RenderIcon(val2.Piece);
			PieceManager.Instance.AddPiece(val2);
		}

		private static void AddMarker(GameObject prefab)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("guard_stone");
			CircleProjector val = ((prefab2 == null) ? null : prefab2.GetComponent<PrivateArea>()?.m_areaMarker);
			if (!((Object)(object)val == (Object)null))
			{
				GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, prefab.transform, false);
				((Object)obj).name = "WardRadius";
				obj.transform.localPosition = Vector3.zero;
				obj.SetActive(false);
			}
		}

		internal static float RadiusOf(int level)
		{
			string[] array = (PackConfig.WardRadii.Value ?? "").Split(new char[1] { ',' });
			float[] array2 = new float[4] { 75f, 100f, 125f, 150f };
			int num = Mathf.Clamp(level, 1, 4) - 1;
			if (num >= array.Length || !float.TryParse(array[num].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !(result > 0f))
			{
				return array2[num];
			}
			return result;
		}

		private static string RecipeOf(int level)
		{
			return level switch
			{
				2 => PackConfig.WardRecipe2.Value, 
				3 => PackConfig.WardRecipe3.Value, 
				4 => PackConfig.WardRecipe4.Value, 
				_ => PackConfig.WardRecipe.Value, 
			};
		}

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null)
			{
				Loaded.Add(this);
				_marker = ((Component)this).GetComponentInChildren<CircleProjector>(true);
				if ((Object)(object)_marker != (Object)null)
				{
					_marker.m_radius = Radius;
				}
			}
		}

		private void OnDestroy()
		{
			Loaded.Remove(this);
		}

		internal static Ward Covering(Vector3 point)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!Active)
			{
				return null;
			}
			foreach (Ward item in Loaded)
			{
				if (!((Object)(object)item == (Object)null) && item.IsValid)
				{
					Vector3 val = ((Component)item).transform.position - point;
					val.y = 0f;
					float radius = item.Radius;
					if (((Vector3)(ref val)).sqrMagnitude <= radius * radius)
					{
						return item;
					}
				}
			}
			return null;
		}

		internal static bool Near(Vector3 point, float margin)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return Loaded.Any((Ward w) => (Object)(object)w != (Object)null && w.IsValid && Vector3.Distance(((Component)w).transform.position, point) <= w.Radius + margin);
		}

		private void Update()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < _nextMarkerCheck)
			{
				return;
			}
			_nextMarkerCheck = Time.time + 0.3f;
			if (!((Object)(object)_marker == (Object)null))
			{
				Player localPlayer = Player.m_localPlayer;
				float radius = Radius;
				bool flag = Active && (Object)(object)localPlayer != (Object)null && ((Character)localPlayer).InPlaceMode() && Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) < radius + 40f;
				if (flag && Mathf.Abs(_marker.m_radius - radius) > 0.01f)
				{
					_marker.m_radius = radius;
					_marker.CreateSegments();
				}
				if (((Component)_marker).gameObject.activeSelf != flag)
				{
					((Component)_marker).gameObject.SetActive(flag);
				}
			}
		}

		public string GetHoverName()
		{
			return Loc.T(TierInfo.NameRu, TierInfo.NameEn);
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverText()
		{
			if (!Active)
			{
				return GetHoverName() + "\n" + Loc.T("Выключен в настройках", "Disabled in the settings");
			}
			List<string> list = new List<string>
			{
				GetHoverName(),
				Loc.T($"Радиус {Radius:0} м: мобы здесь не появляются", $"Radius {Radius:0} m: creatures do not spawn here")
			};
			if (PackConfig.WardScareWeak.Value)
			{
				list.Add(Loc.T("Слабые мобы бегут прочь", "Weak creatures flee"));
			}
			if (PackConfig.WardBuildingProtection.Value > 0f)
			{
				list.Add(Loc.T($"Урон мобов по постройкам −{PackConfig.WardBuildingProtection.Value * 100f:0}%", $"Creature damage to buildings −{PackConfig.WardBuildingProtection.Value * 100f:0}%"));
			}
			return string.Join("\n", list);
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		private static bool IsBesieger(Character c)
		{
			if ((Object)(object)c == (Object)null || (Object)(object)c.m_nview == (Object)null || !c.m_nview.IsValid())
			{
				return false;
			}
			ZDO zDO = c.m_nview.GetZDO();
			if (!zDO.GetBool(ZDOVars.s_eventCreature, false) && string.IsNullOrEmpty(zDO.GetString("LC_Invader", "")))
			{
				return !string.IsNullOrEmpty(zDO.GetString("LC_Legend", ""));
			}
			return true;
		}

		[HarmonyPatch(typeof(SpawnSystem), "Spawn")]
		[HarmonyPrefix]
		private static bool NoBiomeSpawns(ref Vector3 spawnPoint, bool eventSpawner)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			Ward ward = Covering(spawnPoint);
			if ((Object)(object)ward == (Object)null)
			{
				return true;
			}
			if (!eventSpawner)
			{
				return false;
			}
			Vector3 position = ((Component)ward).transform.position;
			Vector3 val = spawnPoint - position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) * Vector3.forward;
			}
			Vector3 val2 = position + ((Vector3)(ref val)).normalized * (ward.Radius + 8f);
			float y = default(float);
			if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(val2, ref y))
			{
				val2.y = y;
			}
			spawnPoint = val2;
			return true;
		}

		[HarmonyPatch(typeof(CreatureSpawner), "UpdateSpawner")]
		[HarmonyPrefix]
		private static bool NoSpawnPoints(CreatureSpawner __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return (Object)(object)Covering(((Component)__instance).transform.position) == (Object)null;
		}

		[HarmonyPatch(typeof(SpawnArea), "UpdateSpawn")]
		[HarmonyPrefix]
		private static bool NoNests(SpawnArea __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return (Object)(object)Covering(((Component)__instance).transform.position) == (Object)null;
		}

		[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
		[HarmonyPrefix]
		private static bool ScareWeak(MonsterAI __instance, float dt, ref bool __result)
		{
			//IL_004b: 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)
			if (Loaded.Count == 0 || !PackConfig.WardScareWeak.Value)
			{
				return true;
			}
			Character character = ((BaseAI)__instance).m_character;
			if ((Object)(object)character == (Object)null || character.GetLevel() > 1 || character.IsBoss() || character.IsTamed())
			{
				return true;
			}
			Ward ward = Covering(((Component)character).transform.position);
			if ((Object)(object)ward == (Object)null || IsBesieger(character))
			{
				return true;
			}
			((BaseAI)__instance).Flee(dt, ((Component)ward).transform.position);
			__result = true;
			return false;
		}

		[HarmonyPatch(typeof(WearNTear), "RPC_Damage")]
		[HarmonyPrefix]
		private static void ShieldBuildings(WearNTear __instance, HitData hit)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			float value = PackConfig.WardBuildingProtection.Value;
			if (!(value <= 0f) && hit != null && Loaded.Count != 0 && !((Object)(object)Covering(((Component)__instance).transform.position) == (Object)null))
			{
				Character attacker = hit.GetAttacker();
				if (!((Object)(object)attacker == (Object)null) && !attacker.IsPlayer() && !IsBesieger(attacker))
				{
					hit.ApplyModifier(1f - Mathf.Clamp01(value));
				}
			}
		}
	}
	internal sealed class WardWatch : MonoBehaviour
	{
		private static WardWatch _instance;

		private readonly HashSet<int> _seen = new HashSet<int>();

		private float _nextCheck;

		private float _nextMessage;

		internal static void Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("LemyChadPack_WardWatch");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<WardWatch>();
			}
		}

		private void Update()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < _nextCheck)
			{
				return;
			}
			_nextCheck = Time.time + 2f;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || Ward.Loaded.Count == 0 || !PackConfig.WardWarnings.Value || !PackConfig.WardEnabled.Value || RandEventSystem.HaveActiveEvent() || !Ward.Near(((Component)localPlayer).transform.position, 40f))
			{
				return;
			}
			List<Character> list = new List<Character>();
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer() && !allCharacter.IsTamed() && !((Object)(object)((Component)allCharacter).GetComponent<MonsterAI>() == (Object)null) && !allCharacter.IsDead() && !((Object)(object)Ward.Covering(((Component)allCharacter).transform.position) == (Object)null) && (!((Object)(object)allCharacter.m_nview != (Object)null) || !allCharacter.m_nview.IsValid() || string.IsNullOrEmpty(allCharacter.m_nview.GetZDO().GetString("LC_Invader", ""))) && _seen.Add(((Object)allCharacter).GetInstanceID()))
				{
					list.Add(allCharacter);
				}
			}
			if (_seen.Count > 500)
			{
				_seen.Clear();
			}
			if (list.Count != 0 && !(Time.time < _nextMessage))
			{
				_nextMessage = Time.time + 8f;
				string hoverName = list[0].GetHoverName();
				string text = ((list.Count == 1) ? Loc.T("Оберег: враг на базе — " + hoverName, "Ward: an enemy in the base — " + hoverName) : Loc.T($"Оберег: врагов на базе — {list.Count} ({hoverName} и другие)", $"Ward: {list.Count} enemies in the base ({hoverName} and others)"));
				((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false);
			}
		}
	}
}
namespace LemyChadPack.UI
{
	internal static class Ui
	{
		internal static readonly Color Beige = GUIManager.Instance.ValheimBeige;

		internal static readonly Color Orange = GUIManager.Instance.ValheimOrange;

		internal static readonly Color Muted = new Color(0.72f, 0.7f, 0.65f);

		internal static readonly Color Good = new Color(0.55f, 0.85f, 0.45f);

		internal static readonly Color Bad = new Color(0.9f, 0.4f, 0.35f);

		internal static readonly Color BoxColor = new Color(0f, 0f, 0f, 0.35f);

		internal static RectTransform Rect(GameObject go)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			return (RectTransform)go.transform;
		}

		internal static void Stretch(RectTransform rt, float left, float top, float right, float bottom)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.pivot = new Vector2(0.5f, 0.5f);
			rt.offsetMin = new Vector2(left, bottom);
			rt.offsetMax = new Vector2(0f - right, 0f - top);
		}

		internal static GameObject Node(string name, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			return val;
		}

		internal static LayoutElement Layout(GameObject go, float width = -1f, float height = -1f, float flexWidth = -1f)
		{
			LayoutElement val = go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>();
			if (width >= 0f)
			{
				val.preferredWidth = width;
				val.minWidth = width;
			}
			if (height >= 0f)
			{
				val.preferredHeight = height;
				val.minHeight = height;
			}
			if (flexWidth >= 0f)
			{
				val.flexibleWidth = flexWidth;
			}
			return val;
		}

		internal static Text Label(Transform parent, string text, int size = 18, Color? color = null, TextAnchor align = (TextAnchor)3, bool bold = true)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Text val = Node("Text", parent).AddComponent<Text>();
			GUIManager.Instance.ApplyTextStyle(val, bold ? GUIManager.Instance.AveriaSerifBold : GUIManager.Instance.AveriaSerif, (Color)(((??)color) ?? Beige), size, true);
			val.supportRichText = true;
			val.alignment = align;
			val.horizontalOverflow = (HorizontalWrapMode)0;
			val.verticalOverflow = (VerticalWrapMode)1;
			val.text = text;
			return val;
		}

		internal static GameObject Row(Transform parent, float spacing = 8f, TextAnchor align = (TextAnchor)3)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Node("Row", parent);
			HorizontalLayoutGroup obj2 = obj.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = spacing;
			((LayoutGroup)obj2).childAlignment = align;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
			return obj;
		}

		internal static GameObject Column(Transform parent, float spacing = 4f, int padding = 0)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			GameObject obj = Node("Column", parent);
			VerticalLayoutGroup obj2 = obj.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = spacing;
			((LayoutGroup)obj2).padding = new RectOffset(padding, padding, padding, padding);
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
			return obj;
		}

		internal static GameObject Box(Transform parent, Color? tint = null)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Column(parent, 4f, 10);
			((Graphic)obj.AddComponent<Image>()).color = (Color)(((??)tint) ?? BoxColor);
			return obj;
		}

		internal static Button Button(Transform parent, string label, float width, UnityAction onClick, float height = 34f, bool interactable = true)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GUIManager.Instance.CreateButton(label, parent, Vector2.zero, Vector2.zero, Vector2.zero, width, height);
			Layout(obj, width, height, 0f);
			Button component = obj.GetComponent<Button>();
			if (onClick != null)
			{
				((UnityEvent)component.onClick).AddListener(onClick);
			}
			((Selectable)component).interactable = interactable;
			Text componentInChildren = obj.GetComponentInChildren<Text>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.supportRichText = true;
			}
			return component;
		}

		internal static InputField Input(Transform parent, string placeholder, float width, string value, Action<string> onChange, ContentType type = (ContentType)0, int maxLength = 0)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GUIManager.Instance.CreateInputField(parent, Vector2.zero, Vector2.zero, Vector2.zero, type, placeholder, 16, width, 32f);
			Layout(obj, width, 32f, (width <= 0f) ? 1f : 0f);
			InputField component = obj.GetComponent<InputField>();
			component.characterLimit = maxLength;
			component.text = value ?? "";
			if (onChange != null)
			{
				((UnityEvent<string>)(object)component.onValueChanged).AddListener((UnityAction<string>)delegate(string v)
				{
					onChange(v);
				});
			}
			return component;
		}

		internal static Image Icon(Transform parent, Sprite sprite, float size = 32f)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Node("Icon", parent);
			Image obj = val.AddComponent<Image>();
			obj.sprite = sprite;
			obj.preserveAspect = true;
			((Graphic)obj).color = (((Object)(object)sprite != (Object)null) ? Color.white : Color.clear);
			Layout(val, size, size, 0f);
			return obj;
		}

		internal static void Spacer(Transform parent, float height = -1f, bool flexible = false)
		{
			LayoutElement val = Layout(Node("Spacer", parent), -1f, height);
			if (flexible)
			{
				val.flexibleWidth = 1f;
			}
		}

		internal static void ProgressBar(Transform parent, float fraction, string text, float height = 22f)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Node("Progress", parent);
			Layout(val, -1f, height);
			((Graphic)val.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.55f);
			GameObject obj = Node("Fill", val.transform);
			RectTransform obj2 = Rect(obj);
			obj2.anchorMin = Vector2.zero;
			obj2.anchorMax = new Vector2(Mathf.Clamp01(fraction), 1f);
			obj2.offsetMin = new Vector2(2f, 2f);
			obj2.offsetMax = new Vector2(-2f, -2f);
			((Graphic)obj.AddComponent<Image>()).color = ((fraction >= 1f) ? Good : Orange);
			Stretch(Rect(((Component)Label(val.transform, text, 14, Color.white, (TextAnchor)4)).gameObject), 0f, 0f, 0f, 0f);
		}

		internal static void Clear(Transform t)
		{
			for (int num = t.childCount - 1; num >= 0; num--)
			{
				GameObject gameObject = ((Component)t.GetChild(num)).gameObject;
				gameObject.SetActive(false);
				Object.Destroy((Object)(object)gameObject);
			}
		}
	}
	internal abstract class UiWindow : MonoBehaviour
	{
		private const float TitleHeight = 50f;

		private const float TabsHeight = 44f;

		private const float FooterHeight = 56f;

		private GameObject _panel;

		private Text _title;

		private Transform _tabs;

		private RectTransform _header;

		private RectTransform _scrollRoot;

		private ScrollRect _scroll;

		private float _headerHeight;

		protected Transform Content { get; private set; }

		protected Transform Header => (Transform)(object)_header;

		internal bool Visible
		{
			get
			{
				if ((Object)(object)_panel != (Object)null)
				{
					return _panel.activeSelf;
				}
				return false;
			}
		}

		protected abstract string Title { get; }

		protected abstract Vector2 Size { get; }

		protected abstract void Fill();

		protected bool EnsurePanel()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Expected O, but got Unknown
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Expected O, but got Unknown
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Expected O, but got Unknown
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Expected O, but got Unknown
			if ((Object)(object)_panel != (Object)null)
			{
				return true;
			}
			GameObject customGUIFront = GUIManager.CustomGUIFront;
			if ((Object)(object)customGUIFront == (Object)null)
			{
				return false;
			}
			Vector2 size = Size;
			_panel = GUIManager.Instance.CreateWoodpanel(customGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, Mathf.Min(size.x, (float)Screen.width - 40f), Mathf.Min(size.y, (float)Screen.height - 60f), true);
			((Object)_panel).name = "LemyChadPack_" + ((object)this).GetType().Name;
			_title = Ui.Label(_panel.transform, Title, 26, Ui.Orange, (TextAnchor)4);
			RectTransform obj = Ui.Rect(((Component)_title).gameObject);
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(0.5f, 1f);
			obj.offsetMin = new Vector2(20f, -50f);
			obj.offsetMax = new Vector2(-20f, -10f);
			GameObject val = Ui.Row(_panel.transform, 6f, (TextAnchor)4);
			RectTransform obj2 = Ui.Rect(val);
			obj2.anchorMin = new Vector2(0f, 1f);
			obj2.anchorMax = new Vector2(1f, 1f);
			obj2.pivot = new Vector2(0.5f, 1f);
			obj2.offsetMin = new Vector2(24f, -94f);
			obj2.offsetMax = new Vector2(-24f, -50f);
			_tabs = val.transform;
			GameObject go = Ui.Column(_panel.transform, 6f);
			_header = Ui.Rect(go);
			_header.anchorMin = new Vector2(0f, 1f);
			_header.anchorMax = new Vector2(1f, 1f);
			_header.pivot = new Vector2(0.5f, 1f);
			GameObject val2 = GUIManager.Instance.CreateScrollView(_panel.transform, false, true, 8f, 5f, GUIManager.Instance.ValheimScrollbarHandleColorBlock, new Color(0f, 0f, 0f, 0.2