Decompiled source of HeimToolz v1.0.0

BepInEx/plugins/HeimToolz/HeimToolz.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HeimToolzUnified;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.0.0.0")]
internal class <Module>
{
	static <Module>()
	{
		HeimToolz_ModuleInit_Version_1_0_0_0_Culture_neutral_PublicKeyToken_null_HeimToolz_ModuleInit_ModuleInitializer();
	}

	private static void HeimToolz_ModuleInit_Version_1_0_0_0_Culture_neutral_PublicKeyToken_null_HeimToolz_ModuleInit_ModuleInitializer()
	{
		RuntimeBootstrap.ModuleInit();
	}
}
namespace HeimToolz
{
	[Flags]
	public enum KilnWoodTypes
	{
		None = 0,
		Wood = 1,
		CoreWood = 2,
		FineWood = 4,
		YggdrasilWood = 8
	}
	[BepInPlugin("HeimToolz.Valheim", "HeimToolz", "1.0.0")]
	public class HeimToolzPlugin : BaseUnityPlugin
	{
		private sealed class CircletLightOriginal
		{
			internal bool Enabled;

			internal float Range;

			internal float Intensity;

			internal float SpotAngle;

			internal Color Color;
		}

		public const string PluginGuid = "HeimToolz.Valheim";

		public const string PluginName = "HeimToolz";

		public const string PluginVersion = "1.0.0";

		internal static HeimToolzPlugin Instance;

		internal static ConfigEntry<bool> MasterEnabled;

		internal static ConfigEntry<bool> CircletEnabled;

		internal static ConfigEntry<float> CircletBrightness;

		internal static ConfigEntry<float> CircletRange;

		internal static ConfigEntry<int> CircletFocusSteps;

		internal static ConfigEntry<KeyboardShortcut> CircletNarrowKey;

		internal static ConfigEntry<KeyboardShortcut> CircletWidenKey;

		internal static ConfigEntry<KeyboardShortcut> CircletToggleKey;

		internal static ConfigEntry<bool> SkipIntroEnabled;

		internal static ConfigEntry<bool> WaterEquipmentEnabled;

		internal static ConfigEntry<bool> FermenterEnabled;

		internal static ConfigEntry<bool> FermenterShowProgress;

		internal static ConfigEntry<float> FermenterMinutes;

		internal static ConfigEntry<bool> FermenterNoCover;

		internal static ConfigEntry<bool> NoRainDamageEnabled;

		internal static ConfigEntry<bool> MapTeleportEnabled;

		internal static ConfigEntry<bool> BuildSpaceEnabled;

		internal static ConfigEntry<float> BuildRadiusMultiplier;

		internal static ConfigEntry<bool> FasterBoatsEnabled;

		internal static ConfigEntry<float> BoatWindMultiplier;

		internal static ConfigEntry<float> BoatRudderMultiplier;

		internal static ConfigEntry<bool> QuickCartEnabled;

		internal static ConfigEntry<KeyboardShortcut> QuickCartHotkey;

		internal static ConfigEntry<float> QuickCartDistance;

		internal static ConfigEntry<bool> QuickCartOutOfPlace;

		internal static ConfigEntry<bool> RegenerationEnabled;

		internal static ConfigEntry<float> StaminaCostMultiplier;

		internal static ConfigEntry<float> StaminaRegenMultiplier;

		internal static ConfigEntry<float> StaminaRegenDelayMultiplier;

		internal static ConfigEntry<float> EitrRegenRate;

		internal static ConfigEntry<float> HealthRegenMultiplier;

		internal static ConfigEntry<float> HealthRegenDelayMultiplier;

		internal static ConfigEntry<bool> AutoConsumeExtraSlotsFood;

		internal static ConfigEntry<bool> PathfinderEnabled;

		internal static ConfigEntry<bool> PathfinderDisableInDungeons;

		internal static ConfigEntry<float> LandExploreRadius;

		internal static ConfigEntry<float> SeaExploreRadius;

		internal static ConfigEntry<float> AltitudeExploreBonus;

		internal static ConfigEntry<bool> CarryWeightEnabled;

		internal static ConfigEntry<float> CarryWeightMultiplier;

		internal static ConfigEntry<bool> FastToolsEnabled;

		internal static ConfigEntry<float> PlaceDelay;

		internal static ConfigEntry<float> RemoveDelay;

		internal static ConfigEntry<float> BuildStaminaMultiplier;

		internal static ConfigEntry<bool> DigDeeperEnabled;

		internal static ConfigEntry<float> DigDepth;

		internal static ConfigEntry<float> RaiseHeight;

		internal static ConfigEntry<bool> BossPowersEnabled;

		internal static ConfigEntry<bool> BossPowersRequireDefeat;

		internal static ConfigEntry<bool> BossEikthyrEnabled;

		internal static ConfigEntry<float> EikthyrRunStaminaReduction;

		internal static ConfigEntry<float> EikthyrJumpStaminaReduction;

		internal static ConfigEntry<float> EikthyrSwimStaminaReduction;

		internal static ConfigEntry<bool> BossElderEnabled;

		internal static ConfigEntry<float> ElderChopDamage;

		internal static ConfigEntry<float> ElderPickaxeDamage;

		internal static ConfigEntry<float> ElderHealthRegen;

		internal static ConfigEntry<bool> BossBonemassEnabled;

		internal static ConfigEntry<float> BonemassBluntResistance;

		internal static ConfigEntry<float> BonemassSlashResistance;

		internal static ConfigEntry<float> BonemassPierceResistance;

		internal static ConfigEntry<float> BonemassBlockStaminaReduction;

		internal static ConfigEntry<float> BonemassStaminaReturn;

		internal static ConfigEntry<bool> BossModerEnabled;

		internal static ConfigEntry<bool> ModerTailwind;

		internal static ConfigEntry<float> ModerCarryWeight;

		internal static ConfigEntry<float> ModerMovementSpeed;

		internal static ConfigEntry<float> ModerFrostResistance;

		internal static ConfigEntry<bool> BossYagluthEnabled;

		internal static ConfigEntry<float> YagluthLightningResistance;

		internal static ConfigEntry<float> YagluthFarmingSkill;

		internal static ConfigEntry<float> YagluthDamage;

		internal static ConfigEntry<bool> BossQueenEnabled;

		internal static ConfigEntry<float> QueenEitrRegen;

		internal static ConfigEntry<float> QueenSneakStaminaReduction;

		internal static ConfigEntry<float> QueenPoisonResistance;

		internal static ConfigEntry<bool> BossFaderEnabled;

		internal static ConfigEntry<float> FaderAdrenalineGain;

		internal static ConfigEntry<float> FaderStaggerReduction;

		internal static ConfigEntry<float> FaderFireResistance;

		internal static ConfigEntry<bool> BeehiveEnabled;

		internal static ConfigEntry<float> HoneyProductionSeconds;

		internal static ConfigEntry<int> MaximumHoney;

		internal static ConfigEntry<bool> NearbyStorageEnabled;

		internal static ConfigEntry<bool> AutoSortEnabled;

		internal static ConfigEntry<KeyboardShortcut> AutoSortHotkey;

		internal static ConfigEntry<bool> CraftFromChestsEnabled;

		internal static ConfigEntry<bool> BuildFromChestsEnabled;

		internal static ConfigEntry<bool> UseItemsFromChestsEnabled;

		internal static ConfigEntry<bool> ShowHaveNeedCounts;

		internal static ConfigEntry<float> StorageRadius;

		internal static ConfigEntry<bool> RecyclingEnabled;

		internal static ConfigEntry<KeyboardShortcut> RecyclingHotkey;

		internal static ConfigEntry<bool> AutoCraftingEnabled;

		internal static ConfigEntry<bool> AutoCraftingAutoRefillLights;

		internal static ConfigEntry<float> AutoCraftingRange;

		internal static ConfigEntry<float> AutoCraftingInterval;

		internal static ConfigEntry<bool> AutoCraftingLeaveOneInput;

		internal static ConfigEntry<bool> AutoCraftingDepositOutputs;

		internal static ConfigEntry<bool> AutoCraftingWoodChests;

		internal static ConfigEntry<bool> AutoCraftingReinforcedChests;

		internal static ConfigEntry<bool> AutoCraftingBlackMetalChests;

		internal static ConfigEntry<bool> AutoCraftingPersonalChests;

		internal static ConfigEntry<bool> AutoCraftingCartContainers;

		internal static ConfigEntry<bool> AutoCraftingShipContainers;

		internal static ConfigEntry<bool> AutoCraftingOtherContainers;

		internal static ConfigEntry<int> AutoCraftingKilnCharcoalTarget;

		internal static ConfigEntry<KilnWoodTypes> AutoCraftingKilnWoodTypes;

		internal static ConfigEntry<int> AutoCraftingStationsPerTick;

		internal static ConfigEntry<float> AutoCraftingContainerCacheSeconds;

		internal static ConfigEntry<bool> AutoCraftingAutoPopCookingStations;

		internal static ConfigEntry<bool> AutoCraftingBetterBlastFurnaces;

		internal static ConfigEntry<float> AutoCraftingBlastFurnaceSeconds;

		internal static ConfigEntry<bool> HuntingGroundsEnabled;

		internal static ConfigEntry<float> HuntingSpawnRadius;

		internal static ConfigEntry<int> HuntingDeerCap;

		internal static ConfigEntry<int> HuntingBoarCap;

		internal static ConfigEntry<int> HuntingNeckCap;

		internal static ConfigEntry<int> HuntingOtherCap;

		internal static ConfigEntry<float> HuntingSpawnInterval;

		internal static ConfigEntry<float> HuntingPlayerRange;

		private readonly List<Harmony> _featureHarmonies = new List<Harmony>();

		private float _nextUtilityUpdate;

		private float _nextExtraSlotsFoodUpdate;

		private int _circletStep;

		private bool _circletLightOn = true;

		private Player _circletCachedPlayer;

		private Light[] _circletCachedLights;

		private float _nextCircletRescan;

		private float _nextBossPowerUpdate;

		private Player _bossHealthTrackedPlayer;

		private float _bossBaselineMaxHealth;

		private static readonly string[] ManagedBossEffects = new string[7] { "GP_Eikthyr", "GP_TheElder", "GP_Bonemass", "GP_Moder", "GP_Yagluth", "GP_Queen", "GP_Fader" };

		private readonly Dictionary<int, CircletLightOriginal> _circletOriginals = new Dictionary<int, CircletLightOriginal>();

