Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BiomeLords v0.6.0
BiomeLords.dll
Decompiled 6 hours ago
The result has been truncated due to the large size, download it to view full contents!
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