Decompiled source of BiomeLords v0.6.15

BiomeLords.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BiomeLords.Config;
using BiomeLords.Data;
using BiomeLords.Patches;
using BiomeLords.Phase1B;
using BiomeLords.Phase1C;
using BiomeLords.Phase1D;
using BiomeLords.Util;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BiomeLords")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("BiomeLords")]
[assembly: AssemblyTitle("BiomeLords")]
[assembly: AssemblyVersion("0.1.0.0")]
namespace BiomeLords
{
	[BepInPlugin("com.taeguk.BiomeLords", "BiomeLords", "0.6.15")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGUID = "com.taeguk.BiomeLords";

		public const string ModName = "BiomeLords";

		public const string ModVersion = "0.6.15";

		internal static Plugin Instance;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			LordConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.taeguk.BiomeLords");
			int num = 0;
			int num2 = 0;
			Type[] types = typeof(Plugin).Assembly.GetTypes();
			foreach (Type type in types)
			{
				try
				{
					new PatchClassProcessor(_harmony, type).Patch();
					num++;
				}
				catch (Exception ex)
				{
					num2++;
					((BaseUnityPlugin)this).Logger.LogError((object)("[BiomeLords] Patch class " + type.FullName + " failed: " + ex.Message));
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"[BiomeLords] Harmony: {num} patch classes applied, {num2} skipped.");
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. {2} Lords registered.", "BiomeLords", "0.6.15", LordRegistry.All.Count));
		}

		private void OnVanillaPrefabsAvailable()
		{
			try
			{
				StatusEffectFactory.RegisterAll();
				GuardianPowerFactory.RegisterAll();
				SubEffectFactory.RegisterAll();
				TrophyFactory.RegisterAll();
				CreatureFactory.RegisterAll();
				ItemFactory.RegisterAll();
				PedestalFactory.RegisterAll();
				DebugCommands.RegisterAll();
				ObjectDB_Awake_BiomeLordsInject.InjectAll();
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"[BiomeLords] Registration failed: {arg}");
			}
			finally
			{
				PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace BiomeLords.Util
{
	public sealed class ConfigurationManagerAttributes
	{
		public bool? IsAdminOnly;

		public bool? Browsable;

		public string Category;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public Action<ConfigEntryBase> CustomDrawer;
	}
	public static class FeatherweightInventory
	{
		public const int BaseWidth = 8;

		public const int VanillaHeight = 4;

		public const int VanillaMaxRows = 9;

		private const string ComfyQuickSlotsGuid = "com.bruce.valheim.comfyquickslots";

		private const string ComfyQuickSlotsInvName = "ComfyQuickSlotsInventory";

		private static readonly string[] IncompatibleSlotModGuids = new string[2] { "shudnal.ExtraSlots", "Azumatt.AzuExtendedPlayerInventory" };

		private static int _incompatibleSlotMod = -1;

		private static int _minBaseHeight = -1;

		private static Player _baseHeightPlayer;

		private static int _baseHeightCached = -1;

		private static int _seHash;

		private static readonly FieldRef<Inventory, int> HeightRef = AccessTools.FieldRefAccess<Inventory, int>("m_height");

		public static bool IncompatibleSlotModLoaded
		{
			get
			{
				if (_incompatibleSlotMod < 0)
				{
					Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos;
					_incompatibleSlotMod = (IncompatibleSlotModGuids.Any(pluginInfos.ContainsKey) ? 1 : 0);
				}
				return _incompatibleSlotMod == 1;
			}
		}

		public static bool ComfyQuickSlotsLoaded => MinBaseHeight == 5;

		public static int MinBaseHeight
		{
			get
			{
				if (_minBaseHeight < 0)
				{
					_minBaseHeight = (Chainloader.PluginInfos.ContainsKey("com.bruce.valheim.comfyquickslots") ? 5 : 4);
				}
				return _minBaseHeight;
			}
		}

		public static int ExtraRows
		{
			get
			{
				if (!IncompatibleSlotModLoaded)
				{
					return Mathf.Max(0, LordConfig.FallerValkyrieExtraRows?.Value ?? 0);
				}
				return 0;
			}
		}

		public static int LoadCeiling => Mathf.Max(9, MinBaseHeight) + Mathf.Max(ExtraRows, 4);

		public static int SeHash
		{
			get
			{
				if (_seHash == 0)
				{
					_seHash = StringExtensionMethods.GetStableHashCode("SE_FallerValkyrieLordSpirit");
				}
				return _seHash;
			}
		}

		public static void InvalidateBaseHeight()
		{
			_baseHeightPlayer = null;
			_baseHeightCached = -1;
		}

		public static int PurchasedRows(Player p)
		{
			string s = default(string);
			if ((Object)(object)p != (Object)null && p.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result))
			{
				return Mathf.Clamp(result, 0, 9);
			}
			return 4;
		}

		public static int BaseHeight(Player p)
		{
			if ((Object)(object)p == (Object)null)
			{
				return MinBaseHeight;
			}
			if (p != _baseHeightPlayer || _baseHeightCached < 0)
			{
				_baseHeightCached = Mathf.Max(MinBaseHeight, PurchasedRows(p));
				_baseHeightPlayer = p;
			}
			return _baseHeightCached;
		}

		public static int ExpandedHeight(Player p)
		{
			return BaseHeight(p) + ExtraRows;
		}

		public static bool HasBlessing(Player p)
		{
			if ((Object)(object)p == (Object)null)
			{
				return false;
			}
			SEMan sEMan = ((Character)p).GetSEMan();
			if (sEMan != null)
			{
				return sEMan.HaveStatusEffect(SeHash);
			}
			return false;
		}

		public static bool IsPlayerInventory(Inventory inv)
		{
			if (inv == null || inv.GetWidth() != 8)
			{
				return false;
			}
			string name = inv.GetName();
			if (!(name == "Inventory"))
			{
				return name == "ComfyQuickSlotsInventory";
			}
			return true;
		}

		public static void GrowForLoad(Inventory inv)
		{
			if (inv != null && !IncompatibleSlotModLoaded && HeightRef.Invoke(inv) < LoadCeiling)
			{
				HeightRef.Invoke(inv) = LoadCeiling;
			}
		}

		public static void EnsureExpanded(Inventory inv)
		{
			if (inv == null || IncompatibleSlotModLoaded)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Humanoid)localPlayer).GetInventory() != inv)
			{
				return;
			}
			int num = ExpandedHeight(localPlayer);
			if (HeightRef.Invoke(inv) < num && HasBlessing(localPlayer))
			{
				if (LordConfig.DebugLogging.Value)
				{
					Logger.LogInfo((object)($"[BiomeLords] Featherweight: inventory height had drifted to {HeightRef.Invoke(inv)}, " + $"restoring to {num} so the extra rows count as real capacity."));
				}
				HeightRef.Invoke(inv) = num;
			}
		}