		private void Awake()
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Expected O, but got Unknown
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b8d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b97: Expected O, but got Unknown
			//IL_0be5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c86: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c90: Expected O, but got Unknown
			//IL_0cc3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f32: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f3c: Expected O, but got Unknown
			Instance = this;
			MasterEnabled = Bind("00 - General", "Enabled", value: true, "Master switch for HeimToolz.");
			CircletEnabled = Bind("01 - Dverger Circlet", "Enabled", value: true, "Improve the Dverger Circlet light.");
			CircletBrightness = BindFloat("01 - Dverger Circlet", "Brightness", 2f, 0.25f, 5f, "Circlet light brightness.");
			CircletRange = BindFloat("01 - Dverger Circlet", "Range", 35f, 5f, 80f, "Maximum circlet beam range.");
			CircletFocusSteps = BindInt("01 - Dverger Circlet", "Focus Steps", 4, 2, 8, "Number of beam focus steps.");
			CircletNarrowKey = Bind<KeyboardShortcut>("01 - Dverger Circlet", "Narrow Beam Key", new KeyboardShortcut((KeyCode)91, (KeyCode[])(object)new KeyCode[0]), "Narrow the light beam.");
			CircletWidenKey = Bind<KeyboardShortcut>("01 - Dverger Circlet", "Widen Beam Key", new KeyboardShortcut((KeyCode)93, (KeyCode[])(object)new KeyCode[0]), "Widen the light beam.");
			CircletToggleKey = Bind<KeyboardShortcut>("01 - Dverger Circlet", "Toggle Light Key", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[0]), "Toggle circlet light on or off.");
			SkipIntroEnabled = Bind("02 - Skip Intro", "Enabled", value: true, "Skip the startup intro video and logos.");
			WaterEquipmentEnabled = Bind("03 - Equipment In Water", "Enabled", value: true, "Allow equipment and tools to stay usable while swimming.");
			FermenterEnabled = Bind("04 - Fermenter", "Enabled", value: true, "Enable fermenter quality-of-life tweaks.");
			FermenterShowProgress = Bind("04 - Fermenter", "Show Progress", value: true, "Show fermentation progress while hovering.");
			FermenterMinutes = BindFloat("04 - Fermenter", "Fermentation Minutes", 40f, 1f, 120f, "Minutes required to finish fermenting.");
			FermenterNoCover = Bind("04 - Fermenter", "Work Without Cover", value: false, "Allow fermenters to work without cover.");
			NoRainDamageEnabled = Bind("05 - Rain Damage", "No Rain Damage", value: true, "Prevent uncovered structures from taking rain wear.");
			MapTeleportEnabled = Bind("06 - Map Teleport", "Enabled", value: true, "Hold Shift and press T while the large map is open to teleport to the cursor.");
			BuildSpaceEnabled = Bind("07 - Build Space", "Enabled", value: true, "Increase crafting-station build radius.");
			BuildRadiusMultiplier = BindFloat("07 - Build Space", "Build Radius Multiplier", 2f, 1f, 10f, "Multiplier for crafting-station build radius.");
			FasterBoatsEnabled = Bind("08 - Faster Boats", "Enabled", value: true, "Increase boat movement speed.");
			BoatWindMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("08 - Faster Boats", "Wind Speed Multiplier", 2.5f, new ConfigDescription("Multiplier for wind-driven sail force. Type any positive value you want.", (AcceptableValueBase)null, new object[0]));
			BoatRudderMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("08 - Faster Boats", "Rudder Speed Multiplier", 2.25f, new ConfigDescription("Multiplier for paddle/rudder force. Type any positive value you want.", (AcceptableValueBase)null, new object[0]));
			QuickCartEnabled = Bind("09 - Quick Cart", "Enabled", value: true, "Quickly attach or detach the nearest cart.");
			QuickCartHotkey = Bind<KeyboardShortcut>("09 - Quick Cart", "Hotkey", new KeyboardShortcut((KeyCode)118, (KeyCode[])(object)new KeyCode[0]), "Attach/detach the nearest cart.");
			QuickCartDistance = BindFloat("09 - Quick Cart", "Attach Distance", 5f, 1f, 12f, "Maximum distance to find a cart.");
			QuickCartOutOfPlace = Bind("09 - Quick Cart", "Allow Out Of Place Attach", value: true, "Allow attaching even if the cart is slightly out of its normal attach position.");
			RegenerationEnabled = Bind("10 - Regeneration", "Enabled", value: true, "Enable stamina, health, and eitr regeneration tweaks.");
			StaminaCostMultiplier = BindFloat("10 - Regeneration", "Stamina Cost Multiplier", 1f, 0f, 2f, "0 = no stamina cost, 1 = vanilla, 2 = double.");
			StaminaRegenMultiplier = BindFloat("10 - Regeneration", "Stamina Regen Multiplier", 1f, 0.1f, 5f, "Multiplier for stamina regeneration.");
			StaminaRegenDelayMultiplier = BindFloat("10 - Regeneration", "Stamina Regen Delay Multiplier", 1f, 0f, 2f, "Multiplier for stamina regeneration delay.");
			EitrRegenRate = BindFloat("10 - Regeneration", "Eitr Regen Rate", 5f, 0f, 20f, "Base eitr regeneration rate.");
			HealthRegenMultiplier = BindFloat("10 - Regeneration", "Health Regen Multiplier", 1f, 0.1f, 5f, "Multiplier for player health regeneration.");
			HealthRegenDelayMultiplier = BindFloat("10 - Regeneration", "Health Regen Delay Multiplier", 1f, 0.1f, 2f, "Multiplier for food health-regeneration delay.");
			AutoConsumeExtraSlotsFood = Bind("10 - Regeneration", "Auto Consume ExtraSlots Food", value: true, "Automatically consume food placed in ExtraSlots food slots whenever an active food slot is available.");
			PathfinderEnabled = Bind("11 - Pathfinder", "Enabled", value: true, "Increase map exploration radius.");
			PathfinderDisableInDungeons = Bind("11 - Pathfinder", "Disable In Dungeons", value: true, "Automatically suspend Pathfinder map revealing inside instanced dungeons and resume it in the overworld.");
			LandExploreRadius = BindFloat("11 - Pathfinder", "Land Explore Radius", 200f, 50f, 2000f, "Map reveal radius while travelling on land.");
			SeaExploreRadius = BindFloat("11 - Pathfinder", "Sea Explore Radius", 300f, 50f, 2000f, "Map reveal radius while attached to a ship.");
			AltitudeExploreBonus = BindFloat("11 - Pathfinder", "Altitude Bonus", 0.5f, 0f, 2f, "Additional land reveal radius per 100m of altitude, as a multiplier.");
			CarryWeightEnabled = Bind("12 - Carry Weight", "Enabled", value: true, "Modify maximum carry weight.");
			CarryWeightMultiplier = BindFloat("12 - Carry Weight", "Carry Weight Multiplier", 2f, 1f, 10f, "Multiplier for maximum carry weight.");
			FastToolsEnabled = Bind("13 - Fast Tools", "Enabled", value: true, "Speed up hammer/hoe/cultivator placement and removal.");
			PlaceDelay = BindFloat("13 - Fast Tools", "Place Delay", 0.1f, 0f, 1f, "Delay in seconds between placements. Vanilla is about 0.4.");
			RemoveDelay = BindFloat("13 - Fast Tools", "Remove Delay", 0.1f, 0f, 1f, "Delay in seconds between removals. Vanilla is about 0.25.");
			BuildStaminaMultiplier = BindFloat("13 - Fast Tools", "Build Stamina Multiplier", 1f, 0f, 2f, "Multiplier for placement-tool stamina cost.");
			DigDeeperEnabled = Bind("14 - Dig Deeper", "Enabled", value: true, "Increase terrain digging and raising limits.");
			DigDepth = BindFloat("14 - Dig Deeper", "Maximum Dig Depth", 16f, 8f, 128f, "Maximum terrain depth. Vanilla is 8.");
			RaiseHeight = BindFloat("14 - Dig Deeper", "Maximum Raise Height", 16f, 8f, 128f, "Maximum terrain raising height. Vanilla is 8.");
			BossPowersEnabled = Bind("15 - BossPowers", "Enabled", value: true, "Apply selected unlocked Forsaken bonuses passively and permanently.");
			BossPowersRequireDefeat = Bind("15 - BossPowers", "Require Boss Defeated", value: true, "Only grant a power after its boss has been defeated in this world.");
			BossEikthyrEnabled = Bind("15 - BossPowers", "Eikthyr Enabled", value: true, "Enable Eikthyr's passive bonuses.");
			EikthyrRunStaminaReduction = BindFloat("15 - BossPowers", "Run Stamina Reduction %", 60f, 0f, 100f, "Percent less stamina used while running.");
			EikthyrJumpStaminaReduction = BindFloat("15 - BossPowers", "Jump Stamina Reduction %", 60f, 0f, 100f, "Percent less stamina used while jumping.");
			EikthyrSwimStaminaReduction = BindFloat("15 - BossPowers", "Swim Stamina Reduction %", 60f, 0f, 100f, "Percent less stamina used while swimming.");
			BossElderEnabled = Bind("15 - BossPowers", "Elder Enabled", value: true, "Enable The Elder's passive bonuses.");
			ElderChopDamage = BindFloat("15 - BossPowers", "Chop Damage %", 60f, 0f, 500f, "Bonus chopping damage percent.");
			ElderPickaxeDamage = BindFloat("15 - BossPowers", "Pickaxe Damage %", 60f, 0f, 500f, "Bonus pickaxe/mining damage percent.");
			ElderHealthRegen = BindFloat("15 - BossPowers", "Health Regen %", 30f, 0f, 500f, "Bonus health regeneration percent.");
			BossBonemassEnabled = Bind("15 - BossPowers", "Bonemass Enabled", value: true, "Enable Bonemass's passive bonuses.");
			BonemassBluntResistance = BindFloat("15 - BossPowers", "Blunt Resistance %", 25f, 0f, 100f, "Physical resistance setting.");
			BonemassSlashResistance = BindFloat("15 - BossPowers", "Slash Resistance %", 25f, 0f, 100f, "Physical resistance setting.");
			BonemassPierceResistance = BindFloat("15 - BossPowers", "Pierce Resistance %", 25f, 0f, 100f, "Physical resistance setting.");
			BonemassBlockStaminaReduction = BindFloat("15 - BossPowers", "Block Stamina Reduction %", 100f, 0f, 100f, "Percent less stamina used when blocking.");
			BonemassStaminaReturn = BindFloat("15 - BossPowers", "Stamina Returned Per Block", 5f, 0f, 100f, "Flat stamina returned when blocking.");
			BossModerEnabled = Bind("15 - BossPowers", "Moder Enabled", value: true, "Enable Moder's passive bonuses.");
			ModerTailwind = Bind("15 - BossPowers", "Always Tailwind", value: true, "Keep Moder's sailing tailwind effect enabled.");
			ModerCarryWeight = BindFloat("15 - BossPowers", "Carry Weight Bonus", 300f, 0f, 5000f, "Flat carry weight bonus.");
			ModerMovementSpeed = BindFloat("15 - BossPowers", "Movement Speed %", 10f, 0f, 500f, "Bonus movement speed percent.");
			ModerFrostResistance = BindFloat("15 - BossPowers", "Frost Resistance %", 50f, 0f, 100f, "Frost resistance setting.");
			BossYagluthEnabled = Bind("15 - BossPowers", "Yagluth Enabled", value: true, "Enable Yagluth's passive bonuses.");
			YagluthLightningResistance = BindFloat("15 - BossPowers", "Lightning Resistance %", 50f, 0f, 100f, "Lightning resistance setting.");
			YagluthFarmingSkill = BindFloat("15 - BossPowers", "Farming Skill Bonus", 25f, 0f, 500f, "Flat Farming skill bonus.");
			YagluthDamage = BindFloat("15 - BossPowers", "Damage %", 10f, 0f, 500f, "Bonus outgoing damage percent.");
			BossQueenEnabled = Bind("15 - BossPowers", "Queen Enabled", value: true, "Enable The Queen's passive bonuses.");
			QueenEitrRegen = BindFloat("15 - BossPowers", "Eitr Regen %", 100f, 0f, 1000f, "Bonus Eitr regeneration percent.");
			QueenSneakStaminaReduction = BindFloat("15 - BossPowers", "Sneak Stamina Reduction %", 100f, 0f, 100f, "Percent less stamina used while sneaking.");
			QueenPoisonResistance = BindFloat("15 - BossPowers", "Poison Resistance %", 50f, 0f, 100f, "Poison resistance setting.");
			BossFaderEnabled = Bind("15 - BossPowers", "Fader Enabled", value: true, "Enable Fader's passive bonuses.");
			FaderAdrenalineGain = BindFloat("15 - BossPowers", "Adrenaline Gain %", 100f, 0f, 1000f, "Bonus Adrenaline gain percent.");
			FaderStaggerReduction = BindFloat("15 - BossPowers", "Stagger Meter Reduction %", 50f, 0f, 100f, "Percent reduction to the stagger meter modifier.");
			FaderFireResistance = BindFloat("15 - BossPowers", "Fire Resistance %", 50f, 0f, 100f, "Fire resistance setting.");
			BeehiveEnabled = Bind("16 - Beehives", "Enabled", value: true, "Enable configurable honey production.");
			HoneyProductionSeconds = BindFloat("16 - Beehives", "Honey Production Seconds", 600f, 1f, 1200f, "Seconds required to produce one honey. Vanilla is 1200. Minimum is 1 second.");
			MaximumHoney = ((BaseUnityPlugin)this).Config.Bind<int>("16 - Beehives", "Maximum Honey", 4, new ConfigDescription("Maximum honey stored in each hive. Type the number you want.", (AcceptableValueBase)null, new object[0]));
			NearbyStorageEnabled = Bind("17 - Nearby Storage", "Enabled", value: true, "Enable nearby storage quality-of-life features.");
			AutoSortEnabled = Bind("17 - Nearby Storage", "Auto Sort", value: true, "Press the hotkey to move normal backpack items into nearby chests that already contain the same item.");
			AutoSortHotkey = Bind<KeyboardShortcut>("17 - Nearby Storage", "Auto Sort Hotkey", new KeyboardShortcut((KeyCode)46, (KeyCode[])(object)new KeyCode[0]), "Hotkey for matching-chest auto sort. Default is period (.).");
			CraftFromChestsEnabled = Bind("17 - Nearby Storage", "Craft From Chests", value: true, "Crafting can count and consume materials from nearby containers.");
			BuildFromChestsEnabled = Bind("17 - Nearby Storage", "Build From Chests", value: true, "Building pieces, ships, and other placeables can count and consume materials from nearby containers.");
			UseItemsFromChestsEnabled = Bind("17 - Nearby Storage", "Use Items From Chests", value: true, "Kilns, smelters, and fireplaces can use required items from nearby containers when you interact with them.");
			ShowHaveNeedCounts = Bind("17 - Nearby Storage", "Show Have Need Counts", value: true, "Show available / required material counts using inventory plus nearby containers.");
			StorageRadius = ((BaseUnityPlugin)this).Config.Bind<float>("17 - Nearby Storage", "Storage Radius", 20f, new ConfigDescription("Radius in meters used by nearby storage features. Type any positive value you want.", (AcceptableValueBase)null, new object[0]));
			RecyclingEnabled = Bind("18 - Recycling", "Enabled", value: true, "Recycle the inventory item under the mouse cursor back into its original recipe materials. Items without a recipe are deleted.");
			RecyclingHotkey = Bind<KeyboardShortcut>("18 - Recycling", "Recycle Hotkey", new KeyboardShortcut((KeyCode)127, (KeyCode[])(object)new KeyCode[0]), "Recycle or delete the hovered inventory item. Default: Delete.");
			AutoCraftingEnabled = Bind("19 - AutoCrafting", "Enabled", value: true, "Automatically feed loaded production stations from nearby allowed containers and route finished outputs into matching containers.");
			AutoCraftingAutoRefillLights = Bind("19 - AutoCrafting", "Auto Refill Lights", value: true, "Automatically refuel Fireplace-based lights and fires from nearby allowed storage.");
			AutoCraftingRange = BindFloat("19 - AutoCrafting", "Container Range", 20f, 1f, 50f, "Maximum distance in meters from a station to pull from or deposit into containers.");
			AutoCraftingInterval = BindFloat("19 - AutoCrafting", "Refill Interval Seconds", 1f, 0.25f, 10f, "How often loaded production stations check nearby containers for inputs.");
			AutoCraftingLeaveOneInput = Bind("19 - AutoCrafting", "Leave One Input In Chest", value: true, "Keep at least one of each station input in its source chest for sorting/reference.");
			AutoCraftingDepositOutputs = Bind("19 - AutoCrafting", "Deposit Outputs Into Matching Chests", value: true, "Move station outputs into a nearby allowed chest that already contains that item. If none exists or it is full, the output drops normally.");
			AutoCraftingWoodChests = Bind("19 - AutoCrafting", "Wood Chests", value: true, "Allow basic wooden chests.");
			AutoCraftingReinforcedChests = Bind("19 - AutoCrafting", "Reinforced Chests", value: true, "Allow reinforced/iron chests.");
			AutoCraftingBlackMetalChests = Bind("19 - AutoCrafting", "Black Metal Chests", value: true, "Allow black metal chests.");
			AutoCraftingPersonalChests = Bind("19 - AutoCrafting", "Personal Chests", value: false, "Allow personal/private chests.");
			AutoCraftingCartContainers = Bind("19 - AutoCrafting", "Cart Storage", value: false, "Allow cart storage.");
			AutoCraftingShipContainers = Bind("19 - AutoCrafting", "Ship Storage", value: false, "Allow ship storage.");
			AutoCraftingOtherContainers = Bind("19 - AutoCrafting", "Other Or Modded Containers", value: false, "Allow containers that do not match a known vanilla chest/storage category.");
			AutoCraftingKilnCharcoalTarget = BindInt("19 - AutoCrafting", "Kiln Charcoal Target", 50, 0, 5000, "Stop automatically feeding wood into charcoal kilns when nearby allowed containers already contain at least this much charcoal. 0 = unlimited.");
			AutoCraftingKilnWoodTypes = ((BaseUnityPlugin)this).Config.Bind<KilnWoodTypes>("19 - AutoCrafting", "Kiln Wood Types", KilnWoodTypes.Wood, "Select which wood types AutoCrafting may feed into charcoal kilns. Default is regular Wood only. This is a multi-select flags box in Configuration Manager.");
			AutoCraftingStationsPerTick = BindInt("19 - AutoCrafting", "Stations Processed Per Tick", 2, 1, 20, "Performance control. Lower values spread AutoCrafting work across frames and reduce spikes.");
			AutoCraftingContainerCacheSeconds = BindFloat("19 - AutoCrafting", "Container Cache Seconds", 3f, 0.5f, 30f, "How long each station reuses its nearby-container list before refreshing it.");
			AutoCraftingAutoPopCookingStations = Bind("19 - AutoCrafting", "Auto Pop Cooking Stations", value: true, "Automatically eject cooked food as soon as it reaches the finished state so it cannot burn.");
			AutoCraftingBetterBlastFurnaces = Bind("19 - AutoCrafting", "Better Blast Furnaces", value: false, "Allow blast furnaces to smelt all vanilla ore/scrap inputs that normal metal smelters can process.");
			AutoCraftingBlastFurnaceSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("19 - AutoCrafting", "Blast Furnace Smelting Seconds", 10f, new ConfigDescription("Seconds per finished item while Better Blast Furnaces is enabled. Type any positive value you want.", (AcceptableValueBase)null, new object[0]));
			HuntingGroundsEnabled = Bind("20 - Hunting Grounds", "Enabled", value: true, "Add placeable hunting-ground spawners for vanilla mobs, labeled and grouped by biome in the hammer Misc category.");
			HuntingSpawnRadius = BindFloat("20 - Hunting Grounds", "Spawn Radius", 30f, 5f, 50f, "Animals spawn randomly between 5 meters and this radius from their spawner.");
			HuntingDeerCap = BindInt("20 - Hunting Grounds", "Deer Population Cap", 10, 1, 50, "Maximum deer maintained inside a Deer Spawner's radius.");
			HuntingBoarCap = BindInt("20 - Hunting Grounds", "Boar Population Cap", 10, 1, 50, "Maximum boars maintained inside a Boar Spawner's radius.");
			HuntingNeckCap = BindInt("20 - Hunting Grounds", "Neck Population Cap", 10, 1, 50, "Maximum necks maintained inside a Neck Spawner's radius.");
			HuntingOtherCap = BindInt("20 - Hunting Grounds", "Other Mob Population Cap", 6, 1, 50, "Population cap used by the biome mob spawner variants.");
			HuntingSpawnInterval = BindFloat("20 - Hunting Grounds", "Spawn Interval Seconds", 15f, 5f, 120f, "When below the local population cap, spawn one animal this often.");
			HuntingPlayerRange = BindFloat("20 - Hunting Grounds", "Player Activation Range", 100f, 20f, 200f, "Spawner only operates while the local player is within this distance.");
			((BaseUnityPlugin)this).Config.SettingChanged += OnAnySettingChanged;
			RefreshFeaturePatches();
			if (AutoCraftingEnabled.Value)
			{
				AutoCrafting.RefreshExistingWorldObjects();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"HeimToolz v1.0.0 loaded.");
		}

		private ConfigEntry<T> Bind<T>(string section, string name, T value, string description)
		{
			return ((BaseUnityPlugin)this).Config.Bind<T>(section, name, value, description);
		}

		private ConfigEntry<float> BindFloat(string section, string name, float value, float min, float max, string description)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<float>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), new object[0]));
		}

		private ConfigEntry<int> BindInt(string section, string name, int value, int min, int max, string description)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<int>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), new object[0]));
		}

		private void OnAnySettingChanged(object sender, SettingChangedEventArgs args)
		{
			try
			{
				if (args == null || args.ChangedSetting == null)
				{
					return;
				}
				string text = args.ChangedSetting.Definition.Section ?? "";
				string text2 = args.ChangedSetting.Definition.Key ?? "";
				if (text2 == "Enabled")
				{
					RefreshFeaturePatches();
				}
				if (text.StartsWith("15", StringComparison.Ordinal))
				{
					_nextBossPowerUpdate = 0f;
				}
				if (text == "19 - AutoCrafting")
				{
					AutoCrafting.InvalidateConfigCaches();
					if (AutoCraftingEnabled.Value)
					{
						AutoCrafting.RefreshExistingWorldObjects();
					}
				}
				if (text == "20 - Hunting Grounds" && HuntingGroundsEnabled.Value)
				{
					HuntingGrounds.EnsureRegistered();
				}
			}
			catch
			{
			}
		}

		private void RefreshFeaturePatches()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			for (int i = 0; i < _featureHarmonies.Count; i++)
			{
				try
				{
					_featureHarmonies[i].UnpatchSelf();
				}
				catch
				{
				}
			}
			_featureHarmonies.Clear();
			if (!MasterEnabled.Value)
			{
				return;
			}
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			foreach (Type type in types)
			{
				object[] customAttributes = type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true);
				if (customAttributes != null && customAttributes.Length != 0 && ShouldPatchFeature(type))
				{
					try
					{
						Harmony val = new Harmony("HeimToolz.Valheim." + type.Name);
						val.PatchAll(type);
						_featureHarmonies.Add(val);
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Patch failed for " + type.Name + ": " + ex.Message));
					}
				}
			}
		}

		private bool ShouldPatchFeature(Type t)
		{
			switch (t.Name)
			{
			case "SkipIntroCoroutinePatch":
				return SkipIntroEnabled.Value;
			case "EquipmentInWaterUpdatePatch":
			case "EquipmentInWaterEquipPatch":
				return WaterEquipmentEnabled.Value;
			case "FermenterAwakePatch":
			case "FermenterHoverPatch":
			case "FermenterCoverPatch":
				return FermenterEnabled.Value;
			case "NoRainDamagePatch":
				return NoRainDamageEnabled.Value;
			case "BuildSpacePatch":
				return BuildSpaceEnabled.Value;
			case "FasterBoatWindPatch":
			case "FasterBoatRudderPatch":
				return FasterBoatsEnabled.Value;
			case "QuickCartAttachPatch":
				return QuickCartEnabled.Value;
			case "StaminaUsePatch":
			case "RegenStatsPatch":
			case "HealthRegenDelayPatch":
			case "HealthRegenAmountPatch":
				return RegenerationEnabled.Value;
			case "CarryWeightPatch":
				return CarryWeightEnabled.Value;
			case "PathfinderPatch":
				return PathfinderEnabled.Value;
			case "BuildStaminaPatch":
			case "FastToolsPlacementPatch":
				return FastToolsEnabled.Value;
			case "DigDeeperHeightmapPatch":
			case "DigDeeperApplyToHeightmapPatch":
			case "DigDeeperTerrainLevelPatch":
			case "DigDeeperTerrainRaisePatch":
				return DigDeeperEnabled.Value;
			case "BeehiveUpdatePatch":
			case "BeehiveHoverPatch":
				return BeehiveEnabled.Value;
			case "DisableGuardianPowerActivationPatch":
			case "ElderResourceDamagePatch":
			case "ModerMovementSpeedPatch":
			case "BossPowerSEModifierPatch":
			case "BossDamageRuntimePatch":
			case "BossBlockStaminaReturnPatch":
			case "BossFarmingSkillPatch":
			case "BossModerTailwindPatch":
			case "BossModerCarryWeightPatch":
				return BossPowersEnabled.Value;
			case "NearbyStorageContainerRegistryPatch":
				if (!NearbyStorageEnabled.Value)
				{
					return AutoCraftingEnabled.Value;
				}
				return true;
			case "NearbyStorageBuildCheckContextPatch":
				if (NearbyStorageEnabled.Value)
				{
					return BuildFromChestsEnabled.Value;
				}
				return false;
			case "NearbyStorageCraftCheckContextPatch":
				if (NearbyStorageEnabled.Value)
				{
					return CraftFromChestsEnabled.Value;
				}
				return false;
			case "NearbyStorageBuildActionContextPatch":
				if (NearbyStorageEnabled.Value)
				{
					return BuildFromChestsEnabled.Value;
				}
				return false;
			case "NearbyStorageCraftActionContextPatch":
				if (NearbyStorageEnabled.Value)
				{
					return CraftFromChestsEnabled.Value;
				}
				return false;
			case "NearbyStorageCountItemsPatch":
			case "NearbyStorageHaveItemPatch":
			case "NearbyStorageConsumeResourcesPatch":
				if (NearbyStorageEnabled.Value)
				{
					if (!CraftFromChestsEnabled.Value)
					{
						return BuildFromChestsEnabled.Value;
					}
					return true;
				}
				return false;
			case "NearbyStorageRequirementUiPatch":
				if (NearbyStorageEnabled.Value && ShowHaveNeedCounts.Value)
				{
					if (!CraftFromChestsEnabled.Value)
					{
						return BuildFromChestsEnabled.Value;
					}
					return true;
				}
				return false;
			case "NearbyStorageSwitchInteractPatch":
			case "NearbyStorageFireplaceInteractPatch":
				if (NearbyStorageEnabled.Value)
				{
					return UseItemsFromChestsEnabled.Value;
				}
				return false;
			case "AutoCraftingEitrRefineryRegistryPatch":
				if (AutoCraftingEnabled.Value)
				{
					return AutoCrafting.GetEitrRefineryType() != null;
				}
				return false;
			case "AutoCraftingFireplaceRegistryPatch":
			case "AutoCraftingSmelterRegistryPatch":
			case "AutoCraftingCookingStationRegistryPatch":
			case "AutoCraftingFermenterRegistryPatch":
			case "AutoCraftingOutputRoutingPatch":
			case "AutoCraftingMessageSuppressPatch":
			case "AutoCraftingCookingAutoPopPatch":
				return AutoCraftingEnabled.Value;
			case "HuntingGroundsZNetScenePatch":
			case "HuntingGroundPlacementPatch":
			case "HuntingGroundMarkerRestorePatch":
			case "HuntingGroundContainerBlockInteractPatch":
				return HuntingGroundsEnabled.Value;
			case "NoRainDamageApplyDamagePatch":
				return NoRainDamageEnabled.Value;
			default:
				return false;
			}
		}

		internal static bool On(ConfigEntry<bool> feature)
		{
			if ((Object)(object)Instance != (Object)null && MasterEnabled.Value)
			{
				return feature.Value;
			}
			return false;
		}

		private void OnDestroy()
		{
			try
			{
				((BaseUnityPlugin)this).Config.SettingChanged -= OnAnySettingChanged;
			}
			catch
			{
			}
			try
			{
				for (int i = 0; i < _featureHarmonies.Count; i++)
				{
					_featureHarmonies[i].UnpatchSelf();
				}
			}
			catch
			{
			}
			_featureHarmonies.Clear();
			try
			{
				RemoveManagedBossPowers();
			}
			catch
			{
			}
			Instance = null;
		}

		private void Update()
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: 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_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			if (!MasterEnabled.Value)
			{
				RestoreCircletLights();
				return;
			}
			if (!QuickCartEnabled.Value && !MapTeleportEnabled.Value && !CircletEnabled.Value && !BossPowersEnabled.Value && (!NearbyStorageEnabled.Value || !AutoSortEnabled.Value) && !RecyclingEnabled.Value && !AutoCraftingEnabled.Value && !HuntingGroundsEnabled.Value && (!RegenerationEnabled.Value || !AutoConsumeExtraSlotsFood.Value))
			{
				return;
			}
			if (HuntingGroundsEnabled.Value)
			{
				HuntingGrounds.EnsureRegistered();
				HuntingGrounds.Tick();
			}
			if (RegenerationEnabled.Value && AutoConsumeExtraSlotsFood.Value && Time.unscaledTime >= _nextExtraSlotsFoodUpdate)
			{
				_nextExtraSlotsFoodUpdate = Time.unscaledTime + 0.75f;
				RegenerationFoodSlots.TryAutoConsume(Player.m_localPlayer);
			}
			if (AutoCraftingEnabled.Value)
			{
				AutoCrafting.Tick();
			}
			if (RecyclingEnabled.Value)
			{
				KeyboardShortcut value = RecyclingHotkey.Value;
				if (!((KeyboardShortcut)(ref value)).IsDown())
				{
					KeyboardShortcut value2 = RecyclingHotkey.Value;
					if (!Input.GetKeyDown(((KeyboardShortcut)(ref value2)).MainKey))
					{
						goto IL_014a;
					}
				}
				Recycling.TryRecycleHoveredItem(Player.m_localPlayer);
			}
			goto IL_014a;
			IL_019a:
			if (QuickCartEnabled.Value)
			{
				KeyboardShortcut value3 = QuickCartHotkey.Value;
				if (!((KeyboardShortcut)(ref value3)).IsDown())
				{
					KeyboardShortcut value4 = QuickCartHotkey.Value;
					if (!Input.GetKeyDown(((KeyboardShortcut)(ref value4)).MainKey))
					{
						goto IL_01db;
					}
				}
				TryQuickCart();
			}
			goto IL_01db;
			IL_01db:
			if (MapTeleportEnabled.Value && Minimap.IsOpen() && (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) && Input.GetKeyDown((KeyCode)116))
			{
				TryMapTeleport();
			}
			if (CircletEnabled.Value)
			{
				KeyboardShortcut value5 = CircletToggleKey.Value;
				if (((KeyboardShortcut)(ref value5)).IsDown())
				{
					_circletLightOn = !_circletLightOn;
				}
				KeyboardShortcut value6 = CircletNarrowKey.Value;
				if (((KeyboardShortcut)(ref value6)).IsDown())
				{
					_circletStep = Mathf.Max(0, _circletStep - 1);
				}
				KeyboardShortcut value7 = CircletWidenKey.Value;
				if (((KeyboardShortcut)(ref value7)).IsDown())
				{
					_circletStep = Mathf.Min(CircletFocusSteps.Value - 1, _circletStep + 1);
				}
			}
			if (CircletEnabled.Value && Time.time >= _nextUtilityUpdate)
			{
				_nextUtilityUpdate = Time.time + 0.5f;
				ApplyCircletLights();
			}
			else if (!CircletEnabled.Value && _circletCachedLights != null)
			{
				RestoreCircletLights();
				_circletCachedLights = null;
			}
			if (BossPowersEnabled.Value && Time.time >= _nextBossPowerUpdate)
			{
				_nextBossPowerUpdate = Time.time + 5f;
				MaintainBossPowers();
			}
			return;
			IL_014a:
			if (NearbyStorageEnabled.Value && AutoSortEnabled.Value)
			{
				KeyboardShortcut value8 = AutoSortHotkey.Value;
				if (!((KeyboardShortcut)(ref value8)).IsDown())
				{
					KeyboardShortcut value9 = AutoSortHotkey.Value;
					if (!Input.GetKeyDown(((KeyboardShortcut)(ref value9)).MainKey))
					{
						goto IL_019a;
					}
				}
				NearbyStorage.AutoSort(Player.m_localPlayer);
			}
			goto IL_019a;
		}

		private void MaintainBossPowers()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			TrackBossHealthBaseline(localPlayer);
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_guardianPowerCooldown");
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(localPlayer, 0f);
				}
			}
			catch
			{
			}
			RestoreBossHealthIfCorrupted(localPlayer);
		}

		private void TrackBossHealthBaseline(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			if ((Object)(object)_bossHealthTrackedPlayer != (Object)(object)player)
			{
				_bossHealthTrackedPlayer = player;
				_bossBaselineMaxHealth = 0f;
			}
			try
			{
				float maxHealth = ((Character)player).GetMaxHealth();
				if (maxHealth > _bossBaselineMaxHealth)
				{
					_bossBaselineMaxHealth = maxHealth;
				}
			}
			catch
			{
			}
		}

		private void RestoreBossHealthIfCorrupted(Player player)
		{
			if ((Object)(object)player == (Object)null || _bossBaselineMaxHealth <= 0f)
			{
				return;
			}
			float maxHealth;
			try
			{
				maxHealth = ((Character)player).GetMaxHealth();
			}
			catch
			{
				return;
			}
			if (maxHealth >= _bossBaselineMaxHealth * 0.5f)
			{
				return;
			}
			TrySetMaxHealth((Character)(object)player, _bossBaselineMaxHealth);
			try
			{
				float health = ((Character)player).GetHealth();
				if (health > _bossBaselineMaxHealth)
				{
					((Character)player).SetHealth(_bossBaselineMaxHealth);
				}
			}
			catch
			{
			}
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Boss Power safety restored max health from " + maxHealth.ToString("0.##") + " to " + _bossBaselineMaxHealth.ToString("0.##") + "."));
		}

		private static void TrySetMaxHealth(Character character, float value)
		{
			if ((Object)(object)character == (Object)null || value <= 0f)
			{
				return;
			}
			try
			{
				MethodInfo[] methods = ((object)character).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "SetMaxHealth")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length < 1 || parameters[0].ParameterType != typeof(float))
					{
						continue;
					}
					object[] array = new object[parameters.Length];
					array[0] = value;
					bool flag = true;
					for (int j = 1; j < parameters.Length; j++)
					{
						Type parameterType = parameters[j].ParameterType;
						if (parameterType == typeof(bool))
						{
							array[j] = false;
							continue;
						}
						if (parameterType == typeof(float))
						{
							array[j] = 0f;
							continue;
						}
						if (parameterType == typeof(int))
						{
							array[j] = 0;
							continue;
						}
						if (!parameterType.IsValueType)
						{
							array[j] = null;
							continue;
						}
						flag = false;
						break;
					}
					if (flag)
					{
						methodInfo.Invoke(character, array);
						break;
					}
				}
			}
			catch
			{
			}
		}

		private bool HasGlobalKey(string key)
		{
			if (!BossPowersRequireDefeat.Value)
			{
				return true;
			}
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return false;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(ZoneSystem), "GetGlobalKey", new Type[1] { typeof(string) }, (Type[])null);
				if (methodInfo != null)
				{
					return Convert.ToBoolean(methodInfo.Invoke(ZoneSystem.instance, new object[1] { key }));
				}
			}
			catch
			{
			}
			return false;
		}

		internal static bool ModerMovementBonusActive(Player player)
		{
			if ((Object)(object)Instance == (Object)null || (Object)(object)player == (Object)null || !MasterEnabled.Value || !BossPowersEnabled.Value || !BossModerEnabled.Value)
			{
				return false;
			}
			try
			{
				if (!Instance.HasGlobalKey("defeated_dragon"))
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
			return ModerMovementSpeed.Value > 0f;
		}

		private void EnsureBossPower(Player player, string effectName, string globalKey, bool enabled)
		{
			if (!enabled || !HasGlobalKey(globalKey))
			{
				RemoveBossPower(player, effectName);
				return;
			}
			int stableHash = GetStableHash(effectName);
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(SEMan), "HaveStatusEffect", new Type[1] { typeof(int) }, (Type[])null);
				if (methodInfo != null && Convert.ToBoolean(methodInfo.Invoke(((Character)player).GetSEMan(), new object[1] { stableHash })))
				{
					return;
				}
			}
			catch
			{
			}
			StatusEffect val = FindStatusEffect(effectName);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Dictionary<FieldInfo, object> dictionary = new Dictionary<FieldInfo, object>();
			try
			{
				ApplyBossPowerSettings(val, effectName, dictionary);
				FieldInfo fieldInfo = AccessTools.Field(((object)val).GetType(), "m_ttl");
				if (fieldInfo != null)
				{
					if (!dictionary.ContainsKey(fieldInfo))
					{
						dictionary[fieldInfo] = fieldInfo.GetValue(val);
					}
					fieldInfo.SetValue(val, 0f);
				}
				FieldInfo fieldInfo2 = AccessTools.Field(((object)val).GetType(), "m_cooldown");
				if (fieldInfo2 != null)
				{
					if (!dictionary.ContainsKey(fieldInfo2))
					{
						dictionary[fieldInfo2] = fieldInfo2.GetValue(val);
					}
					fieldInfo2.SetValue(val, 0f);
				}
				((Character)player).GetSEMan().AddStatusEffect(stableHash, false, 0, 0f, (short)(-1));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Boss power " + effectName + " failed: " + ex.Message));
			}
			finally
			{
				foreach (KeyValuePair<FieldInfo, object> item in dictionary)
				{
					try
					{
						item.Key.SetValue(val, item.Value);
					}
					catch
					{
					}
				}
			}
		}

		private void ApplyBossPowerSettings(StatusEffect effect, string effectName, Dictionary<FieldInfo, object> originals)
		{
			if ((Object)(object)effect == (Object)null)
			{
				return;
			}
			switch (effectName)
			{
			case "GP_Eikthyr":
				SetBossFloat(effect, originals, new string[2] { "m_runStaminaUseModifier", "m_runStaminaDrainModifier" }, (0f - EikthyrRunStaminaReduction.Value) / 100f);
				SetBossFloat(effect, originals, new string[1] { "m_jumpStaminaUseModifier" }, (0f - EikthyrJumpStaminaReduction.Value) / 100f);
				SetBossFloat(effect, originals, new string[1] { "m_swimStaminaUseModifier" }, (0f - EikthyrSwimStaminaReduction.Value) / 100f);
				break;
			case "GP_TheElder":
				SetBossFloat(effect, originals, new string[1] { "m_healthRegenMultiplier" }, 1f + ElderHealthRegen.Value / 100f);
				break;
			case "GP_Bonemass":
				SetBossFloat(effect, originals, new string[1] { "m_blockStaminaUseModifier" }, (0f - BonemassBlockStaminaReduction.Value) / 100f);
				SetKeywordFloat(effect, originals, new string[2] { "block", "stamina" }, new string[2] { "use", "modifier" }, BonemassStaminaReturn.Value);
				SetResistance(effect, "blunt", BonemassBluntResistance.Value);
				SetResistance(effect, "slash", BonemassSlashResistance.Value);
				SetResistance(effect, "pierce", BonemassPierceResistance.Value);
				break;
			case "GP_Moder":
				SetBossFloat(effect, originals, new string[1] { "m_addMaxCarryWeight" }, ModerCarryWeight.Value);
				SetBossFloat(effect, originals, new string[1] { "m_speedModifier" }, ModerMovementSpeed.Value / 100f);
				SetResistance(effect, "frost", ModerFrostResistance.Value);
				if (!ModerTailwind.Value)
				{
					ClearSailingPowerAttribute(effect, originals);
				}
				break;
			case "GP_Yagluth":
				SetResistance(effect, "lightning", YagluthLightningResistance.Value);
				SetKeywordFloat(effect, originals, new string[1] { "skill" }, null, YagluthFarmingSkill.Value);
				SetBossFloat(effect, originals, new string[1] { "m_damageModifier" }, 1f + YagluthDamage.Value / 100f);
				break;
			case "GP_Queen":
				SetBossFloat(effect, originals, new string[1] { "m_eitrRegenMultiplier" }, 1f + QueenEitrRegen.Value / 100f);
				SetBossFloat(effect, originals, new string[1] { "m_sneakStaminaUseModifier" }, (0f - QueenSneakStaminaReduction.Value) / 100f);
				SetResistance(effect, "poison", QueenPoisonResistance.Value);
				break;
			case "GP_Fader":
				SetKeywordFloat(effect, originals, new string[1] { "adrenaline" }, null, FaderAdrenalineGain.Value / 100f);
				SetBossFloat(effect, originals, new string[1] { "m_staggerModifier" }, (0f - FaderStaggerReduction.Value) / 100f);
				SetResistance(effect, "fire", FaderFireResistance.Value);
				break;
			}
		}

		private static FieldInfo FindFieldInHierarchy(Type type, string name)
		{
			while (type != null)
			{
				FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
				type = type.BaseType;
			}
			return null;
		}

		private static void SetBossFloat(StatusEffect effect, Dictionary<FieldInfo, object> originals, string[] fieldNames, float value)
		{
			for (int i = 0; i < fieldNames.Length; i++)
			{
				FieldInfo fieldInfo = FindFieldInHierarchy(((object)effect).GetType(), fieldNames[i]);
				if (!(fieldInfo == null) && !(fieldInfo.FieldType != typeof(float)))
				{
					if (!originals.ContainsKey(fieldInfo))
					{
						originals[fieldInfo] = fieldInfo.GetValue(effect);
					}
					fieldInfo.SetValue(effect, value);
				}
			}
		}

		private static void SetKeywordFloat(StatusEffect effect, Dictionary<FieldInfo, object> originals, string[] include, string[] exclude, float desiredPositiveValue)
		{
			Type type = ((object)effect).GetType();
			while (type != null)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.FieldType != typeof(float))
					{
						continue;
					}
					string text = fieldInfo.Name.ToLowerInvariant();
					bool flag = true;
					for (int j = 0; j < include.Length; j++)
					{
						if (!text.Contains(include[j]))
						{
							flag = false;
							break;
						}
					}
					if (!flag)
					{
						continue;
					}
					if (exclude != null)
					{
						for (int k = 0; k < exclude.Length; k++)
						{
							if (text.Contains(exclude[k]))
							{
								flag = false;
								break;
							}
						}
					}
					if (!flag)
					{
						continue;
					}
					float num = Convert.ToSingle(fieldInfo.GetValue(effect));
					if (!(Math.Abs(num) < 0.0001f))
					{
						if (!originals.ContainsKey(fieldInfo))
						{
							originals[fieldInfo] = num;
						}
						fieldInfo.SetValue(effect, (num < 0f) ? (0f - Math.Abs(desiredPositiveValue)) : Math.Abs(desiredPositiveValue));
					}
				}
				type = type.BaseType;
			}
		}

		private static void SetNamedNumericValue(object root, string token, float value)
		{
			if (root == null)
			{
				return;
			}
			Type type = root.GetType();
			while (type != null)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				for (int i = 0; i < fields.Length; i++)
				{
					object value2;
					try
					{
						value2 = fields[i].GetValue(root);
					}
					catch
					{
						continue;
					}
					if (!(value2 is IEnumerable enumerable) || value2 is string)
					{
						continue;
					}
					foreach (object item in enumerable)
					{
						if (item == null)
						{
							continue;
						}
						FieldInfo[] fields2 = item.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						string text = item.ToString().ToLowerInvariant();
						for (int j = 0; j < fields2.Length; j++)
						{
							if (!fields2[j].FieldType.IsEnum && !(fields2[j].FieldType == typeof(string)))
							{
								continue;
							}
							try
							{
								object value3 = fields2[j].GetValue(item);
								if (value3 != null)
								{
									text = text + " " + value3.ToString().ToLowerInvariant();
								}
							}
							catch
							{
							}
						}
						if (!text.Contains(token.ToLowerInvariant()))
						{
							continue;
						}
						foreach (FieldInfo fieldInfo in fields2)
						{
							if (fieldInfo.FieldType != typeof(float))
							{
								continue;
							}
							float num;
							try
							{
								num = Convert.ToSingle(fieldInfo.GetValue(item));
							}
							catch
							{
								continue;
							}
							if (!(Math.Abs(num) < 0.0001f))
							{
								try
								{
									fieldInfo.SetValue(item, (num < 0f) ? (0f - Math.Abs(value)) : Math.Abs(value));
								}
								catch
								{
								}
							}
						}
					}
				}
				type = type.BaseType;
			}
		}

		private static void SetResistance(StatusEffect effect, string damageToken, float percent)
		{
			if ((Object)(object)effect == (Object)null)
			{
				return;
			}
			string b = ((percent <= 0.1f) ? "Normal" : ((percent < 37.5f) ? "SlightlyResistant" : ((percent < 62.5f) ? "Resistant" : ((percent < 87.5f) ? "VeryResistant" : "Immune"))));
			Type type = ((object)effect).GetType();
			while (type != null)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				for (int i = 0; i < fields.Length; i++)
				{
					object value;
					try
					{
						value = fields[i].GetValue(effect);
					}
					catch
					{
						continue;
					}
					if (!(value is IEnumerable enumerable) || value is string)
					{
						continue;
					}
					foreach (object item in enumerable)
					{
						if (item == null)
						{
							continue;
						}
						FieldInfo[] fields2 = item.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						bool flag = false;
						for (int j = 0; j < fields2.Length; j++)
						{
							if (!fields2[j].FieldType.IsEnum && fields2[j].FieldType != typeof(string))
							{
								continue;
							}
							try
							{
								object value2 = fields2[j].GetValue(item);
								if (value2 != null && value2.ToString().IndexOf(damageToken, StringComparison.OrdinalIgnoreCase) >= 0)
								{
									flag = true;
								}
							}
							catch
							{
							}
						}
						if (!flag)
						{
							continue;
						}
						foreach (FieldInfo fieldInfo in fields2)
						{
							if (!fieldInfo.FieldType.IsEnum)
							{
								continue;
							}
							Array values = Enum.GetValues(fieldInfo.FieldType);
							foreach (object item2 in values)
							{
								if (string.Equals(item2.ToString(), b, StringComparison.OrdinalIgnoreCase))
								{
									try
									{
										fieldInfo.SetValue(item, item2);
									}
									catch
									{
									}
									break;
								}
							}
						}
					}
				}
				type = type.BaseType;
			}
		}

		private static void ClearSailingPowerAttribute(StatusEffect effect, Dictionary<FieldInfo, object> originals)
		{
			Type type = ((object)effect).GetType();
			while (type != null)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!fieldInfo.FieldType.IsEnum)
					{
						continue;
					}
					object value = fieldInfo.GetValue(effect);
					if (value != null && value.ToString().IndexOf("SailingPower", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						if (!originals.ContainsKey(fieldInfo))
						{
							originals[fieldInfo] = value;
						}
						fieldInfo.SetValue(effect, Enum.ToObject(fieldInfo.FieldType, 0));
					}
				}
				type = type.BaseType;
			}
		}

		private static int GetStableHash(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return 0;
			}
			int num = 5381;
			int num2 = 5381;
			for (int i = 0; i < text.Length; i += 2)
			{
				num = ((num << 5) + num) ^ text[i];
				if (i == text.Length - 1)
				{
					break;
				}
				num2 = ((num2 << 5) + num2) ^ text[i + 1];
			}
			return num + num2 * 1566083941;
		}

		private StatusEffect FindStatusEffect(string effectName)
		{
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(ObjectDB), "m_StatusEffects");
				IList list = ((fieldInfo == null) ? null : (fieldInfo.GetValue(ObjectDB.instance) as IList));
				if (list == null)
				{
					return null;
				}
				for (int i = 0; i < list.Count; i++)
				{
					object? obj = list[i];
					StatusEffect val = (StatusEffect)((obj is StatusEffect) ? obj : null);
					if ((Object)(object)val != (Object)null && ((Object)val).name == effectName)
					{
						return val;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private void RemoveBossPower(Player player, string effectName)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(SEMan), "RemoveStatusEffect", new Type[2]
				{
					typeof(int),
					typeof(bool)
				}, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(((Character)player).GetSEMan(), new object[2]
					{
						GetStableHash(effectName),
						true
					});
				}
			}
			catch
			{
			}
		}

		internal static bool IsBossPowerAvailable(ConfigEntry<bool> bossEnabled, string globalKey)
		{
			if ((Object)(object)Instance == (Object)null || MasterEnabled == null || !MasterEnabled.Value || BossPowersEnabled == null || !BossPowersEnabled.Value || bossEnabled == null || !bossEnabled.Value)
			{
				return false;
			}
			if (BossPowersRequireDefeat == null || !BossPowersRequireDefeat.Value)
			{
				return true;
			}
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return false;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(ZoneSystem), "GetGlobalKey", new Type[1] { typeof(string) }, (Type[])null);
				if (methodInfo != null)
				{
					return Convert.ToBoolean(methodInfo.Invoke(ZoneSystem.instance, new object[1] { globalKey }));
				}
			}
			catch
			{
			}
			return false;
		}

		private void RemoveManagedBossPowers()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				for (int i = 0; i < ManagedBossEffects.Length; i++)
				{
					RemoveBossPower(localPlayer, ManagedBossEffects[i]);
				}
			}
		}

		private void ApplyCircletLights()
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (!IsDvergerCircletEquipped(localPlayer))
			{
				RestoreCircletLights();
				_circletCachedPlayer = localPlayer;
				_circletCachedLights = null;
				return;
			}
			if ((Object)(object)_circletCachedPlayer != (Object)(object)localPlayer || _circletCachedLights == null || Time.time >= _nextCircletRescan)
			{
				_circletCachedPlayer = localPlayer;
				_nextCircletRescan = Time.time + 2f;
				Light[] componentsInChildren = ((Component)localPlayer).GetComponentsInChildren<Light>(true);
				List<Light> list = new List<Light>();
				foreach (Light val in componentsInChildren)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					string text = GetTransformPath(((Component)val).transform).ToLowerInvariant();
					bool flag = text.IndexOf("dverger") >= 0 || text.IndexOf("circlet") >= 0 || text.IndexOf("headlamp") >= 0;
					bool flag2 = (int)val.type == 0 && ((Component)val).transform.IsChildOf(((Component)localPlayer).transform);
					if (flag || flag2)
					{
						if (!list.Contains(val))
						{
							list.Add(val);
						}
						RememberCircletOriginal(val);
					}
				}
				_circletCachedLights = list.ToArray();
			}
			if (_circletCachedLights == null || _circletCachedLights.Length == 0)
			{
				return;
			}
			int num = Mathf.Max(2, CircletFocusSteps.Value);
			_circletStep = Mathf.Clamp(_circletStep, 0, num - 1);
			float num2 = Mathf.Clamp01((float)_circletStep / (float)(num - 1));
			float range = Mathf.Lerp(CircletRange.Value * 0.55f, CircletRange.Value, num2);
			float spotAngle = Mathf.Lerp(28f, 80f, num2);
			float intensity = Mathf.Lerp(CircletBrightness.Value * 1.5f, CircletBrightness.Value * 0.7f, num2);
			for (int j = 0; j < _circletCachedLights.Length; j++)
			{
				Light val2 = _circletCachedLights[j];
				if (!((Object)(object)val2 == (Object)null))
				{
					((Behaviour)val2).enabled = _circletLightOn;
					val2.range = range;
					val2.intensity = intensity;
					val2.color = new Color(0.95f, 0.98f, 1f, 1f);
					if ((int)val2.type == 0)
					{
						val2.spotAngle = spotAngle;
					}
				}
			}
		}

		private void RememberCircletOriginal(Light light)
		{
			//IL_005f: 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 (!((Object)(object)light == (Object)null))
			{
				int instanceID = ((Object)light).GetInstanceID();
				if (!_circletOriginals.ContainsKey(instanceID))
				{
					_circletOriginals[instanceID] = new CircletLightOriginal
					{
						Enabled = ((Behaviour)light).enabled,
						Range = light.range,
						Intensity = light.intensity,
						SpotAngle = light.spotAngle,
						Color = light.color
					};
				}
			}
		}

		private void RestoreCircletLights()
		{
			//IL_005c: 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 (_circletCachedLights == null)
			{
				return;
			}
			for (int i = 0; i < _circletCachedLights.Length; i++)
			{
				Light val = _circletCachedLights[i];
				if (!((Object)(object)val == (Object)null) && _circletOriginals.TryGetValue(((Object)val).GetInstanceID(), out var value) && value != null)
				{
					((Behaviour)val).enabled = value.Enabled;
					val.range = value.Range;
					val.intensity = value.Intensity;
					if ((int)val.type == 0)
					{
						val.spotAngle = value.SpotAngle;
					}
					val.color = value.Color;
				}
			}
		}

		private static bool IsDvergerCircletEquipped(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			Type type = ((object)player).GetType();
			while (type != null)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (typeof(ItemData).IsAssignableFrom(fieldInfo.FieldType))
					{
						ItemData item = null;
						try
						{
							object? value = fieldInfo.GetValue(player);
							item = (ItemData)((value is ItemData) ? value : null);
						}
						catch
						{
						}
						if (IsDvergerCircletItem(item))
						{
							return true;
						}
					}
				}
				type = type.BaseType;
			}
			try
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				List<ItemData> list = ((inventory == null) ? null : inventory.GetAllItems());
				if (list != null)
				{
					for (int j = 0; j < list.Count; j++)
					{
						ItemData val = list[j];
						if (!IsDvergerCircletItem(val))
						{
							continue;
						}
						bool flag = false;
						try
						{
							FieldInfo fieldInfo2 = AccessTools.Field(((object)val).GetType(), "m_equipped");
							if (fieldInfo2 != null)
							{
								flag = Convert.ToBoolean(fieldInfo2.GetValue(val));
							}
						}
						catch
						{
						}
						if (flag)
						{
							return true;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsDvergerCircletItem(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			string text = (item.m_shared.m_name ?? "") + " " + (((Object)(object)item.m_dropPrefab == (Object)null) ? "" : (((Object)item.m_dropPrefab).name ?? ""));
			text = text.ToLowerInvariant();
			if (text.IndexOf("dverger") >= 0)
			{
				if (text.IndexOf("circlet") < 0)
				{
					return text.IndexOf("helmet") >= 0;
				}
				return true;
			}
			return false;
		}

		private static string GetTransformPath(Transform t)
		{
			string text = (((Object)(object)t == (Object)null) ? "" : ((Object)t).name);
			while ((Object)(object)t != (Object)null && (Object)(object)t.parent != (Object)null)
			{
				t = t.parent;
				text = ((Object)t).name + "/" + text;
			}
			return text;
		}

		private void TryMapTeleport()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			Minimap instance = Minimap.instance;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", new Type[1] { typeof(Vector3) }, (Type[])null);
				if (methodInfo == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Map Teleport: Minimap.ScreenToWorldPoint was not found.");
					return;
				}
				Vector3 val = (Vector3)methodInfo.Invoke(instance, new object[1] { Input.mousePosition });
				if (val == Vector3.zero)
				{
					return;
				}
				if (WorldGenerator.instance != null)
				{
					val.y = WorldGenerator.instance.GetHeight(val.x, val.z) + 1.5f;
				}
				else if ((Object)(object)ZoneSystem.instance != (Object)null)
				{
					val.y = ZoneSystem.instance.GetGroundHeight(val) + 1.5f;
				}
				((Character)localPlayer).TeleportTo(val, ((Component)localPlayer).transform.rotation, true);
				try
				{
					MethodInfo methodInfo2 = AccessTools.Method(typeof(Minimap), "SetMapMode", (Type[])null, (Type[])null);
					if (methodInfo2 != null)
					{
						ParameterInfo[] parameters = methodInfo2.GetParameters();
						if (parameters.Length == 1 && parameters[0].ParameterType.IsEnum)
						{
							object obj = Enum.ToObject(parameters[0].ParameterType, 1);
							methodInfo2.Invoke(instance, new object[1] { obj });
						}
					}
				}
				catch
				{
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Map Teleport failed: " + ex.Message));
			}
		}

		private void TryQuickCart()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			float num = QuickCartDistance.Value;
			Vagon val = null;
			Vector3 val2 = ((Component)localPlayer).transform.position + Vector3.up;
			Collider[] array = Physics.OverlapSphere(val2, QuickCartDistance.Value);
			foreach (Collider val3 in array)
			{
				if ((Object)(object)val3 == (Object)null || (Object)(object)val3.attachedRigidbody == (Object)null)
				{
					continue;
				}
				Vagon component = ((Component)val3).gameObject.GetComponent<Vagon>();
				if ((Object)(object)component == (Object)null && (Object)(object)((Component)val3).transform.parent != (Object)null)
				{
					component = ((Component)((Component)val3).transform.parent).gameObject.GetComponent<Vagon>();
				}
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				float num2 = Vector3.Distance(val3.ClosestPoint(val2), val2);
				if (!(num2 >= num) && (component.IsAttached((Character)(object)localPlayer) || !component.InUse()))
				{
					num = num2;
					if ((Object)(object)((Component)val3).transform.parent != (Object)null)
					{
						Vagon component2 = ((Component)((Component)val3).transform.parent).gameObject.GetComponent<Vagon>();
						val = (((Object)(object)component2 != (Object)null) ? component2 : component);
					}
					else
					{
						val = component;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				val.Interact((Humanoid)(object)localPlayer, false, false);
			}
		}

		internal static float ComputeExploreRadius(Player player)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return LandExploreRadius.Value;
			}
			bool flag = false;
			try
			{
				flag = ((Character)player).IsAttachedToShip();
			}
			catch
			{
			}
			float num = (flag ? SeaExploreRadius.Value : LandExploreRadius.Value);
			if (!flag)
			{
				float num2 = Mathf.Max(0f, ((Component)player).transform.position.y - 30f);
				num += LandExploreRadius.Value * AltitudeExploreBonus.Value * (num2 / 100f);
			}
			return Mathf.Clamp(num, 0f, 10000f);
		}
	}
	[HarmonyPatch]
	internal static class SkipIntroCoroutinePatch
	{
		private static MethodBase TargetMethod()
		{
			Type typeFromHandle = typeof(FejdStartup);
			Type[] nestedTypes = typeFromHandle.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
			for (int i = 0; i < nestedTypes.Length; i++)
			{
				string name = nestedTypes[i].Name;
				if (name.IndexOf("PlayIntroCinematic", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					MethodInfo methodInfo = AccessTools.Method(nestedTypes[i], "MoveNext", (Type[])null, (Type[])null);
					if (methodInfo != null && methodInfo.ReturnType == typeof(bool))
					{
						return methodInfo;
					}
				}
			}
			return null;
		}

		private static bool Prefix(ref bool __result)
		{
			if (HeimToolzPlugin.On(HeimToolzPlugin.SkipIntroEnabled))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}
	internal static class EquipmentInWaterUtil
	{
		public static bool IsSwimmingForEquipment(Character character)
		{
			if (HeimToolzPlugin.On(HeimToolzPlugin.WaterEquipmentEnabled))
			{
				return false;
			}
			return character.IsSwimming();
		}

		public static IEnumerable<CodeInstruction> ReplaceSwimmingCheck(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo swimming = AccessTools.Method(typeof(Character), "IsSwimming", (Type[])null, (Type[])null);
			MethodInfo replacement = AccessTools.Method(typeof(EquipmentInWaterUtil), "IsSwimmingForEquipment", (Type[])null, (Type[])null);
			foreach (CodeInstruction code in instructions)
			{
				if ((code.opcode == OpCodes.Call || code.opcode == OpCodes.Callvirt) && code.operand is MethodInfo && (MethodInfo)code.operand == swimming)
				{
					yield return new CodeInstruction(OpCodes.Call, (object)replacement);
				}
				else
				{
					yield return code;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UpdateEquipment")]
	internal static class EquipmentInWaterUpdatePatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return EquipmentInWaterUtil.ReplaceSwimmingCheck(instructions);
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class EquipmentInWaterEquipPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return EquipmentInWaterUtil.ReplaceSwimmingCheck(instructions);
		}
	}
	[HarmonyPatch(typeof(Fermenter), "Awake")]
	internal static class FermenterAwakePatch
	{
		private static void Postfix(Fermenter __instance)
		{
			if (HeimToolzPlugin.On(HeimToolzPlugin.FermenterEnabled))
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(Fermenter), "m_fermentationDuration");
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(__instance, HeimToolzPlugin.FermenterMinutes.Value * 60f);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class ModerMovementSpeedPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			string[] names = new string[2] { "GetJogSpeedFactor", "GetRunSpeedFactor" };
			MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			for (int n = 0; n < names.Length; n++)
			{
				foreach (MethodInfo method in methods)
				{
					if (!(method == null) && !(method.Name != names[n]) && !(method.ReturnType != typeof(float)) && method.GetParameters().Length == 0)
					{
						yield return method;
						break;
					}
				}
			}
		}

		private static void Postfix(Player __instance, ref float __result)
		{
			if (HeimToolzPlugin.ModerMovementBonusActive(__instance))
			{
				float num = Mathf.Max(0f, HeimToolzPlugin.ModerMovementSpeed.Value) / 100f;
				__result *= 1f + num;
			}
		}
	}
	[HarmonyPatch(typeof(Fermenter), "GetHoverText")]
	internal static class FermenterHoverPatch
	{
		private static void Postfix(Fermenter __instance, ref string __result)
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.FermenterEnabled) || !HeimToolzPlugin.FermenterShowProgress.Value)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Fermenter), "GetStatus", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(Fermenter), "GetFermentationTime", (Type[])null, (Type[])null);
				if (!(methodInfo == null) && !(methodInfo2 == null))
				{
					object obj = methodInfo.Invoke(__instance, null);
					if (obj != null && obj.ToString().IndexOf("Fermenting", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						object value = methodInfo2.Invoke(__instance, null);
						float num = Convert.ToSingle(value);
						float num2 = Mathf.Max(1f, HeimToolzPlugin.FermenterMinutes.Value * 60f);
						float num3 = Mathf.Clamp01(num / num2) * 100f;
						__result = __result + "\n<color=#FFD36A>" + num3.ToString("0") + "%</color>";
					}
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(Fermenter), "GetStatus")]
	internal static class FermenterCoverPatch
	{
		private static void Postfix(ref object __result)
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.FermenterEnabled) || !HeimToolzPlugin.FermenterNoCover.Value || __result == null)
			{
				return;
			}
			Type type = __result.GetType();
			if (!type.IsEnum)
			{
				return;
			}
			string text = __result.ToString();
			if (text.IndexOf("Cover", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Exposed", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return;
			}
			try
			{
				object obj = Enum.Parse(type, "Fermenting");
				__result = obj;
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "Start")]
	internal static class BuildSpacePatch
	{
		private static void Postfix(CraftingStation __instance)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (!HeimToolzPlugin.On(HeimToolzPlugin.BuildSpaceEnabled))
			{
				return;
			}
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(CraftingStation), "m_rangeBuild");
				if (!(fieldInfo == null))
				{
					float num = Convert.ToSingle(fieldInfo.GetValue(__instance));
					fieldInfo.SetValue(__instance, num * HeimToolzPlugin.BuildRadiusMultiplier.Value);
					FieldInfo fieldInfo2 = AccessTools.Field(typeof(CraftingStation), "m_areaMarker");
					GameObject val = (GameObject)((fieldInfo2 == null) ? null : /*isinst with value type is only supported in some contexts*/);
					if ((Object)(object)val != (Object)null)
					{
						Transform transform = val.transform;
						transform.localScale *= HeimToolzPlugin.BuildRadiusMultiplier.Value;
					}
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(Ship), "GetSailForce")]
	internal static class FasterBoatWindPatch
	{
		private static void Postfix(ref Vector3 __result)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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)
			if (HeimToolzPlugin.On(HeimToolzPlugin.FasterBoatsEnabled))
			{
				__result *= HeimToolzPlugin.BoatWindMultiplier.Value;
			}
		}
	}
	[HarmonyPatch(typeof(Ship), "Awake")]
	internal static class FasterBoatRudderPatch
	{
		private static void Postfix(Ship __instance)
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.FasterBoatsEnabled))
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(Ship), "m_backwardForce");
			if (fieldInfo == null)
			{
				return;
			}
			try
			{
				float num = Convert.ToSingle(fieldInfo.GetValue(__instance));
				fieldInfo.SetValue(__instance, num * HeimToolzPlugin.BoatRudderMultiplier.Value);
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(Vagon), "CanAttach")]
	internal static class QuickCartAttachPatch
	{
		private static bool Prefix(Vagon __instance, GameObject go, ref bool __result)
		{
			//IL_003f: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (!HeimToolzPlugin.On(HeimToolzPlugin.QuickCartEnabled) || !HeimToolzPlugin.QuickCartOutOfPlace.Value || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)go != (Object)(object)((Component)Player.m_localPlayer).gameObject)
			{
				return true;
			}
			if (((Component)__instance).transform.up.y < 0.1f)
			{
				return true;
			}
			try
			{
				__result = !((Character)Player.m_localPlayer).IsTeleporting() && !((Character)Player.m_localPlayer).InDodge() && Vector3.Distance(go.transform.position + __instance.m_attachOffset, __instance.m_attachPoint.position) < HeimToolzPlugin.QuickCartDistance.Value;
				return false;
			}
			catch
			{
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UseStamina")]
	internal static class StaminaUsePatch
	{
		private static void Prefix(ref float v)
		{
			if (HeimToolzPlugin.On(HeimToolzPlugin.RegenerationEnabled))
			{
				v *= HeimToolzPlugin.StaminaCostMultiplier.Value;
			}
		}
	}
	[HarmonyPatch]
	internal static class RegenStatsPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo method in methods)
			{
				if (!(method == null) && !(method.Name != "UpdateStats") && !method.IsStatic && !(method.ReturnType != typeof(void)))
				{
					ParameterInfo[] p = method.GetParameters();
					if (p.Length != 0 && !(p[0].ParameterType != typeof(float)))
					{
						yield return method;
					}
				}
			}
		}

		private static void Prefix(Player __instance, ref float __state)
		{
			__state = 0f;
			if (HeimToolzPlugin.On(HeimToolzPlugin.RegenerationEnabled))
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_stamina");
				FieldInfo fieldInfo2 = AccessTools.Field(typeof(Player), "m_staminaRegenTimer");
				FieldInfo fieldInfo3 = AccessTools.Field(typeof(Player), "m_eiterRegen");
				if (fieldInfo != null)
				{
					__state = Convert.ToSingle(fieldInfo.GetValue(__instance));
				}
				if (fieldInfo2 != null)
				{
					float num = Convert.ToSingle(fieldInfo2.GetValue(__instance));
					fieldInfo2.SetValue(__instance, num * HeimToolzPlugin.StaminaRegenDelayMultiplier.Value);
				}
				if (fieldInfo3 != null)
				{
					fieldInfo3.SetValue(__instance, HeimToolzPlugin.EitrRegenRate.Value);
				}
			}
		}

		private static void Postfix(Player __instance, float __state)
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.RegenerationEnabled))
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_stamina");
			if (!(fieldInfo == null))
			{
				float num = Convert.ToSingle(fieldInfo.GetValue(__instance));
				if (__state > 0f && num > __state)
				{
					fieldInfo.SetValue(__instance, __state + (num - __state) * HeimToolzPlugin.StaminaRegenMultiplier.Value);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateFood")]
	internal static class HealthRegenDelayPatch
	{
		private static void Prefix(float dt, bool forceUpdate, ref float ___m_foodRegenTimer)
		{
			if (HeimToolzPlugin.On(HeimToolzPlugin.RegenerationEnabled) && !forceUpdate)
			{
				float num = Mathf.Max(0.1f, HeimToolzPlugin.HealthRegenDelayMultiplier.Value);
				___m_foodRegenTimer += dt / num - dt;
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Heal")]
	internal static class HealthRegenAmountPatch
	{
		private static void Prefix(Character __instance, ref float hp)
		{
			if (HeimToolzPlugin.On(HeimToolzPlugin.RegenerationEnabled) && __instance is Player)
			{
				hp *= HeimToolzPlugin.HealthRegenMultiplier.Value;
			}
		}
	}
	internal static class RegenerationFoodSlots
	{
		private static bool _apiResolved;

		private static MethodInfo _getFoodSlotsItems;

		private static MethodInfo _useItemMethod;

		private static MethodInfo _consumeItemMethod;

		private static MethodInfo _canConsumeItemMethod;

		private static bool _canConsumeResolved;

		internal static void TryAutoConsume(Player player)
		{
			if ((Object)(object)player == (Object)null || !HeimToolzPlugin.On(HeimToolzPlugin.RegenerationEnabled) || !HeimToolzPlugin.AutoConsumeExtraSlotsFood.Value)
			{
				return;
			}
			List<ItemData> extraSlotsFoodItems = GetExtraSlotsFoodItems();
			if (extraSlotsFoodItems == null || extraSlotsFoodItems.Count == 0)
			{
				return;
			}
			int activeFoodCount = GetActiveFoodCount(player);
			for (int i = 0; i < extraSlotsFoodItems.Count; i++)
			{
				ItemData item = extraSlotsFoodItems[i];
				if (!IsValidFoodItem(item))
				{
					continue;
				}
				if (IsFoodActive(player, item))
				{
					if (!IsFoodAtBlinkStage(player, item))
					{
						continue;
					}
				}
				else if (activeFoodCount >= 3)
				{
					continue;
				}
				if (TryUseFood(player, item))
				{
					break;
				}
			}
		}

		private static bool IsValidFoodItem(ItemData item)
		{
			if (item != null && item.m_stack > 0 && item.m_shared != null)
			{
				return item.m_shared.m_food > 0f;
			}
			return false;
		}

		private static bool ResolveCanConsumeMethod(Type playerType)
		{
			if (_canConsumeResolved)
			{
				return _canConsumeItemMethod != null;
			}
			_canConsumeResolved = true;
			if (playerType == null)
			{
				return false;
			}
			try
			{
				MethodInfo[] methods = playerType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "CanConsumeItem" || methodInfo.ReturnType != typeof(bool))
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					bool flag = false;
					bool flag2 = true;
					for (int j = 0; j < parameters.Length; j++)
					{
						Type parameterType = parameters[j].ParameterType;
						if (parameterType == typeof(ItemData))
						{
							flag = true;
						}
						else if (!(parameterType == typeof(bool)) && !(parameterType == typeof(Inventory)))
						{
							flag2 = false;
							break;
						}
					}
					if (flag2 && flag)
					{
						_canConsumeItemMethod = methodInfo;
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool CanConsumeNow(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null || _canConsumeItemMethod == null)
			{
				return false;
			}
			try
			{
				ParameterInfo[] parameters = _canConsumeItemMethod.GetParameters();
				object[] array = new object[parameters.Length];
				for (int i = 0; i < parameters.Length; i++)
				{
					Type parameterType = parameters[i].ParameterType;
					if (parameterType == typeof(ItemData))
					{
						array[i] = item;
						continue;
					}
					if (parameterType == typeof(bool))
					{
						array[i] = false;
						continue;
					}
					if (parameterType == typeof(Inventory))
					{
						array[i] = ((Humanoid)player).GetInventory();
						continue;
					}
					return false;
				}
				object obj = _canConsumeItemMethod.Invoke(player, array);
				return obj is bool && (bool)obj;
			}
			catch
			{
				return false;
			}
		}

		private static List<ItemData> GetExtraSlotsFoodItems()
		{
			ResolveApi();
			if (_getFoodSlotsItems == null)
			{
				return null;
			}
			try
			{
				object obj = _getFoodSlotsItems.Invoke(null, null);
				if (!(obj is IEnumerable enumerable))
				{
					return null;
				}
				List<ItemData> list = new List<ItemData>();
				foreach (object item in enumerable)
				{
					ItemData val = (ItemData)((item is ItemData) ? item : null);
					if (val != null)
					{
						list.Add(val);
					}
				}
				return list;
			}
			catch
			{
				return null;
			}
		}

		private static void ResolveApi()
		{
			if (_apiResolved)
			{
				return;
			}
			_apiResolved = true;
			try
			{
				Type type = Type.GetType("ExtraSlots.API, ExtraSlots", throwOnError: false);
				if (!(type == null))
				{
					_getFoodSlotsItems = type.GetMethod("GetFoodSlotsItems", BindingFlags.Static | BindingFlags.Public);
				}
			}
			catch
			{
			}
		}

		private static int GetActiveFoodCount(Player player)
		{
			int num = 0;
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_foods");
				IEnumerable enumerable = ((fieldInfo == null) ? null : (fieldInfo.GetValue(player) as IEnumerable));
				if (enumerable == null)
				{
					return 0;
				}
				foreach (object item in enumerable)
				{
					if (item != null)
					{
						num++;
					}
				}
			}
			catch
			{
			}
			return num;
		}

		private static bool IsFoodAtBlinkStage(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null || item.m_shared == null)
			{
				return false;
			}
			string text = item.m_shared.m_name ?? "";
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_foods");
				IEnumerable enumerable = ((fieldInfo == null) ? null : (fieldInfo.GetValue(player) as IEnumerable));
				if (enumerable == null)
				{
					return false;
				}
				foreach (object item2 in enumerable)
				{
					if (item2 == null)
					{
						continue;
					}
					Type type = item2.GetType();
					FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					ItemData val = null;
					foreach (FieldInfo fieldInfo2 in fields)
					{
						if (typeof(ItemData).IsAssignableFrom(fieldInfo2.FieldType))
						{
							try
							{
								object? value = fieldInfo2.GetValue(item2);
								val = (ItemData)((value is ItemData) ? value : null);
							}
							catch
							{
								val = null;
							}
							if (val != null && val.m_shared != null)
							{
								break;
							}
						}
					}
					if (val != null && val.m_shared != null && !(val.m_shared.m_name != text))
					{
						float foodBurnTime = val.m_shared.m_foodBurnTime;
						if (foodBurnTime <= 0f)
						{
							foodBurnTime = item.m_shared.m_foodBurnTime;
						}
						if (foodBurnTime <= 0f)
						{
							return false;
						}
						FieldInfo field = type.GetField("m_time", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field == null || field.FieldType != typeof(float))
						{
							return false;
						}
						float num = Convert.ToSingle(field.GetValue(item2));
						return num <= foodBurnTime * 0.5f;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsFoodActive(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null || item.m_shared == null)
			{
				return false;
			}
			string text = item.m_shared.m_name ?? "";
			string text2 = "";
			try
			{
				text2 = (((Object)(object)item.m_dropPrefab == (Object)null) ? "" : (((Object)item.m_dropPrefab).name ?? ""));
			}
			catch
			{
			}
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_foods");
				IEnumerable enumerable = ((fieldInfo == null) ? null : (fieldInfo.GetValue(player) as IEnumerable));
				if (enumerable == null)
				{
					return false;
				}
				foreach (object item2 in enumerable)
				{
					if (item2 == null)
					{
						continue;
					}
					FieldInfo[] fields = item2.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo2 in fields)
					{
						if (typeof(ItemData).IsAssignableFrom(fieldInfo2.FieldType))
						{
							ItemData val = null;
							try
							{
								object? value = fieldInfo2.GetValue(item2);
								val = (ItemData)((value is ItemData) ? value : null);
							}
							catch
							{
							}
							if (val != null && val.m_shared != null && val.m_shared.m_name == text)
							{
								return true;
							}
						}
						else if (fieldInfo2.FieldType == typeof(string))
						{
							string text3 = null;
							try
							{
								text3 = fieldInfo2.GetValue(item2) as string;
							}
							catch
							{
							}
							if (!string.IsNullOrEmpty(text3) && (text3 == text || (!string.IsNullOrEmpty(text2) && text3 == text2)))
							{
								return true;
							}
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool TryUseFood(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null)
			{
				return false;
			}
			ResolveConsumeMethods(((object)player).GetType());
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (_useItemMethod != null)
			{
				bool? flag = InvokeFoodMethod(_useItemMethod, player, inventory, item);
				if (flag.HasValue)
				{
					return flag.Value;
				}
			}
			if (_consumeItemMethod != null)
			{
				bool? flag2 = InvokeFoodMethod(_consumeItemMethod, player, inventory, item);
				if (flag2.HasValue)
				{
					return flag2.Value;
				}
			}
			return false;
		}

		private static void ResolveConsumeMethods(Type playerType)
		{
			if (_useItemMethod != null || _consumeItemMethod != null || playerType == null)
			{
				return;
			}
			try
			{
				MethodInfo[] methods = playerType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "UseItem" && methodInfo.Name != "ConsumeItem")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					bool flag = false;
					bool flag2 = true;
					for (int j = 0; j < parameters.Length; j++)
					{
						Type parameterType = parameters[j].ParameterType;
						if (parameterType == typeof(ItemData))
						{
							flag = true;
						}
						else if (!(parameterType == typeof(Inventory)) && !(parameterType == typeof(bool)))
						{
							flag2 = false;
							break;
						}
					}
					if (flag2 && flag)
					{
						if (methodInfo.Name == "UseItem" && _useItemMethod == null)
						{
							_useItemMethod = methodInfo;
						}
						if (methodInfo.Name == "ConsumeItem" && _consumeItemMethod == null)
						{
							_consumeItemMethod = methodInfo;
						}
					}
				}
			}
			catch
			{
			}
		}

		private static bool? InvokeFoodMethod(MethodInfo method, Player player, Inventory inventory, ItemData item)
		{
			if (method == null)
			{
				return null;
			}
			try
			{
				ParameterInfo[] parameters = method.GetParameters();
				object[] array = new object[parameters.Length];
				for (int i = 0; i < parameters.Length; i++)
				{
					Type parameterType = parameters[i].ParameterType;
					if (parameterType == typeof(ItemData))
					{
						array[i] = item;
						continue;
					}
					if (parameterType == typeof(Inventory))
					{
						array[i] = inventory;
						continue;
					}
					if (parameterType == typeof(bool))
					{
						array[i] = false;
						continue;
					}
					return null;
				}
				object value = method.Invoke(player, array);
				if (method.ReturnType == typeof(bool))
				{
					return Convert.ToBoolean(value);
				}
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "GetMaxCarryWeight")]
	internal static class CarryWeightPatch
	{
		private static void Postfix(ref float __result)
		{
			if (HeimToolzPlugin.On(HeimToolzPlugin.CarryWeightEnabled))
			{
				__result *= HeimToolzPlugin.CarryWeightMultiplier.Value;
			}
		}
	}
	[HarmonyPatch(typeof(Minimap), "UpdateExplore")]
	internal static class PathfinderPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			CodeInstruction previous = null;
			foreach (CodeInstruction code in instructions)
			{
				if (previous != null)
				{
					if (previous.opcode == OpCodes.Ldarg_0 && code.opcode == OpCodes.Ldfld && code.operand is FieldInfo && ((FieldInfo)code.operand).Name == "m_exploreRadius")
					{
						yield return new CodeInstruction(OpCodes.Ldarg_2, (object)null);
						yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PathfinderPatch), "GetExploreRadius", (Type[])null, (Type[])null));
						previous = null;
						continue;
					}
					yield return previous;
					previous = null;
				}
				if (code.opcode == OpCodes.Ldarg_0)
				{
					previous = code;
				}
				else
				{
					yield return code;
				}
			}
			if (previous != null)
			{
				yield return previous;
			}
		}

		public static float GetExploreRadius(Player player)
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.PathfinderEnabled))
			{
				return 100f;
			}
			if (HeimToolzPlugin.PathfinderDisableInDungeons.Value && IsInsideInstancedDungeon(player))
			{
				return 0f;
			}
			return HeimToolzPlugin.ComputeExploreRadius(player);
		}

		private static bool IsInsideInstancedDungeon(Player player)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).transform == (Object)null)
			{
				return false;
			}
			if (((Component)player).transform.position.y > 3000f)
			{
				return true;
			}
			try
			{
				if ((Object)(object)EnvMan.instance == (Object)null)
				{
					return false;
				}
				MethodInfo method = typeof(EnvMan).GetMethod("GetCurrentEnvironment", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				object obj = ((method == null) ? null : method.Invoke(EnvMan.instance, null));
				if (obj == null)
				{
					return false;
				}
				Type type = obj.GetType();
				string text = "";
				FieldInfo field = type.GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					object value = field.GetValue(obj);
					if (value != null)
					{
						text = value.ToString();
					}
				}
				if (string.IsNullOrEmpty(text))
				{
					return false;
				}
				string text2 = text.ToLowerInvariant();
				return text2.Contains("crypt") || text2.Contains("dungeon") || text2.Contains("cave") || text2.Contains("burial") || text2.Contains("trollcave") || text2.Contains("sunken");
			}
			catch
			{
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "GetBuildStamina")]
	internal static class BuildStaminaPatch
	{
		private static void Postfix(ref float __result)
		{
			if (HeimToolzPlugin.On(HeimToolzPlugin.FastToolsEnabled))
			{
				__result *= HeimToolzPlugin.BuildStaminaMultiplier.Value;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacement")]
	internal static class FastToolsPlacementPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			CodeInstruction previous = null;
			foreach (CodeInstruction code in instructions)
			{
				if (previous != null)
				{
					if (previous.opcode == OpCodes.Ldarg_0 && code.opcode == OpCodes.Ldfld && code.operand is FieldInfo)
					{
						string name = ((FieldInfo)code.operand).Name;
						if (name == "m_placeDelay")
						{
							yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(FastToolsPlacementPatch), "GetPlaceDelay", (Type[])null, (Type[])null));
							previous = null;
							continue;
						}
						if (name == "m_removeDelay")
						{
							yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(FastToolsPlacementPatch), "GetRemoveDelay", (Type[])null, (Type[])null));
							previous = null;
							continue;
						}
					}
					yield return previous;
					previous = null;
				}
				if (code.opcode == OpCodes.Ldarg_0)
				{
					previous = code;
				}
				else
				{
					yield return code;
				}
			}
			if (previous != null)
			{
				yield return previous;
			}
		}

		public static float GetPlaceDelay()
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.FastToolsEnabled))
			{
				return 0.4f;
			}
			return HeimToolzPlugin.PlaceDelay.Value;
		}

		public static float GetRemoveDelay()
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.FastToolsEnabled))
			{
				return 0.25f;
			}
			return HeimToolzPlugin.RemoveDelay.Value;
		}
	}
	internal static class DigDeeperTranspilerUtil
	{
		internal static IEnumerable<CodeInstruction> ReplaceEight(IEnumerable<CodeInstruction> instructions, bool depth)
		{
			foreach (CodeInstruction code in instructions)
			{
				if (code.opcode == OpCodes.Ldc_R4 && code.operand is float)
				{
					float value = (float)code.operand;
					if (Math.Abs(Math.Abs(value) - 8f) < 0.0001f)
					{
						yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DigDeeperTranspilerUtil), depth ? "GetDepth" : "GetHeight", (Type[])null, (Type[])null));
						if (value < 0f)
						{
							yield return new CodeInstruction(OpCodes.Neg, (object)null);
						}
						continue;
					}
				}
				yield return code;
			}
		}

		public static float GetDepth()
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.DigDeeperEnabled))
			{
				return 8f;
			}
			return HeimToolzPlugin.DigDepth.Value;
		}

		public static float GetHeight()
		{
			if (!HeimToolzPlugin.On(HeimToolzPlugin.DigDeeperEnabled))
			{
				return 8f;
			}
			return HeimToolzPlugin.RaiseHeight.Value;
		}
	}
	[HarmonyPatch(typeof(Heightmap), "LevelTerrain")]
	internal static class DigDeeperHeightmapPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return DigDeeperTranspilerUtil.ReplaceEight(instructions, depth: true);
		}
	}
	[HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")]
	internal static class DigDeeperApplyToHeightmapPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return DigDeeperTranspilerUtil.ReplaceEight(instructions, depth: true);
		}
	}
	[HarmonyPatch(typeof(TerrainComp), "LevelTerrain")]
	internal static class DigDeeperTerrainLevelPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return DigDeeperTranspilerUtil.ReplaceEight