Decompiled source of BiomeLords v0.6.0

BiomeLords.dll

Decompiled 6 hours 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.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 Microsoft.CodeAnalysis;
using UnityEngine;
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+03cc5aea47c17c0d9e1df4356b602e888acbc7b1")]
[assembly: AssemblyProduct("BiomeLords")]
[assembly: AssemblyTitle("BiomeLords")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BiomeLords
{
	[BepInPlugin("com.taeguk.BiomeLords", "BiomeLords", "0.6.0")]
	[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.0";

		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.0", 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 BaseHeight = 4;

		private static int _seHash;

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

		public static int ExtraRows => Mathf.Max(0, LordConfig.FallerValkyrieExtraRows?.Value ?? 0);

		public static int ExpandedHeight => 4 + ExtraRows;

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

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

		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.GetName() == "Inventory")
			{
				return inv.GetWidth() == 8;
			}
			return false;
		}

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

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

		public static void Collapse(Player p)
		{
			SetHeight(p, 4);
		}

		private static void SetHeight(Player p, int target)
		{
			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);
			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_ForestsEmbrace",
				new string[4] { "Sapling_Birch", "Sapling_Beech", "BeechSeeds", "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" }
			},
			{
				"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_ForestSitting",
				new string[3] { "Sheltered", "Shelter", "Rested" }
			}
		};

		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
				}
			}
		};

		private static readonly DamageProfile[] ByTier = new DamageProfile[8]
		{
			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
			}
		};

		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 <= 7)
			{
				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 }
		};

		public static float HpFor(string lordId, int tier)
		{
			if (!string.IsNullOrEmpty(lordId) && BaseHp.TryGetValue(lordId, out var value))
			{
				return value;
			}
			return TierTable.HpFor(tier);
		}
	}
	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 }
		};

		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 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 TierTable
	{
		public const int MinTier = 1;

		public const int MaxTier = 7;

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

		public static int Clamp(int tier)
		{
			if (tier >= 1)
			{
				if (tier <= 7)
				{
					return tier;
				}
				return 7;
			}
			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);
				}
				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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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);
			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);
			}
			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);
				}
				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);
				}
			}
		}

		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;
					if (!(((Vector3)(ref val3)).sqrMagnitude > num4))
					{
						HitData val4 = new HitData();
						val4.m_pushForce = 70f;
						val4.m_point = targetPos;
						val4.m_dir = ((((Vector3)(ref val3)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val3)).normalized : Vector3.up);
						val4.m_hitType = (HitType)1;
						val4.m_blockable = true;
						val4.m_dodgeable = true;
						val4.SetAttacker(_character);
						((Character)val2).Damage(val4);
					}
				}
			}
			_character.Land();
			if ((Object)(object)_monsterAI != (Object)null)
			{
				((Behaviour)_monsterAI).enabled = true;
			}
			_inSpecial = false;
		}

		private void TryWindGustKnockback()
		{
			//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)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (_inSpecial || Time.time < _nextGustTime)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead())
			{
				Vector3 val = ((Component)localPlayer).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 49f))
				{
					_nextGustTime = Time.time + (_raging ? 9.6f : 16f);
					((MonoBehaviour)this).StartCoroutine(WindGustKnockbackRoutine());
				}
			}
		}

		private IEnumerator WindGustKnockbackRoutine()
		{
			_inSpecial = true;
			SpawnAbilityTell();
			yield return (object)new WaitForSeconds(0.5f);
			Vector3 center = ((Component)this).transform.position;
			FxLibrary.TrySpawn("fx_fallenvalkyrie_attack_spin_charge", center);
			FxLibrary.TrySpawn("fx_valkyrie_flapwing", center + Vector3.up * 1f);
			for (int i = 0; i < 8; i++)
			{
				float num = (float)i * 45f;
				Vector3 val = Quaternion.Euler(0f, num, 0f) * Vector3.forward * (2.5f - (float)i * 0.1f);
				FxLibrary.TrySpawn("vfx_HitSparks", center + val + Vector3.up * 1f);
			}
			FxLibrary.TrySpawn("fx_himminafl_aoe", center);
			yield return (object)new WaitForSeconds(0.4f);
			FxLibrary.TrySpawn("fx_fallenvalkyrie_attack_spin_release", center + Vector3.up * 1f);
			FxLibrary.TrySpawn("fx_redlightning_burst", center + Vector3.up * 1f);
			for (int j = 0; j < 12; j++)
			{
				float num2 = (float)j * 30f;
				Vector3 val2 = Quaternion.Euler(0f, num2, 0f) * Vector3.forward * 6f;
				FxLibrary.TrySpawn("vfx_HitSparks", center + val2 + Vector3.up * 0.5f);
			}
			float num3 = 36f;
			List<Character> allCharacters = Character.GetAllCharacters();
			for (int k = 0; k < allCharacters.Count; k++)
			{
				Character obj = allCharacters[k];
				Player val3 = (Player)(object)((obj is Player) ? obj : null);
				if (val3 != null && !((Character)val3).IsDead())
				{
					Vector3 val4 = ((Component)val3).transform.position - center;
					if (!(((Vector3)(ref val4)).sqrMagnitude > num3))
					{
						HitData val5 = new HitData();
						val5.m_pushForce = 50f;
						val5.m_point = ((Component)val3).transform.position;
						val5.m_dir = ((((Vector3)(ref val4)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val4)).normalized : Vector3.forward);
						val5.m_hitType = (HitType)1;
						val5.m_blockable = true;
						val5.m_dodgeable = true;
						val5.SetAttacker(_character);
						((Character)val3).Damage(val5);
					}
				}
			}
			_inSpecial = false;
		}

		private void TrySoulHarvest()
		{
			//IL_003e: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			if (_inSpecial || !_harvestArmed || Time.time < _nextHarvestTime)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead())
			{
				Vector3 val = ((Component)localPlayer).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 144f))
				{
					_nextHarvestTime = Time.time + (_raging ? 18f : 30f);
					((MonoBehaviour)this).StartCoroutine(SoulHarvestRoutine());
				}
			}
		}

		private IEnumerator SoulHarvestRoutine()
		{
			_inSpecial = true;
			if ((Object)(object)_monsterAI != (Object)null)
			{
				((Behaviour)_monsterAI).enabled = false;
			}
			SpawnAbilityTell();
			yield return (object)new WaitForSeconds(0.5f);
			_character.TakeOff();
			FxLibrary.TrySpawn("fx_fallenvalkyrie_attack_spit_charge", ((Component)this).transform.position);
			FxLibrary.TrySpawn("fx_himminafl_aoe", ((Component)this).transform.position);
			float elapsed = 0f;
			float nextTick = 0f;
			float nextFlap = 0f;
			while (elapsed < 6f)
			{
				_character.SetMoveDir(Vector3.up * 0.15f);
				if (elapsed >= nextFlap)
				{
					nextFlap = elapsed + 0.8f;
					FxLibrary.TrySpawn("fx_valkyrie_flapwing", ((Component)this).transform.position);
				}
				if (elapsed >= nextTick)
				{
					nextTick = elapsed + 0.5f;
					DrainTick();
				}
				elapsed += Time.deltaTime;
				yield return null;
			}
			_character.Land();
			if ((Object)(object)_monsterAI != (Object)null)
			{
				((Behaviour)_monsterAI).enabled = true;
			}
			_inSpecial = false;
		}

		private void DrainTick()
		{
			//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_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)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)this).transform.position;
			float num = 100f;
			List<Character> allCharacters = Character.GetAllCharacters();
			float num2 = 0f;
			for (int i = 0; i < allCharacters.Count; i++)
			{
				Character obj = allCharacters[i];
				Player val = (Player)(object)((obj is Player) ? obj : null);
				if (val != null && !((Character)val).IsDead())
				{
					Vector3 val2 = ((Component)val).transform.position - position;
					if (!(((Vector3)(ref val2)).sqrMagnitude > num))
					{
						HitData val3 = new HitData();
						val3.m_damage.m_spirit = 6f;
						val3.m_point = ((Component)val).transform.position;
						val3.m_dir = ((Vector3)(ref val2)).normalized;
						val3.m_hitType = (HitType)2;
						val3.SetAttacker(_character);
						((Character)val).Damage(val3);
						SpawnTether(position, ((Component)val).transform.position + Vector3.up * 1f);
						num2 += 6f;
					}
				}
			}
			if (num2 > 0f)
			{
				_character.Heal(num2, true);
			}
		}

		private void SpawnTether(Vector3 from, Vector3 to)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			FxLibrary.TrySpawn("fx_fallenvalkyrie_attack_spit_projectile", from);
			for (int i = 0; i <= 5; i++)
			{
				float num = (float)i / 5f;
				Vector3 pos = Vector3.Lerp(from, to, num);
				FxLibrary.TrySpawn("vfx_HitSparks", pos);
			}
			FxLibrary.TrySpawn("fx_fallenvalkyrie_attack_spit_projectile_impact", to);
		}

		private void TickRageAura()
		{
			//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_004d: 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_0070: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			if (_raging && !(Time.time < _nextRagePulse))
			{
				_nextRagePulse = Time.time + 0.4f;
				Vector3 val = ((Component)this).transform.position + Vector3.up * 1f;
				FxLibrary.TrySpawn("vfx_HitSparks", val);
				if (Random.value < 0.5f)
				{
					FxLibrary.TrySpawn("fx_himminafl_aoe", val + Vector3.up * 0.3f);
				}
			}
		}
	}
	public class FenringLordBrain : MonoBehaviour
	{
		private const float BatSummonCooldown = 60f;

		private const int MaxNearbyBats = 4;

		private const int BatsPerSummon = 2;

		private const float BatDetectRadius = 16f;

		private const string BatPrefab = "Bat";

		private const float VampHpTrigger = 0.8f;

		private const float VampCooldown = 40f;

		public const float VampHealFraction = 0.8f;

		private const float VampDuration = 60f;

		private const float InvisHpTrigger = 0.6f;

		private const float InvisCooldown = 60f;

		private const float InvisDuration = 12f;

		private const float InvisPreDelay = 1f;

		private const float FrenzyHpFraction = 0.3f;

		private const float FrenzySpeedFactor = 1.5f;

		private const float FrenzyJumpFactor = 0.2f;

		private const float FrenzyAttackFactor = 0.3f;

		private Character _character;

		private ZNetView _nview;

		private MonsterAI _monsterAI;

		private float _baseSpeed;

		private float _baseRunSpeed;

		private float _baseJumpInterval;

		private float _baseAttackInterval;

		private bool _frenzied;

		private float _nextBatSummonTime;

		private float _nextVampTime;

		private float _vampEndTime = -1f;

		private float _nextInvisTime;

		private float _nextFrenzyPulse;

		private Light _auraLight;

		private Color _auraOrigColor;

		private float _auraOrigIntensity;

		private float _auraOrigRange;

		private static GameObject _cachedBat;

		private Animator _animator;

		public bool IsVampActive => Time.time < _vampEndTime;

		private void Awake()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			_character = ((Component)this).GetComponent<Character>();
			_nview = ((Component)this).GetComponent<ZNetView>();
			_monsterAI = ((Component)this).GetComponent<MonsterAI>();
			_animator = ((Component)this).GetComponentInChildren<Animator>();
			if ((Object)(object)_character != (Object)null)
			{
				_baseSpeed = _character.m_speed;
				_baseRunSpeed = _character.m_runSpeed;
			}
			if ((Object)(object)_monsterAI != (Object)null)
			{
				_baseJumpInterval = ((BaseAI)_monsterAI).m_jumpInterval;
				_baseAttackInterval = _monsterAI.m_minAttackInterval;
			}
			Transform val = ((Component)this).transform.Find("BiomeLords_Aura");
			if ((Object)(object)val != (Object)null)
			{
				_auraLight = ((Component)val).GetComponent<Light>();
				if ((Object)(object)_auraLight != (Object)null)
				{
					_auraOrigColor = _auraLight.color;
					_auraOrigIntensity = _auraLight.intensity;
					_auraOrigRange = _auraLight.range;
				}
			}
			_nextBatSummonTime = Time.time + 15f;
			_nextVampTime = Time.time + 10f;
			_nextInvisTime = Time.time + 20f;
		}

		private void Update()
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && !((Object)(object)_character == (Object)null) && !_character.IsDead())
			{
				TryFrenzy();
				TryBatSummon();
				TryVampiricStrike();
				TryInvisibility();
				TickFrenzyAura();
			}
		}

		private void TryFrenzy()
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			if (!_frenzied && !(_character.GetHealth() / _character.GetMaxHealth() > 0.3f))
			{
				_frenzied = true;
				_character.m_speed = _baseSpeed * 1.5f;
				_character.m_runSpeed = _baseRunSpeed * 1.5f;
				if ((Object)(object)_monsterAI != (Object)null)
				{
					((BaseAI)_monsterAI).m_jumpInterval = _baseJumpInterval * 0.2f;
					_monsterAI.m_minAttackInterval = _baseAttackInterval * 0.3f;
				}
				ApplyFrenzyAttackBias();
				UpdateAura();
				Vector3 val = ((Component)this).transform.position + Vector3.up * 1f;
				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);
				}
				Logger.LogInfo((object)"[BiomeLords] Fenring Lord entered Blood Frenzy.");
			}
		}

		private void TryBatSummon()
		{
			if (!(Time.time < _nextBatSummonTime))
			{
				if (CountNearbyBats() >= 4)
				{
					_nextBatSummonTime = Time.time + 15f;
					return;
				}
				PlayTaunt();
				SpawnBats(2);
				_nextBatSummonTime = Time.time + 60f;
			}
		}

		private void TryVampiricStrike()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_007f: 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)
			if (!_frenzied && !IsVampActive && !(Time.time < _nextVampTime) && !(_character.GetHealth() / _character.GetMaxHealth() > 0.8f))
			{
				_vampEndTime = Time.time + 60f;
				_nextVampTime = _vampEndTime + 40f;
				Vector3 pos = ((Component)this).transform.position + Vector3.up * 1.5f;
				FxLibrary.TrySpawn("fx_GP_Activation", pos);
				UpdateAura();
				((MonoBehaviour)this).StartCoroutine(VampExpireCoroutine());
				Logger.LogInfo((object)"[BiomeLords] Fenring Lord activated Vampiric Strike.");
			}
		}

		private IEnumerator VampExpireCoroutine()
		{
			yield return (object)new WaitForSeconds(60f);
			UpdateAura();
		}

		private void TryInvisibility()
		{
			//IL_004b: 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)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < _nextInvisTime || _character.GetHealth() / _character.GetMaxHealth() > 0.6f)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead())
			{
				Vector3 val = ((Component)localPlayer).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 400f))
				{
					_nextInvisTime = Time.time + 60f;
					((MonoBehaviour)this).StartCoroutine(InvisibilityRoutine());
				}
			}
		}

		private IEnumerator InvisibilityRoutine()
		{
			PlayTaunt();
			SpawnBats(2);
			Vector3 pos = ((Component)this).transform.position + Vector3.up * 1f;
			FxLibrary.TrySpawn("vfx_mist_puff", pos);
			FxLibrary.TrySpawn("vfx_spawn", pos);
			yield return (object)new WaitForSeconds(1f);
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(false);
			List<Renderer> hidden = new List<Renderer>(componentsInChildren.Length);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if (!(val is ParticleSystemRenderer))
				{
					val.enabled = false;
					hidden.Add(val);
				}
			}
			yield return (object)new WaitForSeconds(12f);
			foreach (Renderer item in hidden)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.enabled = true;
				}
			}
			FxLibrary.TrySpawn("vfx_spawn", ((Component)this).transform.position + Vector3.up * 1f);
		}

		private void TickFrenzyAura()
		{
			//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_004d: 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_0070: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			if (_frenzied && !(Time.time < _nextFrenzyPulse))
			{
				_nextFrenzyPulse = Time.time + 0.5f;
				Vector3 val = ((Component)this).transform.position + Vector3.up * 1f;
				FxLibrary.TrySpawn("vfx_HitSparks", val);
				if (Random.value < 0.4f)
				{
					FxLibrary.TrySpawn("fx_redlightning_burst", val + Vector3.up * 0.3f);
				}
			}
		}

		private void ApplyFrenzyAttackBias()
		{
			Humanoid component = ((Component)this).GetComponent<Humanoid>();
			if (!((Object)(object)component == (Object)null) && !(BiasArray(component.m_defaultItems) | BiasArray(component.m_randomWeapon)))
			{
				Logger.LogWarning((object)"[BiomeLords] Fenring Lord frenzy: no jump-attack item found — attack bias not applied. Check the attack-animation names in the log.");
			}
		}

		private static bo