		public static Vector2i FindExtraRowSlot(Inventory inv, bool topFirst)
		{
			//IL_0013: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			Vector2i result = default(Vector2i);
			((Vector2i)(ref result))..ctor(-1, -1);
			if (inv == null || IncompatibleSlotModLoaded)
			{
				return result;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Humanoid)localPlayer).GetInventory() != inv)
			{
				return result;
			}
			EnsureExpanded(inv);
			int height = inv.GetHeight();
			int width = inv.GetWidth();
			int num = BaseHeight(localPlayer);
			if (height <= num)
			{
				return result;
			}
			if (topFirst)
			{
				for (int i = num; i < height; i++)
				{
					for (int j = 0; j < width; j++)
					{
						if (inv.GetItemAt(j, i) == null)
						{
							return new Vector2i(j, i);
						}
					}
				}
			}
			else
			{
				for (int num2 = height - 1; num2 >= num; num2--)
				{
					for (int k = 0; k < width; k++)
					{
						if (inv.GetItemAt(k, num2) == null)
						{
							return new Vector2i(k, num2);
						}
					}
				}
			}
			return result;
		}

		public static void Reconcile(Player p)
		{
			if (!((Object)(object)p == (Object)null))
			{
				InvalidateBaseHeight();
				int target = ((HasBlessing(p) && ExtraRows > 0) ? ExpandedHeight(p) : BaseHeight(p));
				SetHeight(p, target);
			}
		}

		public static void Collapse(Player p)
		{
			if (!((Object)(object)p == (Object)null))
			{
				InvalidateBaseHeight();
				SetHeight(p, BaseHeight(p));
			}
		}

		private static void SetHeight(Player p, int target)
		{
			if (IncompatibleSlotModLoaded)
			{
				return;
			}
			Inventory inventory = ((Humanoid)p).GetInventory();
			if (inventory != null)
			{
				List<ItemData> list = (from it in inventory.GetAllItems()
					where it.m_gridPos.y >= target
					select it).ToList();
				if (list.Count > 0)
				{
					SpillToCrate(p, inventory, list);
				}
				HeightRef.Invoke(inventory) = target;
			}
		}

		private static void SpillToCrate(Player p, Inventory inv, List<ItemData> items)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			GameObject cratePrefab = GetCratePrefab();
			Container val = null;
			int num = 0;
			int num2 = 0;
			foreach (ItemData item in items)
			{
				bool flag = false;
				if ((Object)(object)cratePrefab != (Object)null)
				{
					if ((Object)(object)val == (Object)null)
					{
						val = SpawnCrate(p, cratePrefab, num++);
					}
					flag = (Object)(object)val != (Object)null && val.GetInventory().AddItem(item);
					if (!flag && (Object)(object)val != (Object)null)
					{
						val = SpawnCrate(p, cratePrefab, num++);
						flag = (Object)(object)val != (Object)null && val.GetInventory().AddItem(item);
					}
				}
				if (!flag)
				{
					ItemDrop.DropItem(item, item.m_stack, ((Component)p).transform.position + Vector3.up * 0.5f, Quaternion.identity);
					num2++;
				}
				inv.RemoveItem(item);
			}
			((Character)p).Message((MessageType)2, (num > 0) ? "$biomelords_featherweight_crate" : "$biomelords_featherweight_dropped", 0, (Sprite)null, false);
			if (LordConfig.DebugLogging.Value)
			{
				Logger.LogInfo((object)($"[BiomeLords] Featherweight collapse: {items.Count} item(s) cleared from extra rows " + $"({num} crate(s), ground-dropped={num2})."));
			}
		}

		private static Container SpawnCrate(Player p, GameObject prefab, int index)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			float num = (float)(index - 1) * 25f;
			Vector3 val = Quaternion.Euler(0f, num, 0f) * ((Component)p).transform.forward;
			Vector3 val2 = ((Component)p).transform.position + val * 1.5f + Vector3.up * 0.5f;
			GameObject val3 = Object.Instantiate<GameObject>(prefab, val2, Quaternion.identity);
			if (!((Object)(object)val3 != (Object)null))
			{
				return null;
			}
			return val3.GetComponent<Container>();
		}

		private static GameObject GetCratePrefab()
		{
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			GameObject prefab = instance.GetPrefab("CargoCrate");
			if ((Object)(object)prefab != (Object)null)
			{
				return prefab;
			}
			GameObject prefab2 = instance.GetPrefab("Cart");
			Container val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponentInChildren<Container>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.m_destroyedLootPrefab;
		}
	}
	public static class FxLibrary
	{
		private static bool _dumped;

		public static GameObject TrySpawn(string name, Vector3 pos, Quaternion? rot = null, Transform parent = null)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(name);
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(prefab, pos, (Quaternion)(((??)rot) ?? Quaternion.identity));
			if ((Object)(object)parent != (Object)null)
			{
				val.transform.SetParent(parent, true);
			}
			return val;
		}

		public static GameObject TrySpawnTimed(string name, Vector3 pos, float lifetime)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = TrySpawn(name, pos);
			if ((Object)(object)val != (Object)null && lifetime > 0f)
			{
				Object.Destroy((Object)(object)val, lifetime);
			}
			return val;
		}

		public static GameObject TrySpawnFirst(IEnumerable<string> names, Vector3 pos)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			foreach (string name in names)
			{
				GameObject val = TrySpawn(name, pos);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		public static void DumpFxNamesOnce()
		{
			if (_dumped)
			{
				return;
			}
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null || instance.m_prefabs == null)
			{
				return;
			}
			_dumped = true;
			int num = 0;
			foreach (GameObject prefab in instance.m_prefabs)
			{
				if (!((Object)(object)prefab == (Object)null))
				{
					string name = ((Object)prefab).name;
					if (name.StartsWith("fx_") || name.StartsWith("vfx_") || name.Contains("ummon"))
					{
						Logger.LogInfo((object)("[BiomeLords.FxDump] " + name));
						num++;
					}
				}
			}
			Logger.LogInfo((object)$"[BiomeLords.FxDump] {num} candidate FX prefabs dumped.");
		}
	}
	public static class IconAssignment
	{
		private static readonly Dictionary<string, string[]> Map = new Dictionary<string, string[]>
		{
			{
				"GP_TidesGrace",
				new string[3] { "Harpoon", "FishingRod", "Wet" }
			},
			{
				"GP_Rootward",
				new string[3] { "Root", "GreydwarfEye", "Wood" }
			},
			{
				"GP_PlagueBearer",
				new string[4] { "Poison", "Ooze", "BloodPudding", "Entrails" }
			},
			{
				"GP_HowlOfThePack",
				new string[2] { "WolfFang", "FreezeGland" }
			},
			{
				"GP_BullRush",
				new string[3] { "ShieldWood", "ShieldBronzeBuckler", "ShieldIronTower" }
			},
			{
				"GP_HiveSense",
				new string[3] { "Wisplight", "Wisp", "Eitr" }
			},
			{
				"GP_ValkyrieAscension",
				new string[1] { "Feathers" }
			},
			{
				"GP_Petrify",
				new string[3] { "Stone", "Grausten", "BlackMarble" }
			},
			{
				"SE_NeckLordSpirit",
				new string[2] { "FishingBait", "Fish1" }
			},
			{
				"SE_GreydwarfLordSpirit",
				new string[2] { "Carrot", "CarrotSeeds" }
			},
			{
				"SE_DraugrLordSpirit",
				new string[2] { "IronScrap", "Iron" }
			},
			{
				"SE_FenringLordSpirit",
				new string[3] { "WolfPelt", "WolfFang", "TrophyWolf" }
			},
			{
				"SE_LoxLordSpirit",
				new string[3] { "CookedLoxMeat", "LoxMeat", "Barley" }
			},
			{
				"SE_SeekerLordSpirit",
				new string[3] { "Coal", "Bronze", "Iron" }
			},
			{
				"SE_FallerValkyrieLordSpirit",
				new string[1] { "Feathers" }
			},
			{
				"SE_GammeltrollLordSpirit",
				new string[3] { "BjornHide", "TrollHide", "WolfPelt" }
			},
			{
				"SE_ForestSitting",
				new string[3] { "Sheltered", "Shelter", "Rested" }
			},
			{
				"SE_PetrifiedSkin",
				new string[2] { "Stone", "Grausten" }
			}
		};

		public static void AssignAll()
		{
			int num = 0;
			int num2 = 0;
			foreach (KeyValuePair<string, string[]> item in Map)
			{
				StatusEffect val = ResolveSE(item.Key);
				if ((Object)(object)val == (Object)null)
				{
					num2++;
					continue;
				}
				Sprite val2 = FindFirstItemIcon(item.Value);
				if ((Object)(object)val2 != (Object)null)
				{
					val.m_icon = val2;
					num++;
				}
				else
				{
					num2++;
				}
			}
			Sprite featherFallIcon = GetFeatherFallIcon();
			if ((Object)(object)featherFallIcon != (Object)null)
			{
				StatusEffect val3 = ResolveSE("SE_FallerValkyrieLordSpirit");
				if ((Object)(object)val3 != (Object)null)
				{
					val3.m_icon = featherFallIcon;
				}
				StatusEffect val4 = ResolveSE("GP_ValkyrieAscension");
				if ((Object)(object)val4 != (Object)null)
				{
					val4.m_icon = featherFallIcon;
				}
			}
			else
			{
				Logger.LogWarning((object)"[BiomeLords] IconAssignment: Feather fall icon not found; Valkyrie SEs kept their fallback icons.");
			}
			Logger.LogInfo((object)$"[BiomeLords] IconAssignment: {num} SEs got icons, {num2} missed.");
		}

		private static Sprite GetFeatherFallIcon()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("CapeFeather");
			StatusEffect val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_equipStatusEffect;
			if ((Object)(object)val != (Object)null && (Object)(object)val.m_icon != (Object)null)
			{
				return val.m_icon;
			}
			return FindFirstItemIcon(new string[1] { "Feathers" });
		}

		private static StatusEffect ResolveSE(string name)
		{
			if (GuardianPowerFactory.ByName.TryGetValue(name, out var value))
			{
				return value;
			}
			if (StatusEffectFactory.ByName.TryGetValue(name, out var value2))
			{
				return value2;
			}
			if (SubEffectFactory.ByName.TryGetValue(name, out var value3))
			{
				return value3;
			}
			return null;
		}

		private static Sprite FindFirstItemIcon(string[] candidates)
		{
			ObjectDB instance = ObjectDB.instance;
			foreach (string text in candidates)
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(text);
				Sprite[] array = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_icons;
				if (array != null && array.Length != 0 && (Object)(object)array[0] != (Object)null)
				{
					return array[0];
				}
				if (!((Object)(object)instance != (Object)null) || instance.m_StatusEffects == null)
				{
					continue;
				}
				foreach (StatusEffect statusEffect in instance.m_StatusEffects)
				{
					if (!((Object)(object)statusEffect == (Object)null) && !((Object)(object)statusEffect.m_icon == (Object)null) && ((Object)statusEffect).name == text)
					{
						return statusEffect.m_icon;
					}
				}
			}
			return null;
		}
	}
	public static class KillStore
	{
		private const string Prefix = "BiomeLords.kills.";

		public static int Get(Player p, string prefabName)
		{
			if ((Object)(object)p == (Object)null || string.IsNullOrEmpty(prefabName))
			{
				return 0;
			}
			if (!p.m_customData.TryGetValue("BiomeLords.kills." + prefabName, out var value) || !int.TryParse(value, out var result))
			{
				return 0;
			}
			return result;
		}

		public static void Set(Player p, string prefabName, int value)
		{
			if (!((Object)(object)p == (Object)null) && !string.IsNullOrEmpty(prefabName))
			{
				p.m_customData["BiomeLords.kills." + prefabName] = value.ToString();
			}
		}

		public static int Increment(Player p, string prefabName)
		{
			if ((Object)(object)p == (Object)null || string.IsNullOrEmpty(prefabName))
			{
				return 0;
			}
			string key = "BiomeLords.kills." + prefabName;
			int num = ((p.m_customData.TryGetValue(key, out var value) && int.TryParse(value, out var result)) ? result : 0);
			num++;
			p.m_customData[key] = num.ToString();
			return num;
		}

		public static int SumFor(Player p, IEnumerable<string> prefabNames)
		{
			int num = 0;
			foreach (string prefabName in prefabNames)
			{
				num += Get(p, prefabName);
			}
			return num;
		}
	}
	public struct DamageProfile
	{
		public float Blunt;

		public float Slash;

		public float Pierce;

		public float Fire;

		public float Frost;

		public float Lightning;

		public float Poison;

		public float Spirit;
	}
	public static class LordAttackProfile
	{
		private static readonly Dictionary<string, DamageProfile> Profiles = new Dictionary<string, DamageProfile>
		{
			{
				"neck_lord",
				new DamageProfile
				{
					Slash = 6f
				}
			},
			{
				"greydwarf_lord",
				new DamageProfile
				{
					Slash = 17f
				}
			},
			{
				"draugr_lord",
				new DamageProfile
				{
					Slash = 58f
				}
			},
			{
				"fenring_lord",
				new DamageProfile
				{
					Slash = 85f
				}
			},
			{
				"lox_lord",
				new DamageProfile
				{
					Slash = 130f
				}
			},
			{
				"seeker_lord",
				new DamageProfile
				{
					Pierce = 120f
				}
			},
			{
				"faller_valkyrie_lord",
				new DamageProfile
				{
					Pierce = 160f
				}
			},
			{
				"gammeltroll_lord",
				new DamageProfile
				{
					Blunt = 220f
				}
			}
		};

		private static readonly DamageProfile[] ByTier = new DamageProfile[9]
		{
			default(DamageProfile),
			new DamageProfile
			{
				Blunt = 6f
			},
			new DamageProfile
			{
				Blunt = 17f
			},
			new DamageProfile
			{
				Blunt = 58f
			},
			new DamageProfile
			{
				Blunt = 85f
			},
			new DamageProfile
			{
				Blunt = 130f
			},
			new DamageProfile
			{
				Blunt = 120f
			},
			new DamageProfile
			{
				Blunt = 160f
			},
			new DamageProfile
			{
				Blunt = 220f
			}
		};

		public static bool TryGet(string lordId, out DamageProfile profile)
		{
			if (!string.IsNullOrEmpty(lordId) && Profiles.TryGetValue(lordId, out profile))
			{
				return true;
			}
			profile = default(DamageProfile);
			return false;
		}

		public static bool TryGetByTier(int tier, out DamageProfile profile)
		{
			if (tier >= 1 && tier <= 8)
			{
				profile = ByTier[tier];
				return true;
			}
			profile = default(DamageProfile);
			return false;
		}

		public static float TierMagnitude(int tier)
		{
			if (!TryGetByTier(tier, out var profile))
			{
				return 0f;
			}
			return profile.Blunt + profile.Slash + profile.Pierce + profile.Fire + profile.Frost + profile.Lightning + profile.Poison + profile.Spirit;
		}

		public static DamageProfile Resolve(string lordId, int nativeTier, int effectiveTier)
		{
			TryGet(lordId, out var profile);
			if (effectiveTier <= nativeTier || !TryGetByTier(effectiveTier, out var profile2))
			{
				return profile;
			}
			DamageProfile result = new DamageProfile
			{
				Fire = profile.Fire + profile2.Fire,
				Frost = profile.Frost + profile2.Frost,
				Lightning = profile.Lightning + profile2.Lightning,
				Poison = profile.Poison + profile2.Poison,
				Spirit = profile.Spirit + profile2.Spirit
			};
			float num = profile2.Blunt + profile2.Slash + profile2.Pierce;
			if (profile.Pierce >= profile.Blunt && profile.Pierce >= profile.Slash && profile.Pierce > 0f)
			{
				result.Pierce = ((num > 0f) ? num : profile.Pierce);
			}
			else if (profile.Blunt >= profile.Slash && profile.Blunt > 0f)
			{
				result.Blunt = ((num > 0f) ? num : profile.Blunt);
			}
			else if (profile.Slash > 0f)
			{
				result.Slash = ((num > 0f) ? num : profile.Slash);
			}
			return result;
		}
	}
	public static class LordBaseStats
	{
		private static readonly Dictionary<string, float> BaseHp = new Dictionary<string, float>
		{
			{ "neck_lord", 500f },
			{ "greydwarf_lord", 2500f },
			{ "draugr_lord", 5000f },
			{ "fenring_lord", 7500f },
			{ "lox_lord", 10000f },
			{ "seeker_lord", 12500f },
			{ "faller_valkyrie_lord", 25000f },
			{ "gammeltroll_lord", 47000f }
		};

		public static float DefaultHpFor(string lordId, int tier)
		{
			if (!string.IsNullOrEmpty(lordId) && BaseHp.TryGetValue(lordId, out var value))
			{
				return value;
			}
			return TierTable.HpFor(tier);
		}

		public static float HpFor(string lordId, int tier)
		{
			float num = LordConfig.BaseHealth(lordId);
			if (!(num > 0f))
			{
				return DefaultHpFor(lordId, tier);
			}
			return num;
		}
	}
	public static class LordDamageRegistry
	{
		private static readonly Dictionary<int, float> _mults = new Dictionary<int, float>();

		public static void Set(Character c, float multiplier)
		{
			if (!((Object)(object)c == (Object)null))
			{
				_mults[((Object)c).GetInstanceID()] = multiplier;
			}
		}

		public static float Get(Character c, float fallback = 1f)
		{
			if ((Object)(object)c == (Object)null)
			{
				return fallback;
			}
			if (!_mults.TryGetValue(((Object)c).GetInstanceID(), out var value))
			{
				return fallback;
			}
			return value;
		}

		public static bool Has(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return false;
			}
			return _mults.ContainsKey(((Object)c).GetInstanceID());
		}

		public static void Clear(Character c)
		{
			if (!((Object)(object)c == (Object)null))
			{
				_mults.Remove(((Object)c).GetInstanceID());
			}
		}
	}
	public static class LordDefeatStore
	{
		private const string KeyPrefix = "biomelords_defeated_";

		public static void RecordDefeat(string lordId)
		{
			if (string.IsNullOrEmpty(lordId))
			{
				return;
			}
			if (LordConfig.GlobalLordDefeats != null && LordConfig.GlobalLordDefeats.Value)
			{
				if (!((Object)(object)ZoneSystem.instance == (Object)null))
				{
					ZoneSystem.instance.SetGlobalKey("biomelords_defeated_" + lordId);
					Logger.LogInfo((object)("[BiomeLords] Recorded Lord defeat: " + lordId + " (global key — all players affected)."));
				}
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				((Humanoid)localPlayer).AddUniqueKey("biomelords_defeated_" + lordId);
				Logger.LogInfo((object)("[BiomeLords] Recorded Lord defeat: " + lordId + " (player key — " + localPlayer.GetPlayerName() + " only)."));
			}
		}

		public static int HighestDefeatedTier()
		{
			int num = 0;
			if (LordConfig.GlobalLordDefeats != null && LordConfig.GlobalLordDefeats.Value)
			{
				if ((Object)(object)ZoneSystem.instance == (Object)null)
				{
					return 0;
				}
				foreach (BiomeLordDef item in LordRegistry.All)
				{
					if (ZoneSystem.instance.GetGlobalKey("biomelords_defeated_" + item.Id) && item.Tier > num)
					{
						num = item.Tier;
					}
				}
			}
			else
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					return 0;
				}
				foreach (BiomeLordDef item2 in LordRegistry.All)
				{
					if (((Humanoid)localPlayer).HaveUniqueKey("biomelords_defeated_" + item2.Id) && item2.Tier > num)
					{
						num = item2.Tier;
					}
				}
			}
			return num;
		}
	}
	public static class LordIntrinsic
	{
		private static readonly Dictionary<string, float> DamageMult = new Dictionary<string, float>
		{
			{ "neck_lord", 1f },
			{ "greydwarf_lord", 1f },
			{ "draugr_lord", 1f },
			{ "fenring_lord", 1f },
			{ "lox_lord", 1f },
			{ "seeker_lord", 1f },
			{ "faller_valkyrie_lord", 1f },
			{ "gammeltroll_lord", 1f }
		};

		private static readonly Dictionary<string, float> Defaults = new Dictionary<string, float>(DamageMult);

		public static IEnumerable<string> Ids => Defaults.Keys;

		public static float DamageMultiplier(string lordId)
		{
			if (lordId == null)
			{
				return 1f;
			}
			if (!DamageMult.TryGetValue(lordId, out var value))
			{
				return 1f;
			}
			return value;
		}

		public static bool IsKnown(string lordId)
		{
			if (!string.IsNullOrEmpty(lordId))
			{
				return Defaults.ContainsKey(lordId);
			}
			return false;
		}

		public static float Set(string lordId, float value)
		{
			if (!IsKnown(lordId))
			{
				return -1f;
			}
			float value2;
			float result = (DamageMult.TryGetValue(lordId, out value2) ? value2 : 1f);
			DamageMult[lordId] = value;
			return result;
		}

		public static bool Reset(string lordId)
		{
			if (!Defaults.TryGetValue(lordId, out var value))
			{
				return false;
			}
			DamageMult[lordId] = value;
			return true;
		}

		public static int ResetAll()
		{
			foreach (KeyValuePair<string, float> @default in Defaults)
			{
				DamageMult[@default.Key] = @default.Value;
			}
			return Defaults.Count;
		}

		public static float DefaultFor(string lordId)
		{
			if (!Defaults.TryGetValue(lordId, out var value))
			{
				return 1f;
			}
			return value;
		}
	}
	public static class LordProfileRegistry
	{
		private static readonly Dictionary<int, DamageProfile> _profiles = new Dictionary<int, DamageProfile>();

		public static void Set(Character c, DamageProfile profile)
		{
			if (!((Object)(object)c == (Object)null))
			{
				_profiles[((Object)c).GetInstanceID()] = profile;
			}
		}

		public static bool TryGet(Character c, out DamageProfile profile)
		{
			if ((Object)(object)c != (Object)null && _profiles.TryGetValue(((Object)c).GetInstanceID(), out profile))
			{
				return true;
			}
			profile = default(DamageProfile);
			return false;
		}

		public static void Clear(Character c)
		{
			if (!((Object)(object)c == (Object)null))
			{
				_profiles.Remove(((Object)c).GetInstanceID());
			}
		}
	}
	public static class RecipeParser
	{
		public static RequirementConfig[] Parse(string csv, RequirementConfig[] fallback, bool recover, string logContext)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			List<RequirementConfig> list = new List<RequirementConfig>();
			if (!string.IsNullOrWhiteSpace(csv))
			{
				string[] array = csv.Split(',');
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (string.IsNullOrEmpty(text))
					{
						continue;
					}
					string[] array2 = text.Split(':');
					if (array2.Length == 2)
					{
						string text2 = array2[0].Trim();
						if (!string.IsNullOrEmpty(text2) && int.TryParse(array2[1].Trim(), out var result) && result > 0)
						{
							list.Add(new RequirementConfig
							{
								Item = text2,
								Amount = result,
								Recover = recover
							});
						}
					}
				}
			}
			if (list.Count == 0)
			{
				Logger.LogWarning((object)("[BiomeLords] " + logContext + " recipe empty / unparseable — falling back to defaults."));
				return fallback;
			}
			return list.ToArray();
		}
	}
	public static class RegisteredLords
	{
		public static readonly HashSet<string> PrefabNames = new HashSet<string>();

		public static readonly Dictionary<string, string> EventByPrefab = new Dictionary<string, string>();

		public static readonly Dictionary<string, string> LordIdByPrefab = new Dictionary<string, string>();

		public static void Register(string prefabName, string eventName = null, string lordId = null)
		{
			if (!string.IsNullOrEmpty(prefabName))
			{
				PrefabNames.Add(prefabName);
				if (!string.IsNullOrEmpty(eventName))
				{
					EventByPrefab[prefabName] = eventName;
				}
				if (!string.IsNullOrEmpty(lordId))
				{
					LordIdByPrefab[prefabName] = lordId;
				}
			}
		}

		public static string LordIdFor(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return null;
			}
			if (!LordIdByPrefab.TryGetValue(StripClone(((Object)((Component)c).gameObject).name), out var value))
			{
				return null;
			}
			return value;
		}

		public static bool IsLord(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return false;
			}
			return PrefabNames.Contains(StripClone(((Object)((Component)c).gameObject).name));
		}

		public static string EventFor(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return null;
			}
			if (!EventByPrefab.TryGetValue(StripClone(((Object)((Component)c).gameObject).name), out var value))
			{
				return null;
			}
			return value;
		}

		private static string StripClone(string n)
		{
			if (string.IsNullOrEmpty(n))
			{
				return n;
			}
			if (!n.EndsWith("(Clone)"))
			{
				return n;
			}
			return n.Substring(0, n.Length - "(Clone)".Length);
		}
	}
	public static class SpriteTinter
	{
		public static Sprite Tint(Sprite source, Color targetHueColor)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0079: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_00c3: 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)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			try
			{
				Texture2D texture = source.texture;
				if ((Object)(object)texture == (Object)null)
				{
					return source;
				}
				RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0);
				RenderTexture active = RenderTexture.active;
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false);
				val.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0);
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				float num = default(float);
				float num2 = default(float);
				float num3 = default(float);
				Color.RGBToHSV(targetHueColor, ref num, ref num2, ref num3);
				Color[] pixels = val.GetPixels();
				float num4 = default(float);
				float num5 = default(float);
				for (int i = 0; i < pixels.Length; i++)
				{
					Color val2 = pixels[i];
					if (!(val2.a < 0.02f))
					{
						Color.RGBToHSV(val2, ref num3, ref num4, ref num5);
						float num6 = Mathf.Max(num4, 0.75f);
						Color val3 = Color.HSVToRGB(num, num6, num5);
						val3.a = val2.a;
						pixels[i] = val3;
					}
				}
				val.SetPixels(pixels);
				val.Apply();
				return Sprite.Create(val, source.rect, new Vector2(0.5f, 0.5f), source.pixelsPerUnit);
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[BiomeLords] SpriteTinter failed: " + ex.Message));
				return source;
			}
		}
	}
	public static class StorageWindowPosition
	{
		private const float FallbackCellSize = 70f;

		private const float ScreenMargin = 48f;

		private static RectTransform _tracked;

		private static Vector2 _base;

		private static bool _hooked;

		public static void Apply(InventoryGui gui)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = gui?.m_container;
			if (!((Object)(object)val == (Object)null))
			{
				Track(val);
				EnsureDragger(gui, val);
				HookConfig();
				float num = CellSize(gui);
				val.anchoredPosition = new Vector2(_base.x + LordConfig.StorageUiOffsetColumns.Value * num, _base.y - LordConfig.StorageUiOffsetRows.Value * num);
				ClampToScreen(val);
			}
		}

		internal static void SetDragged(RectTransform container, Vector2 anchored)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)container == (Object)null))
			{
				Track(container);
				container.anchoredPosition = anchored;
			}
		}

		internal static void CommitDragged(InventoryGui gui, RectTransform container)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)container == (Object)null))
			{
				Track(container);
				ClampToScreen(container);
				float num = CellSize(gui);
				if (!(num <= 0f))
				{
					Vector2 anchoredPosition = container.anchoredPosition;
					LordConfig.StorageUiOffsetColumns.Value = (anchoredPosition.x - _base.x) / num;
					LordConfig.StorageUiOffsetRows.Value = (_base.y - anchoredPosition.y) / num;
				}
			}
		}

		private static void Track(RectTransform container)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_tracked == (Object)(object)container))
			{
				_tracked = container;
				_base = container.anchoredPosition;
			}
		}

		private static float CellSize(InventoryGui gui)
		{
			float num = (((Object)(object)gui != (Object)null && (Object)(object)gui.m_playerGrid != (Object)null) ? gui.m_playerGrid.m_elementSpace : 0f);
			if (!(num > 0f))
			{
				return 70f;
			}
			return num;
		}

		private static void EnsureDragger(InventoryGui gui, RectTransform container)
		{
			StorageWindowDragger obj = ((Component)container).GetComponent<StorageWindowDragger>() ?? ((Component)container).gameObject.AddComponent<StorageWindowDragger>();
			obj.Gui = gui;
			obj.SlotArea = (RectTransform)(((Object)(object)gui.ContainerGrid != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
		}

		private static void HookConfig()
		{
			if (!_hooked)
			{
				_hooked = true;
				LordConfig.StorageUiOffsetColumns.SettingChanged += OnChanged;
				LordConfig.StorageUiOffsetRows.SettingChanged += OnChanged;
			}
			static void OnChanged(object _, EventArgs __)
			{
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				InventoryGui instance = InventoryGui.instance;
				if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_container == (Object)null))
				{
					float num = CellSize(instance);
					instance.m_container.anchoredPosition = new Vector2(_base.x + LordConfig.StorageUiOffsetColumns.Value * num, _base.y - LordConfig.StorageUiOffsetRows.Value * num);
					ClampToScreen(instance.m_container);
				}
			}
		}

		private static Camera UiCamera(RectTransform rt)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Canvas val = (((Object)(object)rt != (Object)null) ? ((Component)rt).GetComponentInParent<Canvas>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if ((int)val.renderMode != 0)
			{
				return val.worldCamera;
			}
			return null;
		}

		private static bool TryGetScreenRect(RectTransform rt, out Rect rect)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			rect = default(Rect);
			if ((Object)(object)rt == (Object)null)
			{
				return false;
			}
			Camera val = UiCamera(rt);
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			rt.GetWorldCorners(array);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(float.MaxValue, float.MaxValue);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(float.MinValue, float.MinValue);
			for (int i = 0; i < 4; i++)
			{
				Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val, array[i]);
				if (float.IsNaN(val4.x) || float.IsNaN(val4.y) || float.IsInfinity(val4.x) || float.IsInfinity(val4.y))
				{
					return false;
				}
				val2 = Vector2.Min(val2, val4);
				val3 = Vector2.Max(val3, val4);
			}
			Vector2 val5 = val3 - val2;
			if (val5.x < 1f || val5.y < 1f)
			{
				return false;
			}
			rect = new Rect(val2, val5);
			return true;
		}

		private static bool TryScreenDeltaToLocal(RectTransform rt, Vector2 screenDelta, out Vector2 local)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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)
			local = Vector2.zero;
			RectTransform val = (RectTransform)(((Object)(object)rt != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Camera val2 = UiCamera(rt);
			Vector2 val3 = new Vector2((float)Screen.width, (float)Screen.height) * 0.5f;
			Vector2 val4 = default(Vector2);
			if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(val, val3, val2, ref val4))
			{
				return false;
			}
			Vector2 val5 = default(Vector2);
			if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(val, val3 + screenDelta, val2, ref val5))
			{
				return false;
			}
			local = val5 - val4;
			return true;
		}

		private static void ClampToScreen(RectTransform rt)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)rt == (Object)null) && TryGetScreenRect(rt, out var rect))
			{
				float num = Mathf.Min(48f, ((Rect)(ref rect)).width);
				float num2 = Mathf.Min(48f, ((Rect)(ref rect)).height);
				float num3 = 0f;
				float num4 = 0f;
				if (((Rect)(ref rect)).xMax < num)
				{
					num3 = num - ((Rect)(ref rect)).xMax;
				}
				else if (((Rect)(ref rect)).xMin > (float)Screen.width - num)
				{
					num3 = (float)Screen.width - num - ((Rect)(ref rect)).xMin;
				}
				if (((Rect)(ref rect)).yMax < num2)
				{
					num4 = num2 - ((Rect)(ref rect)).yMax;
				}
				else if (((Rect)(ref rect)).yMin > (float)Screen.height - num2)
				{
					num4 = (float)Screen.height - num2 - ((Rect)(ref rect)).yMin;
				}
				if ((num3 != 0f || num4 != 0f) && TryScreenDeltaToLocal(rt, new Vector2(num3, num4), out var local))
				{
					rt.anchoredPosition += local;
				}
			}
		}
	}
	public class StorageWindowDragger : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		internal InventoryGui Gui;

		internal RectTransform SlotArea;

		private RectTransform _rect;

		private RectTransform _parent;

		private Canvas _canvas;

		private Vector2 _grabOffset;

		private bool _dragging;

		private void Awake()
		{
			ref RectTransform rect = ref _rect;
			Transform transform = ((Component)this).transform;
			rect = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			_parent = (RectTransform)(((Object)(object)_rect != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			_canvas = ((Component)this).GetComponentInParent<Canvas>();
		}

		public void OnBeginDrag(PointerEventData e)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			_dragging = false;
			if (!((Object)(object)_rect == (Object)null) && !((Object)(object)_parent == (Object)null) && (int)e.button == 0 && !StartedOnSlots(e) && ToLocal(e.position, out var local))
			{
				_grabOffset = _rect.anchoredPosition - local;
				_dragging = true;
			}
		}

		public void OnDrag(PointerEventData e)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (_dragging && ToLocal(e.position, out var local))
			{
				StorageWindowPosition.SetDragged(_rect, local + _grabOffset);
			}
		}

		public void OnEndDrag(PointerEventData e)
		{
			if (_dragging)
			{
				_dragging = false;
				StorageWindowPosition.CommitDragged(Gui, _rect);
			}
		}

		private bool StartedOnSlots(PointerEventData e)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)SlotArea == (Object)null)
			{
				return false;
			}
			RaycastResult val = e.pointerPressRaycast;
			GameObject gameObject = ((RaycastResult)(ref val)).gameObject;
			if (gameObject == null)
			{
				val = e.pointerCurrentRaycast;
				gameObject = ((RaycastResult)(ref val)).gameObject;
			}
			GameObject val2 = gameObject;
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.transform.IsChildOf((Transform)(object)SlotArea);
			}
			return false;
		}

		private bool ToLocal(Vector2 screen, out Vector2 local)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Camera val = (((Object)(object)_canvas != (Object)null && (int)_canvas.renderMode != 0) ? _canvas.worldCamera : null);
			return RectTransformUtility.ScreenPointToLocalPointInRectangle(_parent, screen, val, ref local);
		}
	}
	public static class TierTable
	{
		public const int MinTier = 1;

		public const int MaxTier = 8;

		private static readonly float[] HpByTier = new float[9] { 0f, 500f, 2500f, 5000f, 7500f, 10000f, 12500f, 25000f, 47000f };

		public static int Clamp(int tier)
		{
			if (tier >= 1)
			{
				if (tier <= 8)
				{
					return tier;
				}
				return 8;
			}
			return 1;
		}

		public static float HpFor(int tier)
		{
			return HpByTier[Clamp(tier)];
		}
	}
}
namespace BiomeLords.Phase1D
{
	public static class DebugCommands
	{
		private class ResetCooldowns : ConsoleCommand
		{
			public override string Name => "biomelords_reset_cooldowns";

			public override string Help => "Resets BiomeLords Forsaken Power and pedestal blessing cooldowns for the local player.";

			public override bool IsCheat => true;

			public override bool IsNetwork => false;

			public override void Run(string[] args)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					Console instance = Console.instance;
					if (instance != null)
					{
						instance.Print("BiomeLords: no local player.");
					}
					return;
				}
				localPlayer.m_guardianPowerCooldown = 0f;
				if (localPlayer.m_customData != null)
				{
					List<string> list = localPlayer.m_customData.Keys.Where((string k) => k.StartsWith("BiomeLords.bless.next.")).ToList();
					foreach (string item in list)
					{
						localPlayer.m_customData.Remove(item);
					}
					Console instance2 = Console.instance;
					if (instance2 != null)
					{
						instance2.Print($"BiomeLords: cleared {list.Count} blessing cooldown(s) + GP cooldown.");
					}
				}
				else
				{
					Console instance3 = Console.instance;
					if (instance3 != null)
					{
						instance3.Print("BiomeLords: GP cooldown cleared.");
					}
				}
			}
		}

		private class CropTimes : ConsoleCommand
		{
			public override string Name => "biomelords_crop_times";

			public override string Help => "Toggles hover-text display of remaining grow time on planted crops (debug).";

			public override bool IsCheat => true;

			public override bool IsNetwork => false;

			public override void Run(string[] args)
			{
				bool value = LordConfig.ShowCropGrowTimes.Value;
				LordConfig.ShowCropGrowTimes.Value = !value;
				bool value2 = LordConfig.ShowCropGrowTimes.Value;
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print($"BiomeLords: crop grow-time display {value} -> {value2}.");
				}
				if (value2 == value)
				{
					Console instance2 = Console.instance;
					if (instance2 != null)
					{
						instance2.Print("  (Write may have been blocked. Edit the config file directly: BepInEx/config/com.taeguk.BiomeLords.cfg → [General] ShowCropGrowTimes = true)");
					}
				}
				else
				{
					Console instance3 = Console.instance;
					if (instance3 != null)
					{
						instance3.Print("  Hover over a planted crop to see remaining / total grow time in cyan.");
					}
				}
			}
		}

		private class Intrinsic : ConsoleCommand
		{
			public override string Name => "biomelords_intrinsic";

			public override string Help => "Read/write per-Lord intrinsic damage multiplier. Usage: biomelords_intrinsic [<lord_id> [<value>|reset] | reset]. No args = list all. Changes are session-only.";

			public override bool IsCheat => true;

			public override bool IsNetwork => false;

			public override void Run(string[] args)
			{
				if (args == null || args.Length == 0)
				{
					PrintAll();
					return;
				}
				if (args.Length == 1 && args[0].Equals("reset", StringComparison.OrdinalIgnoreCase))
				{
					int num = LordIntrinsic.ResetAll();
					RefreshAllLordInstances();
					Console instance = Console.instance;
					if (instance != null)
					{
						instance.Print($"BiomeLords: reset {num} Lord intrinsics to defaults.");
					}
					return;
				}
				string text = args[0].ToLowerInvariant();
				if (!LordIntrinsic.IsKnown(text))
				{
					Console instance2 = Console.instance;
					if (instance2 != null)
					{
						instance2.Print("BiomeLords: unknown lord_id '" + text + "'. Known: " + string.Join(", ", LordIntrinsic.Ids));
					}
				}
				else if (args.Length == 1)
				{
					PrintOne(text);
				}
				else if (args.Length == 2 && args[1].Equals("reset", StringComparison.OrdinalIgnoreCase))
				{
					float num2 = LordIntrinsic.DamageMultiplier(text);
					LordIntrinsic.Reset(text);
					float num3 = LordIntrinsic.DamageMultiplier(text);
					RefreshLordInstances(text);
					Console instance3 = Console.instance;
					if (instance3 != null)
					{
						instance3.Print($"BiomeLords: {text} intrinsic {num2:F2} -> {num3:F2} (default).");
					}
				}
				else
				{
					if (args.Length < 2)
					{
						return;
					}
					if (!float.TryParse(args[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						Console instance4 = Console.instance;
						if (instance4 != null)
						{
							instance4.Print("BiomeLords: '" + args[1] + "' is not a number. Examples: 1.0, 0.35, 2.5");
						}
						return;
					}
					if (result < 0f)
					{
						Console instance5 = Console.instance;
						if (instance5 != null)
						{
							instance5.Print("BiomeLords: value must be >= 0.");
						}
						return;
					}
					float num4 = LordIntrinsic.Set(text, result);
					int num5 = RefreshLordInstances(text);
					Console instance6 = Console.instance;
					if (instance6 != null)
					{
						instance6.Print($"BiomeLords: {text} intrinsic {num4:F2} -> {result:F2} " + $"(refreshed {num5} live instance(s); next spawns use the new value).");
					}
				}
			}

			private static void PrintAll()
			{
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print("BiomeLords intrinsic damage multipliers (current / default):");
				}
				foreach (string id in LordIntrinsic.Ids)
				{
					float num = LordIntrinsic.DamageMultiplier(id);
					float num2 = LordIntrinsic.DefaultFor(id);
					string text = ((Math.Abs(num - num2) > 0.0001f) ? "  *" : "");
					Console instance2 = Console.instance;
					if (instance2 != null)
					{
						instance2.Print($"  {id,-16}  {num:F2} / {num2:F2}{text}");
					}
				}
				Console instance3 = Console.instance;
				if (instance3 != null)
				{
					instance3.Print("Set: biomelords_intrinsic <lord_id> <value>   |   Reset: biomelords_intrinsic [<lord_id>] reset");
				}
			}

			private static void PrintOne(string lordId)
			{
				float num = LordIntrinsic.DamageMultiplier(lordId);
				float num2 = LordIntrinsic.DefaultFor(lordId);
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print($"BiomeLords: {lordId} intrinsic = {num:F2} (default {num2:F2}).");
				}
			}

			private static int RefreshLordInstances(string lordId)
			{
				int num = 0;
				BiomeLordDef biomeLordDef = LordRegistry.ById(lordId);
				if (biomeLordDef == null)
				{
					return 0;
				}
				int effectiveTier = Math.Max(biomeLordDef.Tier, LordDefeatStore.HighestDefeatedTier());
				DamageProfile profile = LordAttackProfile.Resolve(biomeLordDef.Id, biomeLordDef.Tier, effectiveTier);
				float num2 = LordConfig.DamageMultiplier(biomeLordDef.Id);
				float num3 = LordIntrinsic.DamageMultiplier(biomeLordDef.Id);
				float multiplier = num2 * num3;
				List<Character> allCharacters = Character.GetAllCharacters();
				for (int i = 0; i < allCharacters.Count; i++)
				{
					Character val = allCharacters[i];
					if (!((Object)(object)val == (Object)null) && !val.IsDead() && !(RegisteredLords.LordIdFor(val) != lordId))
					{
						LordDamageRegistry.Set(val, multiplier);
						LordProfileRegistry.Set(val, profile);
						num++;
					}
				}
				return num;
			}

			private static void RefreshAllLordInstances()
			{
				foreach (string id in LordIntrinsic.Ids)
				{
					RefreshLordInstances(id);
				}
			}
		}

		private class TameTime : ConsoleCommand
		{
			private const float DefaultRadius = 10f;

			public override string Name => "biomelords_tame_time";

			public override string Help => "Shows remaining tame time for untamed tameable creatures near the local player. Usage: biomelords_tame_time [radius]  (default radius = 10 m)";

			public override bool IsCheat => true;

			public override bool IsNetwork => false;

			public override void Run(string[] args)
			{
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0186: Unknown result type (might be due to invalid IL or missing references)
				//IL_018b: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					Console instance = Console.instance;
					if (instance != null)
					{
						instance.Print("BiomeLords: no local player.");
					}
					return;
				}
				float result = 10f;
				if (args != null && args.Length >= 1 && (!float.TryParse(args[0], NumberStyles.Float, CultureInfo.InvariantCulture, out result) || result <= 0f))
				{
					Console instance2 = Console.instance;
					if (instance2 != null)
					{
						instance2.Print("BiomeLords: invalid radius. Usage: biomelords_tame_time [radius]");
					}
					return;
				}
				Vector3 position = ((Component)localPlayer).transform.position;
				List<string> list = new List<string>();
				List<Character> allCharacters = Character.GetAllCharacters();
				for (int i = 0; i < allCharacters.Count; i++)
				{
					Character val = allCharacters[i];
					if (!((Object)(object)val == (Object)null) && !val.IsDead() && !(Vector3.Distance(((Component)val).transform.position, position) > result))
					{
						Tameable component = ((Component)val).GetComponent<Tameable>();
						if (!((Object)(object)component == (Object)null) && !val.IsTamed())
						{
							float tamingTime = component.m_tamingTime;
							ZNetView component2 = ((Component)val).GetComponent<ZNetView>();
							float num = (((Object)(object)component2 != (Object)null && component2.GetZDO() != null) ? component2.GetZDO().GetFloat(ZDOVars.s_tameTimeLeft, tamingTime) : tamingTime);
							float num2 = ((tamingTime > 0f) ? ((1f - num / tamingTime) * 100f) : 100f);
							int num3 = (int)(num / 60f);
							int num4 = (int)(num % 60f);
							string arg = ((Localization.instance != null) ? Localization.instance.Localize(val.m_name) : val.m_name);
							float num5 = Vector3.Distance(((Component)val).transform.position, position);
							list.Add($"  {arg} ({num5:F1}m away): " + $"{num3}m {num4}s left  ({num2:F0}% tamed, " + $"total {tamingTime / 60f:F1}m)");
						}
					}
				}
				if (list.Count == 0)
				{
					Console instance3 = Console.instance;
					if (instance3 != null)
					{
						instance3.Print($"BiomeLords: no untamed tameable creatures within {result:F0} m.");
					}
					return;
				}
				Console instance4 = Console.instance;
				if (instance4 != null)
				{
					instance4.Print($"BiomeLords: {list.Count} untamed tameable creature(s) within {result:F0} m:");
				}
				foreach (string item in list)
				{
					Console instance5 = Console.instance;
					if (instance5 != null)
					{
						instance5.Print(item);
					}
				}
			}
		}

		private class DumpAttacks : ConsoleCommand
		{
			private static readonly string[] BasePrefabs = new string[7] { "Neck", "Greydwarf_Shaman", "Draugr_Elite", "Fenring", "Lox", "Seeker", "FallenValkyrie" };

			public override string Name => "biomelords_dump_attacks";

			public override string Help => "Dumps vanilla melee attack damage values for all 7 Lord base prefabs to the log.";

			public override bool IsCheat => true;

			public override bool IsNetwork => false;

			public override void Run(string[] args)
			{
				//IL_0119: Unknown result type (might be due to invalid IL or missing references)
				//IL_011e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0142: Unknown result type (might be due to invalid IL or missing references)
				//IL_016e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0157: Unknown result type (might be due to invalid IL or missing references)
				//IL_019a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0183: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01af: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_01db: Unknown result type (might be due to invalid IL or missing references)
				//IL_021e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0207: Unknown result type (might be due to invalid IL or missing references)
				//IL_024a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0233: 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_025f: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_028b: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_030f: Unknown result type (might be due to invalid IL or missing references)
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("[BiomeLords] === Vanilla attack damage dump ===");
				string[] basePrefabs = BasePrefabs;
				List<ItemData> itemSets;
				foreach (string text in basePrefabs)
				{
					GameObject prefab = PrefabManager.Instance.GetPrefab(text);
					if ((Object)(object)prefab == (Object)null)
					{
						stringBuilder.AppendLine("  " + text + ": PREFAB NOT FOUND");
						continue;
					}
					stringBuilder.AppendLine("\n  [" + text + "]");
					Humanoid component = prefab.GetComponent<Humanoid>();
					if ((Object)(object)component == (Object)null)
					{
						stringBuilder.AppendLine("    (no Humanoid component)");
						continue;
					}
					itemSets = new List<ItemData>();
					CollectArray(component.m_defaultItems);
					CollectArray(component.m_randomWeapon);
					CollectArray(component.m_randomShield);
					if (itemSets.Count == 0)
					{
						stringBuilder.AppendLine("    (no default items found)");
						continue;
					}
					foreach (ItemData item in itemSets)
					{
						if (item.m_shared != null)
						{
							DamageTypes damages = item.m_shared.m_damages;
							StringBuilder stringBuilder2 = new StringBuilder("    " + item.m_shared.m_name + ": ");
							if (damages.m_damage > 0f)
							{
								stringBuilder2.Append($"damage={damages.m_damage} ");
							}
							if (damages.m_blunt > 0f)
							{
								stringBuilder2.Append($"blunt={damages.m_blunt} ");
							}
							if (damages.m_slash > 0f)
							{
								stringBuilder2.Append($"slash={damages.m_slash} ");
							}
							if (damages.m_pierce > 0f)
							{
								stringBuilder2.Append($"pierce={damages.m_pierce} ");
							}
							if (damages.m_chop > 0f)
							{
								stringBuilder2.Append($"chop={damages.m_chop} ");
							}
							if (damages.m_pickaxe > 0f)
							{
								stringBuilder2.Append($"pickaxe={damages.m_pickaxe} ");
							}
							if (damages.m_fire > 0f)
							{
								stringBuilder2.Append($"fire={damages.m_fire} ");
							}
							if (damages.m_frost > 0f)
							{
								stringBuilder2.Append($"frost={damages.m_frost} ");
							}
							if (damages.m_lightning > 0f)
							{
								stringBuilder2.Append($"lightning={damages.m_lightning} ");
							}
							if (damages.m_poison > 0f)
							{
								stringBuilder2.Append($"poison={damages.m_poison} ");
							}
							if (damages.m_spirit > 0f)
							{
								stringBuilder2.Append($"spirit={damages.m_spirit} ");
							}
							stringBuilder.AppendLine(stringBuilder2.ToString().TrimEnd());
						}
					}
					void CollectArray(GameObject[] arr)
					{
						if (arr != null)
						{
							foreach (GameObject val in arr)
							{
								if (!((Object)(object)val == (Object)null))
								{
									ItemDrop component2 = val.GetComponent<ItemDrop>();
									if ((Object)(object)component2 != (Object)null)
									{
										Collect(component2.m_itemData);
									}
								}
							}
						}
					}
				}
				stringBuilder.AppendLine("\n[BiomeLords] === End dump ===");
				string text2 = stringBuilder.ToString();
				Logger.LogInfo((object)text2);
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print(text2);
				}
				void Collect(ItemData item)
				{
					if (item != null)
					{
						itemSets.Add(item);
					}
				}
			}
		}

		private class DumpQueenAttackFx : ConsoleCommand
		{
			public override string Name => "biomelords_dump_queen_attack";

			public override string Help => "Dumps vanilla SeekerQueen attack-item projectile/trail prefab names to the log.";

			public override bool IsCheat => true;

			public override bool IsNetwork => false;

			public override void Run(string[] args)
			{
				//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
				StringBuilder sb = new StringBuilder();
				sb.AppendLine("[BiomeLords] === SeekerQueen attack FX dump ===");
				GameObject prefab = PrefabManager.Instance.GetPrefab("SeekerQueen");
				List<ItemData> itemSets;
				if ((Object)(object)prefab == (Object)null)
				{
					sb.AppendLine("  SeekerQueen: PREFAB NOT FOUND");
				}
				else
				{
					Humanoid component = prefab.GetComponent<Humanoid>();
					itemSets = new List<ItemData>();
					if ((Object)(object)component != (Object)null)
					{
						CollectArray(component.m_defaultItems);
						CollectArray(component.m_randomWeapon);
					}
					foreach (ItemData item in itemSets)
					{
						Attack val = item?.m_shared?.m_attack;
						if (val == null)
						{
							continue;
						}
						sb.AppendLine($"  Attack item: {item.m_shared.m_name}  (type={val.m_attackType})");
						sb.AppendLine("    m_attackProjectile = " + (((Object)(object)val.m_attackProjectile != (Object)null) ? ((Object)val.m_attackProjectile).name : "(none)"));
						DumpEffectList("m_trailStartEffect", val.m_trailStartEffect);
						DumpEffectList("m_hitEffect", val.m_hitEffect);
						DumpEffectList("m_startEffect (launch vfx+sfx)", val.m_startEffect);
						if ((Object)(object)val.m_attackProjectile != (Object)null)
						{
							Projectile component2 = val.m_attackProjectile.GetComponent<Projectile>();
							if ((Object)(object)component2 != (Object)null)
							{
								sb.AppendLine("    projectile.m_visual = " + (((Object)(object)component2.m_visual != (Object)null) ? ((Object)component2.m_visual).name : "(none)"));
								sb.AppendLine("    projectile.m_spawnOnHit = " + (((Object)(object)component2.m_spawnOnHit != (Object)null) ? ((Object)component2.m_spawnOnHit).name : "(none)"));
								DumpEffectList("    projectile.m_hitEffects (impact vfx+sfx)", component2.m_hitEffects);
								DumpEffectList("    projectile.m_spawnOnHitEffects", component2.m_spawnOnHitEffects);
							}
						}
					}
					if (itemSets.Count == 0)
					{
						sb.AppendLine("  (no attack items found on SeekerQueen)");
					}
				}
				sb.AppendLine("\n[BiomeLords] === End dump ===");
				string text = sb.ToString();
				Logger.LogInfo((object)text);
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print(text);
				}
				void Collect(ItemData item)
				{
					if (item != null)
					{
						itemSets.Add(item);
					}
				}
				void CollectArray(GameObject[] arr)
				{
					if (arr != null)
					{
						foreach (GameObject val2 in arr)
						{
							if (!((Object)(object)val2 == (Object)null))
							{
								ItemDrop component3 = val2.GetComponent<ItemDrop>();
								if ((Object)(object)component3 != (Object)null)
								{
									Collect(component3.m_itemData);
								}
							}
						}
					}
				}
				void DumpEffectList(string label, EffectList list)
				{
					if (list?.m_effectPrefabs != null && list.m_effectPrefabs.Length != 0)
					{
						EffectData[] effectPrefabs = list.m_effectPrefabs;
						foreach (EffectData val2 in effectPrefabs)
						{
							if ((Object)(object)val2?.m_prefab != (Object)null)
							{
								sb.AppendLine("    " + label + " = " + ((Object)val2.m_prefab).name);
							}
						}
					}
				}
			}
		}

		public static void RegisterAll()
		{
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ResetCooldowns());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CropTimes());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new Intrinsic());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DumpAttacks());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TameTime());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DumpQueenAttackFx());
			Logger.LogInfo((object)"[BiomeLords] Registered debug console commands.");
		}
	}
	public class DraugrLordBrain : MonoBehaviour
	{
		private const float CleaveCooldown = 30f;

		private const float CleaveRange = 5f;

		private const float WoundDuration = 60f;

		private const float WoundTickDamage = 5f;

		private const float WoundTickInterval = 1f;

		private const float SurgeHpFraction = 0.4f;

		private const float SurgeHealPerKill = 500f;

		private const float SurgeAbsorbRadius = 60f;

		private const float MinionCooldown = 60f;

		private const int MaxNearbyMinions = 3;

		private const int MinionsPerSummon = 2;

		private const float MinionDetectRadius = 12f;

		private const float CloudHpFraction = 0.6f;

		private const float DeathThroesHpFrac = 0.25f;

		private const float DeathThroesSpeed = 1.5f;

		private const float WetTickInterval = 2f;

		private const float WetTouchRadius = 3f;

		private const string MinionPrefab = "Draugr";

		private Character _character;

		private Humanoid _humanoid;

		private ZNetView _nview;

		private float _baseSpeed;

		private float _baseRunSpeed;

		private bool _cloudFired;

		private bool _surgeFired;

		private bool _surgeActive;

		private bool _deathThroes;

		private float _nextCleaveTime;

		private float _nextMinionTime;

		private float _nextWetTouch;

		private float _nextDeathThroesPulse;

		private static GameObject _cachedMinion;

		private static StatusEffect _cachedWetSE;

		private static SE_DraugrWound _woundProto;

		private static readonly HashSet<int> _cleaveWindowLords = new HashSet<int>();

		public static bool IsCleaving(int instanceId)
		{
			return _cleaveWindowLords.Contains(instanceId);
		}

		private void Awake()
		{
			_character = ((Component)this).GetComponent<Character>();
			_humanoid = ((Component)this).GetComponent<Humanoid>();
			_nview = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)_character != (Object)null)
			{
				_baseSpeed = _character.m_speed;
				_baseRunSpeed = _character.m_runSpeed;
			}
			_nextCleaveTime = Time.time + 8f;
			_nextMinionTime = Time.time + 15f;
		}

		private void Update()
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && !((Object)(object)_character == (Object)null) && !_character.IsDead())
			{
				TryPlagueCloud();
				TryUndyingSurge();
				TryDeathThroes();
				TryRottenCleave();
				TrySummonMinions();
				TickWetTouch();
				TickDeathThroesAura();
			}
		}

		private void TryPlagueCloud()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			if (!_cloudFired && !(_character.GetHealth() / _character.GetMaxHealth() > 0.6f))
			{
				_cloudFired = true;
				Vector3 val = ((Component)this).transform.position + Vector3.up * 0.5f;
				FxLibrary.TrySpawnTimed("vfx_blob_attack", val, 3f);
				FxLibrary.TrySpawnTimed("vfx_blob_attack", val, 4f);
				for (int i = 0; i < 6; i++)
				{
					float num = (float)i * 60f;
					Vector3 val2 = Quaternion.Euler(0f, num, 0f) * Vector3.forward * 1.6f;
					FxLibrary.TrySpawnTimed("vfx_blob_attack", val + val2, 3f);
				}
				GameObject val3 = new GameObject("BiomeLords_PlagueCloud");
				val3.transform.position = ((Component)this).transform.position;
				val3.AddComponent<PlagueCloud>().Attacker = _character;
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					((Character)localPlayer).Message((MessageType)2, "$biomelords_plague_cloud", 0, (Sprite)null, false);
				}
				Logger.LogInfo((object)"[BiomeLords] Draugr Lord released a plague cloud.");
			}
		}

		private void TryDeathThroes()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			if (_deathThroes || _character.GetHealth() / _character.GetMaxHealth() > 0.25f)
			{
				return;
			}
			_deathThroes = true;
			_character.m_speed = _baseSpeed * 1.5f;
			_character.m_runSpeed = _baseRunSpeed * 1.5f;
			Vector3 val = ((Component)this).transform.position + Vector3.up * 1f;
			FxLibrary.TrySpawnTimed("vfx_blob_attack", val, 3f);
			FxLibrary.TrySpawn("vfx_corpse_destruction_small", val);
			FxLibrary.TrySpawn("fx_redlightning_burst", val);
			for (int i = 0; i < 8; i++)
			{
				float num = (float)i * 45f;
				Vector3 val2 = Quaternion.Euler(0f, num, 0f) * Vector3.forward * 1.4f;
				FxLibrary.TrySpawn("vfx_HitSparks", val + val2);
			}
			Transform val3 = ((Component)this).transform.Find("BiomeLords_Aura");
			if ((Object)(object)val3 != (Object)null)
			{
				Light component = ((Component)val3).GetComponent<Light>();
				if ((Object)(object)component != (Object)null)
				{
					component.color = new Color(1f, 0.15f, 0.1f);
					component.intensity = 4f;
					component.range = 7f;
				}
			}
			Logger.LogInfo((object)"[BiomeLords] Draugr Lord entered Death Throes.");
		}

		private void TickDeathThroesAura()
		{
			//IL_002e: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (_deathThroes && !(Time.time < _nextDeathThroesPulse))
			{
				_nextDeathThroesPulse = Time.time + 0.6f;
				Vector3 pos = ((Component)this).transform.position + Vector3.up * 1.2f;
				if (Random.value < 0.5f)
				{
					FxLibrary.TrySpawn("fx_redlightning_burst", pos);
				}
			}
		}

		private void TryRottenCleave()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!_surgeActive && !(Time.time < _nextCleaveTime))
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead() && !(Vector3.Distance(((Component)this).transform.position, ((Component)localPlayer).transform.position) > 5f))
				{
					_nextCleaveTime = Time.time + 30f;
					((MonoBehaviour)this).StartCoroutine(CleaveRoutine());
				}
			}
		}

		private IEnumerator CleaveRoutine()
		{
			_character.m_speed = 0f;
			_character.m_runSpeed = 0f;
			Vector3 pos = ((Component)this).transform.position + Vector3.up * 1f;
			FxLibrary.TrySpawn("fx_GP_Activation", pos);
			yield return (object)new WaitForSeconds(1f);
			int cleaveId = ((Object)_character).GetInstanceID();
			_cleaveWindowLords.Add(cleaveId);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)_humanoid != (Object)null && (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead())
			{
				Vector3 val = ((Component)localPlayer).transform.position - ((Component)this).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
				{
					((Component)this).transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized);
				}
				((Character)_humanoid).StartAttack((Character)(object)localPlayer, false);
			}
			yield return (object)new WaitForSeconds(0.4f);
			Vector3 pos2 = ((Component)this).transform.position + ((Component)this).transform.forward * 1.5f + Vector3.up * 1.2f;
			FxLibrary.TrySpawnFirst(new string[4] { "vfx_cut", "vfx_swing_sledge", "vfx_player_hit_blood", "vfx_HitSparks" }, pos2);
			yield return (object)new WaitForSeconds(0.4f);
			_cleaveWindowLords.Remove(cleaveId);
			float num = (_deathThroes ? 1.5f : 1f);
			_character.m_speed = _baseSpeed * num;
			_character.m_runSpeed = _baseRunSpeed * num;
		}

		public static void ApplyWound(Player p)
		{
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_woundProto == (Object)null)
			{
				_woundProto = ScriptableObject.CreateInstance<SE_DraugrWound>();
				((Object)_woundProto).name = "SE_DraugrWound";
				((StatusEffect)_woundProto).m_name = "$se_draugrwound";
				((StatusEffect)_woundProto).m_ttl = 60f;
				_woundProto.DamagePerTick = 5f;
				_woundProto.TickInterval = 1f;
				ObjectDB instance = ObjectDB.instance;
				if ((Object)(object)instance != (Object)null)
				{
					StatusEffect statusEffect = instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Poison"));
					if ((Object)(object)statusEffect != (Object)null && (Object)(object)statusEffect.m_icon != (Object)null)
					{
						((StatusEffect)_woundProto).m_icon = statusEffect.m_icon;
					}
					else if (instance.m_StatusEffects != null)
					{
						foreach (StatusEffect statusEffect2 in instance.m_StatusEffects)
						{
							if ((Object)(object)statusEffect2 != (Object)null && (Object)(object)statusEffect2.m_icon != (Object)null)
							{
								((StatusEffect)_woundProto).m_icon = statusEffect2.m_icon;
								break;
							}
						}
					}
				}
			}
			((Character)p).GetSEMan().AddStatusEffect((StatusEffect)(object)_woundProto, true, 0, 0f, (short)(-1));
			FxLibrary.TrySpawnFirst(new string[3] { "vfx_BloodHit", "vfx_player_hit_blood", "vfx_HitSparks" }, ((Component)p).transform.position + Vector3.up * 1f);
		}

		private void TryUndyingSurge()
		{
			if (!_surgeFired && !(_character.GetHealth() / _character.GetMaxHealth() > 0.4f))
			{
				_surgeFired = true;
				_surgeActive = true;
				((MonoBehaviour)this).StartCoroutine(UndyingSurgeRoutine());
			}
		}

		private IEnumerator UndyingSurgeRoutine()
		{
			_character.m_speed = 0f;
			_character.m_runSpeed = 0f;
			Vector3 val = ((Component)this).transform.position + Vector3.up * 1f;
			FxLibrary.TrySpawn("vfx_HealthUpgrade", val);
			FxLibrary.TrySpawnTimed("vfx_Potion_health_medium", val, 4f);
			for (int i = 0; i < 6; i++)
			{
				float num = (float)i * 60f;
				Vector3 val2 = Quaternion.Euler(0f, num, 0f) * Vector3.forward * 1.4f;
				FxLibrary.TrySpawnTimed("vfx_Potion_health_medium", val + val2, 3f);
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, "$biomelords_undying_surge", 0, (Sprite)null, false);
			}
			Logger.LogInfo((object)"[BiomeLords] Draugr Lord triggered Undying Surge.");
			yield return (object)new WaitForSeconds(1.5f);
			int num2 = 0;
			float num3 = 3600f;
			Vector3 position = ((Component)this).transform.position;
			List<Character> allCharacters = Character.GetAllCharacters();
			for (int j = 0; j < allCharacters.Count; j++)
			{
				Character val3 = allCharacters[j];
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)_character) && !val3.IsDead() && !val3.IsPlayer())
				{
					Vector3 val4 = ((Component)val3).transform.position - position;
					if (!(((Vector3)(ref val4)).sqrMagnitude > num3))
					{
						FxLibrary.TrySpawn("vfx_HitSparks", ((Component)val3).transform.position + Vector3.up * 1f);
						float num4 = val3.GetMaxHealth() * 100f + 10000f;
						HitData val5 = new HitData();
						val5.m_damage.m_blunt = num4;
						val5.m_damage.m_slash = num4;
						val5.m_damage.m_pierce = num4;
						val5.m_damage.m_fire = num4;
						val5.m_hitType = (HitType)1;
						val5.m_point = ((Component)val3).transform.position;
						val3.Damage(val5);
						num2++;
					}
				}
			}
			if (num2 > 0)
			{
				_character.Heal((float)num2 * 500f, true);
				Logger.LogInfo((object)$"[BiomeLords] Draugr Lord Undying Surge drained {num2} creature(s).");
			}
			else
			{
				Player localPlayer2 = Player.m_localPlayer;
				if (localPlayer2 != null)
				{
					((Character)localPlayer2).Message((MessageType)2, "$biomelords_undying_surge_fail", 0, (Sprite)null, false);
				}
				Logger.LogInfo((object)"[BiomeLords] Draugr Lord Undying Surge found no prey — failed.");
			}
			yield return (object)new WaitForSeconds(1.5f);
			float num5 = (_deathThroes ? 1.5f : 1f);
			_character.m_speed = _baseSpeed * num5;
			_character.m_runSpeed = _baseRunSpeed * num5;
			_surgeActive = false;
		}

		private void TrySummonMinions()
		{
			if (!_surgeActive && !(Time.time < _nextMinionTime))
			{
				if (CountNearbyMinions() >= 3)
				{
					_nextMinionTime = Time.time + 15f;
					return;
				}
				DoSpawnMinions();
				_nextMinionTime = Time.time + 60f;
			}
		}

		private void DoSpawnMinions()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			EnsurePrefabs();
			if (!((Object)(object)_cachedMinion == (Object)null))
			{
				int num = CountNearbyMinions();
				int num2 = Math.Min(2, 3 - num);
				for (int i = 0; i < num2; i++)
				{
					float num3 = (float)i * (360f / (float)Math.Max(1, num2)) + Random.Range(-25f, 25f);
					Vector3 val = Quaternion.Euler(0f, num3, 0f) * Vector3.forward;
					Vector3 val2 = ((Component)this).transform.position + val * 3.5f + Vector3.up * 0.2f;
					Object.Instantiate<GameObject>(_cachedMinion, val2, Quaternion.LookRotation(-val));
					FxLibrary.TrySpawn("vfx_spawn", val2);
				}
			}
		}

		private void TickWetTouch()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (!_deathThroes || Time.time < _nextWetTouch)
			{
				return;
			}
			_nextWetTouch = Time.time + 2f;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				return;
			}
			Vector3 val = ((Component)localPlayer).transform.position - ((Component)this).transform.position;
			if (!(((Vector3)(ref val)).sqrMagnitude > 9f))
			{
				if ((Object)(object)_cachedWetSE == (Object)null)
				{
					ObjectDB instance = ObjectDB.instance;
					_cachedWetSE = ((instance != null) ? instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Wet")) : null);
				}
				if ((Object)(object)_cachedWetSE != (Object)null)
				{
					((Character)localPlayer).GetSEMan().AddStatusEffect(_cachedWetSE, true, 0, 0f, (short)(-1));
				}
			}
		}

		private int CountNearbyMinions()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			Vector3 position = ((Component)this).transform.position;
			float num2 = 144f;
			List<Character> allCharacters = Character.GetAllCharacters();
			for (int i = 0; i < allCharacters.Count; i++)
			{
				Character val = allCharacters[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)_character) && !val.IsDead())
				{
					Vector3 val2 = ((Component)val).transform.position - position;
					if (!(((Vector3)(ref val2)).sqrMagnitude > num2) && ((Object)((Component)val).gameObject).name.StartsWith("Draugr"))
					{
						num++;
					}
				}
			}
			return num;
		}

		private static void EnsurePrefabs()
		{
			if ((Object)(object)_cachedMinion == (Object)null)
			{
				_cachedMinion = PrefabManager.Instance.GetPrefab("Draugr");
			}
		}
	}
	public class FallerValkyrieLordBrain : MonoBehaviour
	{
		private const float AbilityTellDelay = 0.5f;

		private const float DiveCooldown = 13f;

		private const float DiveRange = 20f;

		private const float DiveRadius = 4f;

		private const float DiveHpThreshold = 0.8f;

		private const float DiveAscend = 0.6f;

		private const float DiveDescend = 0.5f;

		private const float DiveSkyHeight = 10f;

		private const float DivePushForce = 70f;

		private const float GustCooldown = 16f;

		private const float GustTriggerRange = 7f;

		private const float GustRadius = 6f;

		private const float GustPushForce = 50f;

		private const float GustTelegraph = 0.4f;

		private const float HarvestCooldown = 30f;

		private const float HarvestTriggerRange = 12f;

		private const float HarvestRadius = 10f;

		private const float HarvestDuration = 6f;

		private const float HarvestTickInterval = 0.5f;

		private const float HarvestDrainPerTick = 6f;

		private const float HarvestArmThreshold = 0.3f;

		private const float HarvestDisarmThreshold = 0.5f;

		private const float RageHpFraction = 0.3f;

		private const float RageSpeedFactor = 1.5f;

		private Character _character;

		private ZNetView _nview;

		private MonsterAI _monsterAI;

		private float _baseSpeed;

		private float _baseRunSpeed;

		private bool _raging;

		private bool _inSpecial;

		private bool _harvestArmed;

		private float _nextDiveTime;

		private float _nextGustTime;

		private float _nextHarvestTime;

		private float _nextRagePulse;

		private void Awake()
		{
			_character = ((Component)this).GetComponent<Character>();
			_nview = ((Component)this).GetComponent<ZNetView>();
			_monsterAI = ((Component)this).GetComponent<MonsterAI>();
			if ((Object)(object)_character != (Object)null)
			{
				_baseSpeed = _character.m_speed;
				_baseRunSpeed = _character.m_runSpeed;
			}
			_nextDiveTime = Time.time + 8f;
			_nextGustTime = Time.time + 6f;
			_nextHarvestTime = Time.time + 12f;
		}

		private void Update()
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && !((Object)(object)_character == (Object)null) && !_character.IsDead())
			{
				TryRage();
				UpdateHarvestArming();
				TryDiveBombSlam();
				TryWindGustKnockback();
				TrySoulHarvest();
				TickRageAura();
			}
		}

		private float HealthFrac()
		{
			float maxHealth = _character.GetMaxHealth();
			if (!(maxHealth > 0f))
			{
				return 1f;
			}
			return _character.GetHealth() / maxHealth;
		}

		private void SpawnAbilityTell()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 pos = ((Component)this).transform.position + Vector3.up * 1.5f;
			FxLibrary.TrySpawn("fx_fallenvalkyrie_alert", pos);
			FxLibrary.TrySpawn("fx_fallenvalkyrie_taunt", ((Component)this).transform.position);
			FxLibrary.TrySpawn("fx_himminafl_aoe", pos);
		}

		private void TryRage()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if (_raging || HealthFrac() > 0.3f)
			{
				return;
			}
			_raging = true;
			_character.m_speed = _baseSpeed * 1.5f;
			_character.m_runSpeed = _baseRunSpeed * 1.5f;
			Transform val = ((Component)this).transform.Find("BiomeLords_Aura");
			if ((Object)(object)val != (Object)null)
			{
				Light component = ((Component)val).GetComponent<Light>();
				if ((Object)(object)component != (Object)null)
				{
					component.color = new Color(1f, 0.95f, 0.75f);
					component.intensity = 5f;
					component.range = 8.5f;
				}
			}
			Vector3 pos = ((Component)this).transform.position + Vector3.up * 1.2f;
			FxLibrary.TrySpawn("fx_fallenvalkyrie_screech", pos);
			FxLibrary.TrySpawn("fx_himminafl_aoe", pos);
			FxLibrary.TrySpawn("vfx_corpse_destruction_small", pos);
			FxLibrary.TrySpawn("fx_redlightning_burst", pos);
			Logger.LogInfo((object)"[BiomeLords] Fallen Valkyrie Lord entered Rage.");
		}

		private void UpdateHarvestArming()
		{
			float num = HealthFrac();
			if (num < 0.3f)
			{
				_harvestArmed = true;
			}
			else if (num > 0.5f)
			{
				_harvestArmed = false;
			}
		}

		private void TryDiveBombSlam()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!_inSpecial && !(HealthFrac() >= 0.8f) && !(Time.time < _nextDiveTime))
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead() && !(Vector3.Distance(((Component)this).transform.position, ((Component)localPlayer).transform.position) > 20f))
				{
					_nextDiveTime = Time.time + (_raging ? 7.8f : 13f);
					((MonoBehaviour)this).StartCoroutine(DiveBombSlamRoutine(((Component)localPlayer).transform.position));
				}
			}
		}

		private IEnumerator DiveBombSlamRoutine(Vector3 targetPos)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			_inSpecial = true;
			if ((Object)(object)_monsterAI != (Object)null)
			{
				((Behaviour)_monsterAI).enabled = false;
			}
			SpawnAbilityTell();
			yield return (object)new WaitForSeconds(0.5f);
			_character.TakeOff();
			Vector3 skyPos = targetPos + Vector3.up * 10f;
			Vector3 startPos = ((Component)this).transform.position;
			float t = 0f;
			while (t < 0.6f)
			{
				float num = t / 0.6f;
				((Component)this).transform.position = Vector3.Lerp(startPos, skyPos, num);
				FxLibrary.TrySpawn("fx_valkyrie_flapwing", ((Component)this).transform.position);
				t += Time.deltaTime;
				yield return null;
			}
			((Component)this).transform.position = skyPos;
			((Component)this).transform.rotation = Quaternion.LookRotation(Vector3.down);
			FxLibrary.TrySpawn("fx_redlightning_burst", targetPos);
			for (int i = 0; i < 6; i++)
			{
				float num2 = (float)i * 60f;
				Vector3 val = Quaternion.Euler(0f, num2, 0f) * Vector3.forward * 1.2f;
				FxLibrary.TrySpawn("vfx_HitSparks", targetPos + val);
			}
			yield return (object)new WaitForSeconds(0.3f);
			t = 0f;
			while (t < 0.5f)
			{
				float num3 = t / 0.5f;
				((Component)this).transform.position = Vector3.Lerp(skyPos, targetPos, num3);
				t += Time.deltaTime;
				yield return null;
			}
			((Component)this).transform.position = targetPos;
			FxLibrary.TrySpawn("fx_fallenvalkyrie_attack_claw", targetPos);
			FxLibrary.TrySpawn("fx_himminafl_aoe", targetPos);
			FxLibrary.TrySpawn("vfx_corpse_destruction_small", targetPos);
			FxLibrary.TrySpawnTimed("vfx_meteor_explosion", targetPos, 3f);
			float num4 = 16f;
			List<Character> allCharacters = Character.GetAllCharacters();
			for (int j = 0; j < allCharacters.Count; j++)
			{
				Character obj = allCharacters[j];
				Player val2 = (Player)(object)((obj is Player) ? obj : null);
				if (val2 != null && !((Character)val2).IsDead())
				{
					Vector3 val3 = ((Component)val2).transform.position - targetPos;