using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using SoftReferenceableAssets; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Rootbound Witch")] [assembly: AssemblyDescription("A restriction-led moss witch transformation for Valheim.")] [assembly: AssemblyCompany("ADARC")] [assembly: AssemblyProduct("Rootbound Witch")] [assembly: ComVisible(false)] [assembly: Guid("6e7899d2-9912-4d93-956b-6ead18e4fd18")] [assembly: AssemblyFileVersion("0.4.11.0")] [assembly: AssemblyVersion("0.4.11.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 ADARC.RootboundWitch { internal static class BogWitchBackGrowth { private static readonly string[] GrowthTokens = new string[8] { "branch", "root", "twig", "bark", "vine", "growth", "wood", "stick" }; private static GameObject _upperTemplate; private static GameObject _lowerTemplate; private static GameObject _upperInstance; private static GameObject _lowerInstance; private static Player _owner; private static Bounds _combinedBounds; private static Material[] _ordinaryMaterials; private static Material[] _permafrostMaterials; private static float _nextResolveAt; private static bool _loggedFailure; private static bool _materialStateKnown; private static bool _lastPermafrost; internal static void Prepare() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Expected O, but got Unknown //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_upperTemplate) || Time.realtimeSinceStartup < _nextResolveAt) { return; } _nextResolveAt = Time.realtimeSinceStartup + 5f; GameObject val = RootboundContent.FindPrefab("BogWitch"); if (!Object.op_Implicit((Object)(object)val)) { if (!_loggedFailure) { RootboundWitchPlugin.Log.LogWarning((object)"Bog Witch back-growth experiment is waiting for the live BogWitch prefab."); _loggedFailure = true; } return; } try { List list = new List(); List list2 = new List(); List list3 = new List(); List list4 = new List(); Matrix4x4 worldToLocalMatrix = val.transform.worldToLocalMatrix; Renderer[] componentsInChildren = val.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { Mesh val3 = SourceMesh(val2); if (!Object.op_Implicit((Object)(object)val3) || val3.subMeshCount <= 0) { continue; } Material[] array = (Material[])(((object)val2.sharedMaterials) ?? ((object)new Material[0])); string text = RelativePath(((Component)val2).transform, val.transform); bool flag = ContainsGrowthToken(((Object)val2).name); list4.Add(text + " :: " + string.Join(", ", from material in array where Object.op_Implicit((Object)(object)material) select ((Object)material).name)); for (int num = 0; num < val3.subMeshCount; num++) { Material val4 = ((array.Length == 0) ? null : array[Math.Min(num, array.Length - 1)]); string text2 = ((Object.op_Implicit((Object)(object)val4) && Object.op_Implicit((Object)(object)val4.mainTexture)) ? ((Object)val4.mainTexture).name : string.Empty); string identity = (Object.op_Implicit((Object)(object)val4) ? ((Object)val4).name : string.Empty) + " " + text2; if (flag || ContainsGrowthToken(identity)) { CombineInstance item = default(CombineInstance); ((CombineInstance)(ref item)).mesh = val3; ((CombineInstance)(ref item)).subMeshIndex = num; ((CombineInstance)(ref item)).transform = worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix; list.Add(item); list2.Add(val4); list3.Add(text + "[" + num + "] / " + (Object.op_Implicit((Object)(object)val4) ? ((Object)val4).name : "")); } } } if (list.Count == 0) { if (!_loggedFailure) { RootboundWitchPlugin.Log.LogWarning((object)("Bog Witch branch extraction found no named growth geometry. Live renderer inventory: " + string.Join(" | ", list4))); _loggedFailure = true; } return; } Mesh val5 = new Mesh { name = "Rootbound_BogWitchBranchCrownMesh", indexFormat = (IndexFormat)1 }; val5.CombineMeshes(list.ToArray(), false, true, false); val5.RecalculateBounds(); _combinedBounds = val5.bounds; Bounds bounds = val5.bounds; float y = ((Bounds)(ref bounds)).min.y; bounds = val5.bounds; float splitY = y + ((Bounds)(ref bounds)).size.y * 0.38f; Mesh mesh = SplitMesh(val5, splitY, lower: false); Mesh mesh2 = SplitMesh(val5, splitY, lower: true); _ordinaryMaterials = list2.ToArray(); _permafrostMaterials = PermafrostVisuals.BuildExternalWhiteMaterials(_ordinaryMaterials); _upperTemplate = CreateTemplate("Rootbound_BogWitchBranchCrownUpperTemplate", mesh); _lowerTemplate = CreateTemplate("Rootbound_BogWitchBranchCrownLowerTemplate", mesh2); _loggedFailure = false; RootboundWitchPlugin.Log.LogInfo((object)("Bog Witch back-growth extracted " + list.Count + " exact branch submeshes: " + string.Join(" | ", list3))); } catch (Exception ex) { if (!_loggedFailure) { RootboundWitchPlugin.Log.LogWarning((object)("Bog Witch branch-only extraction failed safely; gameplay content remains intact: " + ex.GetBaseException().Message)); _loggedFailure = true; } } } internal static void Update(Player player, bool active) { if (!RootboundWitchPlugin.EnableBogWitchBackGrowth.Value || !active || (Object)(object)player == (Object)null) { ClearInstance(); return; } if (!Object.op_Implicit((Object)(object)_upperTemplate) || !Object.op_Implicit((Object)(object)_lowerTemplate)) { Prepare(); if (!Object.op_Implicit((Object)(object)_upperTemplate) || !Object.op_Implicit((Object)(object)_lowerTemplate)) { return; } } if (!Object.op_Implicit((Object)(object)_upperInstance) || !Object.op_Implicit((Object)(object)_lowerInstance) || (Object)(object)_owner != (Object)(object)player) { ClearInstance(); _owner = player; _upperInstance = CreateInstance(_upperTemplate, "Rootbound_BogWitchBranchCrownUpper", player); _lowerInstance = CreateInstance(_lowerTemplate, "Rootbound_BogWitchBranchCrownLower", player); AttachToAnimatedTorso(_upperInstance, player, lower: false); AttachToAnimatedTorso(_lowerInstance, player, lower: true); _upperInstance.SetActive(true); _lowerInstance.SetActive(true); _materialStateKnown = false; } bool flag = RootboundState.IsPermafrost(player); if (!_materialStateKnown || _lastPermafrost != flag) { Material[] materials = (flag ? _permafrostMaterials : _ordinaryMaterials); ApplyMaterials(_upperInstance, materials); ApplyMaterials(_lowerInstance, materials); _lastPermafrost = flag; _materialStateKnown = true; } } internal static void Clear() { ClearInstance(); if (Object.op_Implicit((Object)(object)_upperTemplate)) { Object.Destroy((Object)(object)_upperTemplate); } if (Object.op_Implicit((Object)(object)_lowerTemplate)) { Object.Destroy((Object)(object)_lowerTemplate); } _upperTemplate = null; _lowerTemplate = null; _ordinaryMaterials = null; _permafrostMaterials = null; } private static void ClearInstance() { if (Object.op_Implicit((Object)(object)_upperInstance)) { Object.Destroy((Object)(object)_upperInstance); } if (Object.op_Implicit((Object)(object)_lowerInstance)) { Object.Destroy((Object)(object)_lowerInstance); } _upperInstance = null; _lowerInstance = null; _owner = null; _materialStateKnown = false; } private static GameObject CreateInstance(GameObject template, string name, Player player) { GameObject obj = Object.Instantiate(template, ((Component)player).transform, false); ((Object)obj).name = name; ((Object)obj).hideFlags = (HideFlags)52; PositionOnBack(obj); return obj; } private static void PositionOnBack(GameObject crown) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_00fa: Unknown result type (might be due to invalid IL or missing references) Vector3 size = ((Bounds)(ref _combinedBounds)).size; Bounds val = (Bounds)((((Vector3)(ref size)).sqrMagnitude > 0f) ? _combinedBounds : new Bounds(Vector3.zero, Vector3.one)); float num = Mathf.Max(0.5f, RootboundWitchPlugin.BogWitchGrowthWidth.Value); float num2 = Mathf.Max(0.5f, RootboundWitchPlugin.BogWitchGrowthHeight.Value); float num3 = Mathf.Min(num / Mathf.Max(0.05f, ((Bounds)(ref val)).size.x), num2 / Mathf.Max(0.05f, ((Bounds)(ref val)).size.y)); num3 = Mathf.Clamp(num3, 0.05f, 12f); crown.transform.localRotation = Quaternion.identity; crown.transform.localScale = Vector3.one * num3; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(0f, RootboundWitchPlugin.BogWitchGrowthVerticalOffset.Value, RootboundWitchPlugin.BogWitchGrowthBackOffset.Value); crown.transform.localPosition = val2 - ((Bounds)(ref val)).center * num3; } private static void AttachToAnimatedTorso(GameObject crown, Player player, bool lower) { Transform val = (lower ? FindLowerBackAttachment(player) : FindBackAttachment(player)); if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val == (Object)(object)((Component)player).transform) { RootboundWitchPlugin.Log.LogWarning((object)"Bog Witch branch crown found no animated torso anchor; retaining player-root attachment."); return; } crown.transform.SetParent(val, true); RootboundWitchPlugin.Log.LogInfo((object)("Bog Witch branch crown " + (lower ? "lower" : "upper") + " section bound to animated anchor: " + HierarchyPath(val, ((Component)player).transform))); } private static Transform FindLowerBackAttachment(Player player) { //IL_0051: 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) if ((Object)(object)player == (Object)null) { return null; } Animator val = ((IEnumerable)((Component)player).GetComponentsInChildren(true)).FirstOrDefault((Func)((Animator candidate) => Object.op_Implicit((Object)(object)candidate) && candidate.isHuman)); if (Object.op_Implicit((Object)(object)val)) { HumanBodyBones[] array = (HumanBodyBones[])(object)new HumanBodyBones[2] { default(HumanBodyBones), (HumanBodyBones)7 }; foreach (HumanBodyBones val2 in array) { Transform boneTransform = val.GetBoneTransform(val2); if (Object.op_Implicit((Object)(object)boneTransform)) { return boneTransform; } } } Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren(true); string[] array2 = new string[5] { "pelvis", "hips", "hip", "spine1", "spine" }; foreach (string token in array2) { Transform val3 = ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((Transform transform) => Normalize(((Object)transform).name).Contains(token))); if (Object.op_Implicit((Object)(object)val3)) { return val3; } } return ((Component)player).transform; } private static GameObject CreateTemplate(string name, Mesh mesh) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown GameObject val = new GameObject(name); val.SetActive(false); ((Object)val).hideFlags = (HideFlags)61; MeshFilter val2 = val.AddComponent(); MeshRenderer obj = val.AddComponent(); val2.sharedMesh = mesh; ((Renderer)obj).sharedMaterials = _ordinaryMaterials; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)obj).receiveShadows = true; return val; } private static void ApplyMaterials(GameObject instance, Material[] materials) { if (Object.op_Implicit((Object)(object)instance)) { MeshRenderer component = instance.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { ((Renderer)component).sharedMaterials = materials; } } } private static Mesh SplitMesh(Mesh source, float splitY, bool lower) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0049: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown Mesh val = new Mesh { name = ((Object)source).name + (lower ? "_Lower" : "_Upper"), indexFormat = source.indexFormat, vertices = source.vertices, normals = source.normals, tangents = source.tangents, colors32 = source.colors32, uv = source.uv, uv2 = source.uv2, uv3 = source.uv3, uv4 = source.uv4, subMeshCount = source.subMeshCount }; Vector3[] vertices = source.vertices; int num = 0; for (int i = 0; i < source.subMeshCount; i++) { int[] triangles = source.GetTriangles(i); List list = new List(triangles.Length); for (int j = 0; j + 2 < triangles.Length; j += 3) { float num2 = (vertices[triangles[j]].y + vertices[triangles[j + 1]].y + vertices[triangles[j + 2]].y) / 3f; if (lower ? (num2 <= splitY) : (num2 > splitY)) { list.Add(triangles[j]); list.Add(triangles[j + 1]); list.Add(triangles[j + 2]); num++; } } val.SetTriangles(list, i, false); } if (num == 0) { Object.Destroy((Object)(object)val); throw new InvalidOperationException("Bog Witch branch crown split produced an empty " + (lower ? "lower" : "upper") + " section."); } val.RecalculateBounds(); return val; } private static Transform FindBackAttachment(Player player) { //IL_00d1: 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) if ((Object)(object)player == (Object)null) { return null; } string[] obj = new string[5] { "attach_back", "attachback", "back_attach", "attach_backtool", "backtool" }; Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren(true); string[] array = obj; foreach (string target in array) { Transform val = ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((Transform transform) => string.Equals(Normalize(((Object)transform).name), target, StringComparison.OrdinalIgnoreCase))); if (Object.op_Implicit((Object)(object)val)) { return val; } } Animator val2 = ((IEnumerable)((Component)player).GetComponentsInChildren(true)).FirstOrDefault((Func)((Animator candidate) => Object.op_Implicit((Object)(object)candidate) && candidate.isHuman)); if (Object.op_Implicit((Object)(object)val2)) { HumanBodyBones[] array2 = new HumanBodyBones[3]; RuntimeHelpers.InitializeArray(array2, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); HumanBodyBones[] array3 = (HumanBodyBones[])(object)array2; foreach (HumanBodyBones val3 in array3) { Transform boneTransform = val2.GetBoneTransform(val3); if (Object.op_Implicit((Object)(object)boneTransform)) { return boneTransform; } } } return ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((Transform transform) => Normalize(((Object)transform).name).Contains("spine2"))) ?? ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((Transform transform) => Normalize(((Object)transform).name).Contains("spine1"))); } private static string Normalize(string value) { return (value ?? string.Empty).Replace(" ", string.Empty).Replace("-", string.Empty).ToLowerInvariant(); } private static string HierarchyPath(Transform transform, Transform root) { List list = new List(); Transform val = transform; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } private static Mesh SourceMesh(Renderer renderer) { SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if ((Object)(object)val != (Object)null) { return val.sharedMesh; } MeshFilter component = ((Component)renderer).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.sharedMesh; } private static bool ContainsGrowthToken(string identity) { string text = (identity ?? string.Empty).ToLowerInvariant(); return GrowthTokens.Any(text.Contains); } private static string RelativePath(Transform transform, Transform root) { List list = new List(); Transform val = transform; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } } internal static class DraugrRotVisuals { private const string ProjectilePrefabName = "RootboundCrook_DraugrRotProjectile"; private static readonly Color RotDark = new Color(0.006f, 0.022f, 0.01f, 0.1f); private static readonly Color RotLight = new Color(0.045f, 0.115f, 0.038f, 0.26f); private static readonly string[] ColourProperties = new string[3] { "_Color", "_BaseColor", "_TintColor" }; private static GameObject _projectile; internal static void ApplyToAttack(Attack attack) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (attack != null && Object.op_Implicit((Object)(object)attack.m_attackProjectile)) { if (!Object.op_Implicit((Object)(object)_projectile)) { _projectile = PrefabManager.Instance.CreateClonedPrefab("RootboundCrook_DraugrRotProjectile", attack.m_attackProjectile); _projectile.AddComponent(); Recolour(_projectile); PrefabManager.Instance.AddPrefab(new CustomPrefab(_projectile, true)); RootboundWitchPlugin.Log.LogInfo((object)("Rootbound Crook projectile recoloured to the draugr-rot palette from " + ((Object)attack.m_attackProjectile).name + ".")); } attack.m_attackProjectile = _projectile; } } internal static void Recolour(GameObject visual) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)visual)) { return; } ParticleSystem[] componentsInChildren = visual.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { MainModule main = componentsInChildren[i].main; Color rotDark = RotDark; Color rotLight = RotLight; ((MainModule)(ref main)).startColor = new MinMaxGradient(rotDark, rotLight); } Light[] componentsInChildren2 = visual.GetComponentsInChildren(true); foreach (Light obj in componentsInChildren2) { ((Behaviour)obj).enabled = false; obj.intensity = 0f; } Renderer[] componentsInChildren3 = visual.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren3) { Material[] array = ((IEnumerable)val.sharedMaterials).Select((Func)((Material material) => Object.op_Implicit((Object)(object)material) ? new Material(material) : ((Material)null))).ToArray(); Material[] array2 = array; for (int num = 0; num < array2.Length; num++) { Tint(array2[num], val is ParticleSystemRenderer || val is TrailRenderer); } val.sharedMaterials = array; } } private static void Tint(Material material, bool airborne) { //IL_0038: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0059: 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_006a: 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) if (!Object.op_Implicit((Object)(object)material)) { return; } ((Object)material).name = ((Object)material).name + "_DraugrRot"; string[] colourProperties = ColourProperties; foreach (string text in colourProperties) { if (material.HasProperty(text)) { Color color = material.GetColor(text); Color val = Color.Lerp(RotDark, RotLight, Mathf.Clamp01(((Color)(ref color)).grayscale)); val.a = (airborne ? 0.2f : Mathf.Min(0.42f, Mathf.Max(0.22f, color.a * 0.38f))); material.SetColor(text, val); } } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); } material.DisableKeyword("_EMISSION"); if (airborne) { if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 1f); } if (material.HasProperty("_Mode")) { material.SetFloat("_Mode", 3f); } if (material.HasProperty("_SrcBlend")) { material.SetInt("_SrcBlend", 5); } if (material.HasProperty("_DstBlend")) { material.SetInt("_DstBlend", 10); } if (material.HasProperty("_ZWrite")) { material.SetInt("_ZWrite", 0); } material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = 3000; } } } internal sealed class RootboundTriangleProjectile : MonoBehaviour { private static readonly FieldRef Owner = AccessTools.FieldRefAccess("m_owner"); private static readonly FieldRef Velocity = AccessTools.FieldRefAccess("m_vel"); private static readonly FieldRef StartPoint = AccessTools.FieldRefAccess("m_startPoint"); private static int _sequence; private Projectile _projectile; private bool _placed; private void Awake() { _projectile = ((Component)this).GetComponent(); } private void Update() { //IL_006b: 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_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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_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) if (!_placed && !((Object)(object)_projectile == (Object)null) && !((Object)(object)Owner.Invoke(_projectile) == (Object)null) && !(((Vector3)(ref Velocity.Invoke(_projectile))).sqrMagnitude < 0.01f)) { int num = (Interlocked.Increment(ref _sequence) - 1) % 3; Vector3 val = Vector3.ProjectOnPlane(((Vector3)(ref Velocity.Invoke(_projectile))).normalized, Vector3.up); Vector3 normalized = ((Vector3)(ref val)).normalized; if (((Vector3)(ref normalized)).sqrMagnitude < 0.01f) { val = Vector3.ProjectOnPlane(((Component)Owner.Invoke(_projectile)).transform.forward, Vector3.up); normalized = ((Vector3)(ref val)).normalized; } val = Vector3.Cross(Vector3.up, normalized); Vector3 normalized2 = ((Vector3)(ref val)).normalized; float num2 = (float)num * (float)Math.PI * 2f / 3f + (float)Math.PI / 2f; Vector3 val2 = normalized2 * (Mathf.Cos(num2) * 1.9f) + normalized * (Mathf.Sin(num2) * 1.9f); Transform transform = ((Component)this).transform; transform.position += val2; StartPoint.Invoke(_projectile) = StartPoint.Invoke(_projectile) + val2; _placed = true; } } } internal static class FrostedRootAttacks { private static GameObject _moderProjectile; private static GameObject _elderProjectile; internal static Attack BuildPrimary(Attack architecture) { Attack obj = CloneArchitecture(architecture); obj.m_attackProjectile = GetModerProjectile(); obj.m_projectiles = 6; obj.m_projectileBursts = 1; obj.m_burstInterval = 0f; obj.m_projectileAccuracy = 0f; obj.m_projectileAccuracyMin = 0f; obj.m_randomVelocity = false; obj.m_damageMultiplier = 1f; return obj; } internal static Attack BuildSecondary(Attack architecture) { Attack obj = CloneArchitecture(architecture); obj.m_attackProjectile = GetElderProjectile(); obj.m_projectiles = 1; obj.m_projectileBursts = 1; obj.m_burstInterval = 0f; obj.m_perBurstResourceUsage = false; obj.m_projectileAccuracy = 0f; obj.m_projectileAccuracyMin = 0f; obj.m_randomVelocity = false; obj.m_damageMultiplier = 1f; obj.m_attackEitr = Mathf.Max(obj.m_attackEitr, 45f); return obj; } private static Attack CloneArchitecture(Attack architecture) { if (architecture == null) { throw new InvalidOperationException("The live Deep North staff has no projectile attack architecture."); } return architecture.Clone(); } private static GameObject GetModerProjectile() { if (!Object.op_Implicit((Object)(object)_moderProjectile)) { _moderProjectile = CloneSkyProjectile("FrostedRoot_ModerSkyShard", "dragon_ice_projectile", "staff_iceshard_projectile", 20f, 3.4f, 102f); } return _moderProjectile; } private static GameObject GetElderProjectile() { if (!Object.op_Implicit((Object)(object)_elderProjectile)) { _elderProjectile = CloneSkyProjectile("FrostedRoot_ElderSkyRoot", "gdking_root_projectile", "staff_greenroots_projectile", 20f, 0.35f, 102f); } return _elderProjectile; } private static GameObject CloneSkyProjectile(string cloneName, string bossPrefab, string fallbackPrefab, float height, float spread, float speed) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //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) GameObject val = RootboundContent.FindPrefab(bossPrefab); bool flag = false; if (!Object.op_Implicit((Object)(object)val)) { val = RootboundContent.FindPrefab(fallbackPrefab); flag = true; } if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val.GetComponent() == (Object)null) { throw new InvalidOperationException("Neither " + bossPrefab + " nor " + fallbackPrefab + " resolved to a live Projectile prefab."); } GameObject val2 = PrefabManager.Instance.CreateClonedPrefab(cloneName, val); val2.AddComponent().Configure(height, spread, speed); if (cloneName == "FrostedRoot_ElderSkyRoot") { val2.transform.localScale = Vector3.Scale(val2.transform.localScale, new Vector3(0.055f, 0.055f, 0.32f)); MakeElderProjectileWhite(val2); val2.AddComponent(); } PrefabManager.Instance.AddPrefab(new CustomPrefab(val2, true)); RootboundWitchPlugin.Log.LogInfo((object)("Frosted Root projectile " + cloneName + " cloned from " + ((Object)val).name + (flag ? " (boss prefab unavailable; live staff fallback)." : "."))); return val2; } private static void MakeElderProjectileWhite(GameObject projectile) { //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: 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_01fd: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(0.88f, 0.95f, 1f, 1f); Renderer[] componentsInChildren = projectile.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if (val2 is TrailRenderer || val2 is LineRenderer) { val2.enabled = false; continue; } Material[] sharedMaterials = val2.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int j = 0; j < sharedMaterials.Length; j++) { if (Object.op_Implicit((Object)(object)sharedMaterials[j])) { Material val3 = new Material(sharedMaterials[j]) { name = ((Object)sharedMaterials[j]).name + "_FrostedRootWhiteProjectile" }; if (val3.HasProperty("_MainTex")) { val3.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture); } if (val3.HasProperty("_BaseMap")) { val3.SetTexture("_BaseMap", (Texture)(object)Texture2D.whiteTexture); } if (val3.HasProperty("_Color")) { val3.SetColor("_Color", val); } if (val3.HasProperty("_BaseColor")) { val3.SetColor("_BaseColor", val); } if (val3.HasProperty("_TintColor")) { val3.SetColor("_TintColor", val); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", val * 0.22f); } if (val3.HasProperty("_Hue")) { val3.SetFloat("_Hue", 0.55f); } if (val3.HasProperty("_Saturation")) { val3.SetFloat("_Saturation", 0.08f); } if (val3.HasProperty("_Value")) { val3.SetFloat("_Value", 1f); } array[j] = val3; } } val2.sharedMaterials = array; TrailRenderer val4 = (TrailRenderer)(object)((val2 is TrailRenderer) ? val2 : null); if (Object.op_Implicit((Object)(object)val4)) { val4.startColor = val; val4.endColor = new Color(val.r, val.g, val.b, 0f); } } ParticleSystem[] componentsInChildren2 = projectile.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { MainModule main = componentsInChildren2[i].main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(val); ((MainModule)(ref main)).startSizeMultiplier = ((MainModule)(ref main)).startSizeMultiplier * 0.12f; } Light[] componentsInChildren3 = projectile.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { componentsInChildren3[i].color = val; } } internal static void BeginElderContinuation(Projectile seed) { if (Object.op_Implicit((Object)(object)seed) && Object.op_Implicit((Object)(object)RootboundWitchPlugin.Instance)) { ((MonoBehaviour)RootboundWitchPlugin.Instance).StartCoroutine(EmitElderContinuation(seed)); } } private static IEnumerator EmitElderContinuation(Projectile seed) { Character owner = FrostedRootProjectileState.Owner(seed); HitData hitData = FrostedRootProjectileState.HitData(seed); ItemData weapon = FrostedRootProjectileState.Weapon(seed); ItemData ammo = FrostedRootProjectileState.Ammo(seed); float hitNoise = seed.m_hitNoise; int index = 1; while (index < 15) { yield return (object)new WaitForSeconds(0.5f); if (!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)GetElderProjectile())) { break; } Vector3 lookDir = owner.GetLookDir(); Vector3 val = ((Vector3)(ref lookDir)).normalized * 10f; GameObject obj = Object.Instantiate(GetElderProjectile(), owner.GetEyePoint(), Quaternion.LookRotation(val)); FrostedRootElderBurstSeed component = obj.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.MarkContinuation(); } obj.GetComponent().Setup(owner, val, hitNoise, (HitData)((hitData != null) ? ((object)hitData.Clone()) : ((object)new HitData())), weapon, ammo); int num = index + 1; index = num; } } } internal static class FrostedRootProjectileState { private static readonly FieldRef OwnerField = AccessTools.FieldRefAccess("m_owner"); private static readonly FieldRef HitDataField = AccessTools.FieldRefAccess("m_originalHitData"); private static readonly FieldRef WeaponField = AccessTools.FieldRefAccess("m_weapon"); private static readonly FieldRef AmmoField = AccessTools.FieldRefAccess("m_ammo"); internal static Character Owner(Projectile projectile) { return OwnerField.Invoke(projectile); } internal static HitData HitData(Projectile projectile) { return HitDataField.Invoke(projectile); } internal static ItemData Weapon(Projectile projectile) { return WeaponField.Invoke(projectile); } internal static ItemData Ammo(Projectile projectile) { return AmmoField.Invoke(projectile); } } internal sealed class FrostedRootElderBurstSeed : MonoBehaviour { private bool _continuation; internal void MarkContinuation() { _continuation = true; } private void Start() { if (!_continuation) { Projectile component = ((Component)this).GetComponent(); Character obj = (Object.op_Implicit((Object)(object)component) ? FrostedRootProjectileState.Owner(component) : null); Player val = (Player)(object)((obj is Player) ? obj : null); if (Object.op_Implicit((Object)(object)component) && ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)Player.m_localPlayer)) { FrostedRootAttacks.BeginElderContinuation(component); } } } } internal sealed class FrostedRootSkyRedirect : MonoBehaviour { private static readonly FieldRef Owner = AccessTools.FieldRefAccess("m_owner"); private static readonly FieldRef Velocity = AccessTools.FieldRefAccess("m_vel"); private static readonly FieldRef StartPoint = AccessTools.FieldRefAccess("m_startPoint"); private static readonly FieldRef HaveStartPoint = AccessTools.FieldRefAccess("m_haveStartPoint"); private float _height; private float _spread; private float _speed; private Projectile _projectile; private bool _redirected; internal void Configure(float height, float spread, float speed) { _height = height; _spread = spread; _speed = speed; } private void Awake() { _projectile = ((Component)this).GetComponent(); } private void Start() { RedirectNow(); } private void Update() { if (!_redirected) { RedirectNow(); } } internal void RedirectNow() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if (!_redirected && !((Object)(object)_projectile == (Object)null)) { Character val = Owner.Invoke(_projectile); if (!((Object)(object)val == (Object)null)) { Vector3 val2 = FindTargetPoint(val); Vector2 val3 = Random.insideUnitCircle * Mathf.Max(0f, _spread); Vector3 val4 = val2 + new Vector3(val3.x, 0f, val3.y) + Vector3.up * Mathf.Max(3f, _height); Vector3 down = Vector3.down; ((Component)this).transform.position = val4; ((Component)this).transform.rotation = Quaternion.LookRotation(down); Velocity.Invoke(_projectile) = down * Mathf.Max(8f, _speed); StartPoint.Invoke(_projectile) = val4; HaveStartPoint.Invoke(_projectile) = true; _redirected = true; } } } private static Vector3 FindTargetPoint(Character owner) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0045: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) Vector3 eyePoint = owner.GetEyePoint(); Vector3 lookDir = owner.GetLookDir(); Vector3 normalized = ((Vector3)(ref lookDir)).normalized; RaycastHit val2 = default(RaycastHit); Vector3 val = (Physics.Raycast(eyePoint, normalized, ref val2, 4096f, -1, (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val2)).point : (eyePoint + normalized * 512f)); RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val + Vector3.up * 30f, Vector3.down, ref val3, 180f, -1, (QueryTriggerInteraction)1)) { val = ((RaycastHit)(ref val3)).point + Vector3.up * 0.1f; } return val; } } [HarmonyPatch(typeof(Projectile), "Setup")] internal static class FrostedRootImmediateRedirectPatch { private static void Postfix(Projectile __instance) { FrostedRootSkyRedirect frostedRootSkyRedirect = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent() : null); if (Object.op_Implicit((Object)(object)frostedRootSkyRedirect)) { frostedRootSkyRedirect.RedirectNow(); } } } internal static class FrostedStaffVisual { private static Texture2D _snowTexture; internal static void Apply(GameObject itemPrefab) { //IL_004a: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)itemPrefab)) { return; } Light[] componentsInChildren = itemPrefab.GetComponentsInChildren(true); foreach (Light obj in componentsInChildren) { ((Behaviour)obj).enabled = false; obj.intensity = 0f; } ParticleSystem[] componentsInChildren2 = itemPrefab.GetComponentsInChildren(true); foreach (ParticleSystem obj2 in componentsInChildren2) { obj2.Stop(true, (ParticleSystemStopBehavior)0); EmissionModule emission = obj2.emission; ((EmissionModule)(ref emission)).enabled = false; } Renderer[] componentsInChildren3 = itemPrefab.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren3) { Material[] sharedMaterials = val.sharedMaterials; bool flag = false; bool flag2 = true; for (int j = 0; j < sharedMaterials.Length; j++) { if (Object.op_Implicit((Object)(object)sharedMaterials[j])) { flag = true; if (!IsDeadCore(sharedMaterials[j])) { flag2 = false; } } } if (flag && flag2) { val.enabled = false; ((Component)val).gameObject.SetActive(false); RootboundWitchPlugin.Log.LogInfo((object)("Frosted Root removed dead Surtling-core renderer " + ((Object)((Component)val).gameObject).name + ".")); continue; } Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int k = 0; k < sharedMaterials.Length; k++) { if (Object.op_Implicit((Object)(object)sharedMaterials[k])) { Material val2 = new Material(sharedMaterials[k]) { name = ((Object)sharedMaterials[k]).name + "_FrostedRoot" }; if (IsDeadCore(val2)) { MakeInvisible(val2); } else { ApplySnow(val2); } KillEmission(val2); array[k] = val2; } } val.sharedMaterials = array; } } internal static void RemoveDeadCoreOnly(GameObject itemPrefab, string visualName) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)itemPrefab)) { return; } Renderer[] componentsInChildren = itemPrefab.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; bool num = IsDeadCoreName(((Object)((Component)val).gameObject).name); bool flag = sharedMaterials.Any((Material material) => Object.op_Implicit((Object)(object)material)) && sharedMaterials.Where((Material material) => Object.op_Implicit((Object)(object)material)).All(IsDeadCore); if (num || flag) { val.enabled = false; ((Component)val).gameObject.SetActive(false); RootboundWitchPlugin.Log.LogInfo((object)(visualName + " removed dead Surtling-core renderer " + ((Object)((Component)val).gameObject).name + ".")); continue; } Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; bool flag2 = false; for (int num2 = 0; num2 < sharedMaterials.Length; num2++) { Material val2 = sharedMaterials[num2]; if (Object.op_Implicit((Object)(object)val2)) { Material val3 = val2; if (IsDeadCore(val2)) { val3 = new Material(val2) { name = ((Object)val2).name + "_RemovedCore" }; MakeInvisible(val3); KillEmission(val3); flag2 = true; } array[num2] = val3; } } if (flag2) { val.sharedMaterials = array; } } } private static bool IsDeadCore(Material material) { if ((Object)(object)material != (Object)null) { return IsDeadCoreName(((Object)material).name); } return false; } private static bool IsDeadCoreName(string name) { if (!string.IsNullOrEmpty(name)) { if (name.IndexOf("RootboundDeadCore", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Rootbound_DeadCore", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("surtling", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("ember", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("firecore", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("flames", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } private static void ApplySnow(Material material) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) Texture2D snowTexture = GetSnowTexture(); if (material.HasProperty("_MainTex")) { material.SetTexture("_MainTex", (Texture)(object)snowTexture); } if (material.HasProperty("_BaseMap")) { material.SetTexture("_BaseMap", (Texture)(object)snowTexture); } if (material.HasProperty("_BumpMap")) { material.SetTexture("_BumpMap", (Texture)null); } if (material.HasProperty("_MetallicGlossMap")) { material.SetTexture("_MetallicGlossMap", (Texture)null); } SetColour(material, Color.white); } private static Texture2D GetSnowTexture() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_00d5: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_snowTexture)) { return _snowTexture; } _snowTexture = new Texture2D(16, 16, (TextureFormat)4, false) { name = "FrostedRoot_SnowedWoodTexture", filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)0, hideFlags = (HideFlags)61 }; Color val = default(Color); ((Color)(ref val))..ctor(0.72f, 0.82f, 0.84f, 1f); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.9f, 0.95f, 0.96f, 1f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.47f, 0.59f, 0.61f, 1f); Color[] array = (Color[])(object)new Color[256]; for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { int num = (j * 19 + i * 31 + (j ^ i) * 7) % 17; array[i * 16 + j] = ((num < 3) ? val3 : ((num > 12) ? val2 : val)); } } _snowTexture.SetPixels(array); _snowTexture.Apply(false, true); return _snowTexture; } private static void MakeInvisible(Material material) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) SetColour(material, new Color(0f, 0f, 0f, 0f)); if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 1f); } if (material.HasProperty("_Mode")) { material.SetFloat("_Mode", 3f); } if (material.HasProperty("_SrcBlend")) { material.SetInt("_SrcBlend", 5); } if (material.HasProperty("_DstBlend")) { material.SetInt("_DstBlend", 10); } if (material.HasProperty("_ZWrite")) { material.SetInt("_ZWrite", 0); } material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.EnableKeyword("_ALPHABLEND_ON"); material.renderQueue = 3000; } private static void SetColour(Material material, Color colour) { //IL_0013: 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_0045: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty("_Color")) { material.SetColor("_Color", colour); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", colour); } if (material.HasProperty("_TintColor")) { material.SetColor("_TintColor", colour); } } private static void KillEmission(Material material) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); } if (material.HasProperty("_EmissionMap")) { material.SetTexture("_EmissionMap", (Texture)null); } material.DisableKeyword("_EMISSION"); material.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)4; } } internal static class PermafrostVisuals { private static readonly FieldRef Equipment = AccessTools.FieldRefAccess("m_visEquipment"); private static readonly FieldRef BodyModel = AccessTools.FieldRefAccess("m_bodyModel"); private static readonly FieldRef HelmetInstance = AccessTools.FieldRefAccess("m_helmetItemInstance"); private static readonly FieldRef> ChestInstances = AccessTools.FieldRefAccess>("m_chestItemInstances"); private static readonly FieldRef> LegInstances = AccessTools.FieldRefAccess>("m_legItemInstances"); private static readonly Dictionary Previous = new Dictionary(); private static readonly Dictionary PreviousMaterials = new Dictionary(); private static readonly Dictionary FrostedTextures = new Dictionary(); private static readonly Color Permafrost = new Color(0.82f, 0.89f, 0.94f, 1f); private static readonly int ChestTexture = Shader.PropertyToID("_ChestTex"); private static readonly int LegsTexture = Shader.PropertyToID("_LegsTex"); private static readonly int SkinColor = Shader.PropertyToID("_SkinColor"); private static readonly Color DvergerBlue = new Color(0.35f, 0.5f, 0.72f, 1f); private static Material _bodyMaterial; private static SkinnedMeshRenderer _bodyRenderer; private static MaterialPropertyBlock _originalBodyBlock; private static bool _bodyBlockCaptured; private static Texture _originalChest; private static Texture _originalLegs; private static Texture _frostedChest; private static Texture _frostedLegs; private static Color _originalSkinColor; private static bool _skinColorCaptured; private static readonly Dictionary PreviousSkinColours = new Dictionary(); private static MethodInfo _getEquippedBackpack; private static MethodInfo _getBackpackVisual; private static bool _backpackApiFailed; private static readonly List CrystalAccents = new List(); private static readonly List CrystalHosts = new List(); private static Material _crystalMaterial; internal static void BindBackpackApi(Assembly assembly) { Type type = ((assembly != null) ? assembly.GetType("Backpacks.API", throwOnError: false) : null); _getEquippedBackpack = ((type != null) ? type.GetMethod("GetEquippedBackpack", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null) : null); _getBackpackVisual = ((type != null) ? type.GetMethod("GetBackpackVisual", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Player) }, null) : null); _backpackApiFailed = false; } internal static void Update(Player player, bool active) { VisEquipment val = (((Object)(object)player != (Object)null) ? Equipment.Invoke((Humanoid)(object)player) : null); if (!active || (Object)(object)player == (Object)null || (Object)(object)val == (Object)null) { Clear(); return; } HashSet hashSet = new HashSet(); ApplyBodyTextures(val); List list = new List(GetSetVisuals(val)); foreach (GameObject item in list) { ApplyWhiteVisual(item, hashSet); } foreach (GameObject rootboundSatchelVisual in GetRootboundSatchelVisuals(player)) { ApplyWhiteVisual(rootboundSatchelVisual, hashSet); } UpdateCrystalAccents(player, list); foreach (Renderer item2 in new List(Previous.Keys)) { if (!hashSet.Contains(item2)) { Restore(item2); } } } internal static void Clear() { RestoreBodyTextures(); foreach (Renderer item in new List(Previous.Keys)) { Restore(item); } Previous.Clear(); PreviousMaterials.Clear(); ClearCrystalAccents(); } internal static void ReapplyDvergerSkin(VisEquipment equipment) { SkinnedMeshRenderer val = (((Object)(object)equipment != (Object)null) ? BodyModel.Invoke(equipment) : null); if (Object.op_Implicit((Object)(object)val)) { Material material = ((Renderer)val).material; if ((Object)(object)_bodyRenderer != (Object)(object)val || (Object)(object)_bodyMaterial != (Object)(object)material) { ApplyBodyTextures(equipment); } else { ApplyDvergerSkin(Player.m_localPlayer, val); } } } internal static Material[] BuildExternalWhiteMaterials(Material[] source) { return BuildWhiteMaterials((Material[])(((object)source) ?? ((object)new Material[0]))); } private static IEnumerable GetSetVisuals(VisEquipment equipment) { GameObject val = HelmetInstance.Invoke(equipment); if (Object.op_Implicit((Object)(object)val)) { yield return val; } List list = ChestInstances.Invoke(equipment); if (list != null) { foreach (GameObject item in list) { yield return item; } } List list2 = LegInstances.Invoke(equipment); if (list2 == null) { yield break; } foreach (GameObject item2 in list2) { yield return item2; } } private static IEnumerable GetRootboundSatchelVisuals(Player player) { if (_backpackApiFailed || _getEquippedBackpack == null || _getBackpackVisual == null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { yield break; } object obj; object obj2; try { obj = _getEquippedBackpack.Invoke(null, null); obj2 = _getBackpackVisual.Invoke(null, new object[1] { player }); } catch (Exception ex) { _backpackApiFailed = true; RootboundWitchPlugin.Log.LogWarning((object)("Rootbound Satchel permafrost bridge disabled: " + ex.GetBaseException().Message)); yield break; } ItemData val = (ItemData)((obj is ItemData) ? obj : null); string obj3 = RootboundState.PrefabName(val) ?? string.Empty; string text = ((val != null && val.m_shared != null) ? (val.m_shared.m_name ?? string.Empty) : string.Empty); if ((obj3 + text).Replace(" ", string.Empty).Replace("_", string.Empty).IndexOf("RootboundSatchel", StringComparison.OrdinalIgnoreCase) < 0 || val.m_quality < 4 || !(obj2 is IEnumerable enumerable)) { yield break; } foreach (object item in enumerable) { GameObject val2 = (GameObject)((item is GameObject) ? item : null); if (Object.op_Implicit((Object)(object)val2)) { yield return val2; } } } private static void ApplyWhiteVisual(GameObject visual, HashSet current) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00a0: 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_00c0: 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) if (!Object.op_Implicit((Object)(object)visual)) { return; } Renderer[] componentsInChildren = visual.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)((Component)val).GetComponentInParent() != (Object)null)) { current.Add(val); if (!Previous.ContainsKey(val)) { MaterialPropertyBlock val2 = new MaterialPropertyBlock(); val.GetPropertyBlock(val2); Previous[val] = val2; } if (!PreviousMaterials.ContainsKey(val)) { Material[] sharedMaterials = val.sharedMaterials; PreviousMaterials[val] = sharedMaterials; val.sharedMaterials = BuildWhiteMaterials(sharedMaterials); } MaterialPropertyBlock val3 = new MaterialPropertyBlock(); val.GetPropertyBlock(val3); val3.SetColor("_Color", Permafrost); val3.SetColor("_BaseColor", Permafrost); val3.SetColor("_TintColor", Permafrost); val3.SetColor("_EmissionColor", Color.black); val.SetPropertyBlock(val3); } } } private static void Restore(Renderer renderer) { if (Object.op_Implicit((Object)(object)renderer) && Previous.TryGetValue(renderer, out var value)) { renderer.SetPropertyBlock(value); } Previous.Remove(renderer); if (Object.op_Implicit((Object)(object)renderer) && PreviousMaterials.TryGetValue(renderer, out var value2)) { renderer.sharedMaterials = value2; } PreviousMaterials.Remove(renderer); } private static void UpdateCrystalAccents(Player player, List hosts) { //IL_00fa: 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) //IL_0103: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) bool flag = hosts.Count == CrystalHosts.Count; if (flag) { for (int i = 0; i < hosts.Count; i++) { if ((Object)(object)hosts[i] != (Object)(object)CrystalHosts[i]) { flag = false; break; } } } if (flag && CrystalAccents.All((GameObject accent) => Object.op_Implicit((Object)(object)accent))) { return; } ClearCrystalAccents(); CrystalHosts.AddRange(hosts); for (int num = 0; num < hosts.Count; num++) { GameObject val = hosts[num]; Renderer val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponentsInChildren(true).OrderByDescending(delegate(Renderer candidate) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Bounds bounds2 = candidate.bounds; Vector3 size = ((Bounds)(ref bounds2)).size; return ((Vector3)(ref size)).sqrMagnitude; }).FirstOrDefault() : null); if (!((Object)(object)val2 == (Object)null)) { float scale = num switch { 1 => 0.18f, 0 => 0.15f, _ => 0.13f, }; Bounds bounds = val2.bounds; Vector3 val3 = ((Bounds)(ref bounds)).center - ((Component)player).transform.position; val3.y = 0f; if (((Vector3)(ref val3)).sqrMagnitude < 0.01f) { val3 = ((Component)player).transform.right * ((num % 2 == 0) ? 1f : (-1f)); } bounds = val2.bounds; Vector3 worldPosition = ((Bounds)(ref bounds)).center + ((Vector3)(ref val3)).normalized * ((num == 0) ? 0.1f : 0.07f); GameObject val4 = BuildCrystalCluster(((Component)player).transform, worldPosition, scale, (float)num * 37f); if (Object.op_Implicit((Object)(object)val4)) { CrystalAccents.Add(val4); } } } } private static GameObject BuildCrystalCluster(Transform parent, Vector3 worldPosition, float scale, float yaw) { //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_004b: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown Material crystalMaterial = GetCrystalMaterial(); if (!Object.op_Implicit((Object)(object)crystalMaterial)) { return null; } GameObject val = new GameObject("Rootbound_PermafrostCrystalAccent"); val.AddComponent(); val.transform.SetParent(parent, true); val.transform.position = worldPosition; val.transform.rotation = Quaternion.Euler(0f, yaw, 0f); AddCrystal(val.transform, new Vector3(0f, 0f, 0f), Quaternion.Euler(8f, 0f, -8f), scale, crystalMaterial); AddCrystal(val.transform, new Vector3(scale * 0.72f, (0f - scale) * 0.16f, scale * 0.12f), Quaternion.Euler(-12f, 28f, 18f), scale * 0.68f, crystalMaterial); AddCrystal(val.transform, new Vector3((0f - scale) * 0.58f, (0f - scale) * 0.2f, (0f - scale) * 0.08f), Quaternion.Euler(15f, -30f, -22f), scale * 0.56f, crystalMaterial); return val; } private static void AddCrystal(Transform parent, Vector3 position, Quaternion rotation, float scale, Material material) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("IceStaffTipCrystal"); val.transform.SetParent(parent, false); val.transform.localPosition = position; val.transform.localRotation = rotation; val.transform.localScale = new Vector3(scale, scale * 2.4f, scale); MeshFilter val2 = val.AddComponent(); MeshRenderer obj = val.AddComponent(); val2.sharedMesh = BuildCrystalMesh(); ((Renderer)obj).sharedMaterial = material; } private static Mesh BuildCrystalMesh() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown Vector3[] vertices = (Vector3[])(object)new Vector3[6] { new Vector3(0f, 0.65f, 0f), new Vector3(0.42f, 0f, 0f), new Vector3(0f, 0f, 0.42f), new Vector3(-0.42f, 0f, 0f), new Vector3(0f, 0f, -0.42f), new Vector3(0f, -0.35f, 0f) }; int[] triangles = new int[24] { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1, 5, 2, 1, 5, 3, 2, 5, 4, 3, 5, 1, 4 }; Mesh val = new Mesh { name = "Rootbound_IceStaffTipCrystalMesh", vertices = vertices, triangles = triangles }; val.RecalculateNormals(); val.RecalculateBounds(); return val; } private static Material GetCrystalMaterial() { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_crystalMaterial)) { return _crystalMaterial; } GameObject val = RootboundContent.FindPrefab("StaffIce") ?? RootboundContent.FindPrefab("StaffIceShards") ?? RootboundContent.FindPrefab("StaffFrostOrbs"); Material val2 = (Object.op_Implicit((Object)(object)val) ? (from material in val.GetComponentsInChildren(true).SelectMany((Renderer renderer) => renderer.sharedMaterials) where Object.op_Implicit((Object)(object)material) select material).OrderByDescending(delegate(Material material) { string text = ((Object)material).name.ToLowerInvariant(); return (text.Contains("ice") || text.Contains("frost") || text.Contains("crystal")) ? 1 : 0; }).FirstOrDefault() : null); if (!Object.op_Implicit((Object)(object)val2)) { RootboundWitchPlugin.Log.LogWarning((object)"No live vanilla ice-staff material was available for tier-four crystal accents."); return null; } _crystalMaterial = new Material(val2) { name = "Rootbound_VanillaIceStaffAccent" }; Color val3 = default(Color); ((Color)(ref val3))..ctor(0.58f, 0.82f, 1f, 0.92f); if (_crystalMaterial.HasProperty("_Color")) { _crystalMaterial.SetColor("_Color", val3); } if (_crystalMaterial.HasProperty("_BaseColor")) { _crystalMaterial.SetColor("_BaseColor", val3); } if (_crystalMaterial.HasProperty("_EmissionColor")) { _crystalMaterial.SetColor("_EmissionColor", val3 * 0.65f); } return _crystalMaterial; } private static void ClearCrystalAccents() { foreach (GameObject crystalAccent in CrystalAccents) { if (Object.op_Implicit((Object)(object)crystalAccent)) { Object.Destroy((Object)(object)crystalAccent); } } CrystalAccents.Clear(); CrystalHosts.Clear(); } private static Material[] BuildWhiteMaterials(Material[] source) { //IL_0020: 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_003c: Expected O, but got Unknown //IL_0058: 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_0078: 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) Material[] array = (Material[])(object)new Material[source.Length]; for (int i = 0; i < source.Length; i++) { Material val = source[i]; if (Object.op_Implicit((Object)(object)val)) { Material val2 = new Material(val) { name = ((Object)val).name + "_RootboundPermafrostWhite" }; FrostTextureProperty(val2, "_MainTex"); FrostTextureProperty(val2, "_BaseMap"); SetMaterialColour(val2, "_Color", Permafrost); SetMaterialColour(val2, "_BaseColor", Permafrost); SetMaterialColour(val2, "_TintColor", Permafrost); SetMaterialColour(val2, "_EmissionColor", Color.black); val2.DisableKeyword("_EMISSION"); val2.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)4; array[i] = val2; } } return array; } private static void FrostTextureProperty(Material material, string property) { if (material.HasProperty(property)) { Texture2D val = BuildFrostedTexture(material.GetTexture(property), ((Object)material).name + property + "White"); if (Object.op_Implicit((Object)(object)val)) { material.SetTexture(property, (Texture)(object)val); } } } private static void SetMaterialColour(Material material, string property, Color colour) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(property)) { material.SetColor(property, colour); } } private static void ApplyBodyTextures(VisEquipment equipment) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) SkinnedMeshRenderer val = BodyModel.Invoke(equipment); if (!Object.op_Implicit((Object)(object)val)) { RestoreBodyTextures(); return; } Material material = ((Renderer)val).material; if ((Object)(object)_bodyRenderer != (Object)(object)val || (Object)(object)_bodyMaterial != (Object)(object)material) { RestoreBodyTextures(); _bodyRenderer = val; _bodyMaterial = material; _originalBodyBlock = new MaterialPropertyBlock(); ((Renderer)val).GetPropertyBlock(_originalBodyBlock); _bodyBlockCaptured = true; _originalChest = material.GetTexture(ChestTexture); _originalLegs = material.GetTexture(LegsTexture); if (material.HasProperty(SkinColor)) { _originalSkinColor = material.GetColor(SkinColor); _skinColorCaptured = true; } _frostedChest = (Texture)(object)BuildFrostedTexture(_originalChest, "Rootbound_PermafrostChest"); _frostedLegs = (Texture)(object)BuildFrostedTexture(_originalLegs, "Rootbound_PermafrostLegs"); } RefreshSlot(material, ChestTexture, ref _originalChest, ref _frostedChest, "Rootbound_PermafrostChest"); RefreshSlot(material, LegsTexture, ref _originalLegs, ref _frostedLegs, "Rootbound_PermafrostLegs"); ApplyDvergerSkin(Player.m_localPlayer, val); } private static void ApplyDvergerSkin(Player player, SkinnedMeshRenderer body) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00c1: 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) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)body)) { return; } foreach (Renderer item in (IEnumerable)(((Object)(object)player != (Object)null) ? ((Array)((Component)player).GetComponentsInChildren(true)) : ((Array)new Renderer[1] { (Renderer)body }))) { Material[] materials = item.materials; foreach (Material val in materials) { if (Object.op_Implicit((Object)(object)val) && val.HasProperty(SkinColor)) { if (!PreviousSkinColours.ContainsKey(val)) { PreviousSkinColours[val] = val.GetColor(SkinColor); } val.SetColor(SkinColor, DvergerBlue); } } } MaterialPropertyBlock val2 = new MaterialPropertyBlock(); ((Renderer)body).GetPropertyBlock(val2); val2.SetColor(SkinColor, DvergerBlue); ((Renderer)body).SetPropertyBlock(val2); } private static void RefreshSlot(Material material, int property, ref Texture original, ref Texture frosted, string name) { Texture texture = material.GetTexture(property); if (Object.op_Implicit((Object)(object)texture) && (Object)(object)texture != (Object)(object)frosted && (Object)(object)texture != (Object)(object)original) { original = texture; frosted = (Texture)(object)BuildFrostedTexture(texture, name); } if (Object.op_Implicit((Object)(object)frosted)) { material.SetTexture(property, frosted); } } private static Texture2D BuildFrostedTexture(Texture source, string name) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_009f: 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_00c7: 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_00e2: 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_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)source)) { return null; } if (FrostedTextures.TryGetValue(source, out var value) && Object.op_Implicit((Object)(object)value)) { return value; } RenderTexture active = RenderTexture.active; RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)1); try { Graphics.Blit(source, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, false) { name = name, filterMode = source.filterMode, wrapMode = source.wrapMode, hideFlags = (HideFlags)61 }; val.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0, false); Color[] pixels = val.GetPixels(); for (int i = 0; i < pixels.Length; i++) { Color val2 = pixels[i]; float num = Mathf.Clamp01(val2.r * 0.2126f + val2.g * 0.7152f + val2.b * 0.0722f); float num2 = Mathf.Lerp(0.4f, 1f, Mathf.Pow(num, 0.76f)); pixels[i] = new Color(num2 * 0.78f, num2 * 0.9f, num2, val2.a); } val.SetPixels(pixels); val.Apply(false, true); FrostedTextures[source] = val; return val; } catch (Exception ex) { RootboundWitchPlugin.Log.LogWarning((object)("Could not build the quality-four permafrost texture: " + ex.Message)); return null; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } private static void RestoreBodyTextures() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_bodyMaterial)) { if (Object.op_Implicit((Object)(object)_frostedChest) && (Object)(object)_bodyMaterial.GetTexture(ChestTexture) == (Object)(object)_frostedChest) { _bodyMaterial.SetTexture(ChestTexture, _originalChest); } if (Object.op_Implicit((Object)(object)_frostedLegs) && (Object)(object)_bodyMaterial.GetTexture(LegsTexture) == (Object)(object)_frostedLegs) { _bodyMaterial.SetTexture(LegsTexture, _originalLegs); } if (_skinColorCaptured && _bodyMaterial.HasProperty(SkinColor)) { _bodyMaterial.SetColor(SkinColor, _originalSkinColor); } } if (Object.op_Implicit((Object)(object)_bodyRenderer) && _bodyBlockCaptured && _originalBodyBlock != null) { ((Renderer)_bodyRenderer).SetPropertyBlock(_originalBodyBlock); } KeyValuePair[] array = PreviousSkinColours.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair keyValuePair = array[i]; if (Object.op_Implicit((Object)(object)keyValuePair.Key) && keyValuePair.Key.HasProperty(SkinColor)) { keyValuePair.Key.SetColor(SkinColor, keyValuePair.Value); } } PreviousSkinColours.Clear(); _bodyMaterial = null; _bodyRenderer = null; _originalBodyBlock = null; _bodyBlockCaptured = false; _originalChest = null; _originalLegs = null; _frostedChest = null; _frostedLegs = null; _skinColorCaptured = false; } } internal sealed class RootboundPermafrostCrystalMarker : MonoBehaviour { } [HarmonyPatch(typeof(VisEquipment), "UpdateColors")] internal static class RootboundPermafrostSkinRefreshPatch { private static void Postfix(VisEquipment __instance) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && RootboundWitchPlugin.EnablePermafrostTint.Value && RootboundState.IsPermafrost(localPlayer)) { PermafrostVisuals.ReapplyDvergerSkin(__instance); } } } internal static class PetrifiedToolVisuals { private enum Treatment { WalnutAntler, CorewoodBlade } private static readonly Color Walnut = new Color(0.22f, 0.105f, 0.04f, 1f); private static readonly Color Corewood = new Color(0.3f, 0.155f, 0.06f, 1f); internal static void ApplyPick(GameObject prefab) { Apply(prefab, Treatment.WalnutAntler); } internal static void ApplyAxe(GameObject prefab) { Apply(prefab, Treatment.CorewoodBlade); } private static void Apply(GameObject prefab, Treatment treatment) { if (!Object.op_Implicit((Object)(object)prefab)) { return; } Dictionary dictionary = new Dictionary(); Dictionary textureCopies = new Dictionary(); Renderer[] componentsInChildren = prefab.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; bool flag = false; for (int j = 0; j < sharedMaterials.Length; j++) { Material val2 = sharedMaterials[j]; if (Object.op_Implicit((Object)(object)val2)) { if (!dictionary.TryGetValue(val2, out var value)) { value = (dictionary[val2] = BuildMaterial(val2, treatment, textureCopies)); } sharedMaterials[j] = value; flag = true; } } if (flag) { val.sharedMaterials = sharedMaterials; } } RootboundWitchPlugin.Log.LogInfo((object)(((Object)prefab).name + " received the " + ((treatment == Treatment.WalnutAntler) ? "walnut-antler" : "corewood-grain") + " non-metal visual treatment.")); } private static Material BuildMaterial(Material source, Treatment treatment, Dictionary textureCopies) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(source) { name = ((Object)source).name + ((treatment == Treatment.WalnutAntler) ? "_PetrifiedWalnut" : "_PetrifiedCorewood") }; RecolourTextureProperty(val, "_MainTex", treatment, textureCopies); RecolourTextureProperty(val, "_BaseMap", treatment, textureCopies); if (val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", 0f); } if (val.HasProperty("_Glossiness")) { val.SetFloat("_Glossiness", 0.22f); } if (val.HasProperty("_Smoothness")) { val.SetFloat("_Smoothness", 0.22f); } if (val.HasProperty("_EmissionColor")) { val.SetColor("_EmissionColor", Color.black); } val.DisableKeyword("_EMISSION"); val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)4; return val; } private static void RecolourTextureProperty(Material material, string property, Treatment treatment, Dictionary textureCopies) { if (!material.HasProperty(property)) { return; } Texture texture = material.GetTexture(property); if (Object.op_Implicit((Object)(object)texture)) { if (!textureCopies.TryGetValue(texture, out var value)) { value = (textureCopies[texture] = BuildTexture(texture, treatment)); } if (Object.op_Implicit((Object)(object)value)) { material.SetTexture(property, (Texture)(object)value); } } } private static Texture2D BuildTexture(Texture source, Treatment treatment) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0067: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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) //IL_00e1: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) RenderTexture active = RenderTexture.active; RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)1); try { Graphics.Blit(source, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, false) { name = ((Object)source).name + ((treatment == Treatment.WalnutAntler) ? "_PetrifiedWalnutTexture" : "_PetrifiedCorewoodTexture"), filterMode = source.filterMode, wrapMode = source.wrapMode, hideFlags = (HideFlags)61 }; val.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0, false); Color[] pixels = val.GetPixels(); int num = Mathf.Max(1, ((Texture)val).width); Color val3 = default(Color); for (int i = 0; i < pixels.Length; i++) { Color val2 = pixels[i]; if (!(val2.a <= 0.001f)) { float num2 = Mathf.Max(val2.r, Mathf.Max(val2.g, val2.b)); float num3 = Mathf.Min(val2.r, Mathf.Min(val2.g, val2.b)); float num4 = ((num2 <= 0.001f) ? 0f : ((num2 - num3) / num2)); float num5 = val2.r * 0.2126f + val2.g * 0.7152f + val2.b * 0.0722f; float num6; if (treatment == Treatment.WalnutAntler) { num6 = Mathf.Clamp01((num5 - 0.24f) / 0.48f) * Mathf.Clamp01((0.6f - num4) / 0.45f); float num7 = Mathf.Lerp(0.58f, 1.32f, num5); ((Color)(ref val3))..ctor(Walnut.r * num7, Walnut.g * num7, Walnut.b * num7, val2.a); } else { float num8 = Mathf.Clamp01((val2.r - val2.b - 0.025f) * 5.5f); float num9 = Mathf.Clamp01((num5 - 0.18f) / 0.52f); num6 = num8 * num9; int num10 = i % num; int num11 = i / num; float num12 = 0.88f + 0.12f * Mathf.Sin((float)num11 * 0.31f + Mathf.Sin((float)num10 * 0.13f) * 2.4f); float num13 = Mathf.Lerp(0.62f, 1.28f, num5) * num12; ((Color)(ref val3))..ctor(Corewood.r * num13, Corewood.g * num13, Corewood.b * num13, val2.a); } pixels[i] = Color.Lerp(val2, val3, num6 * 0.97f); } } val.SetPixels(pixels); val.Apply(false, true); return val; } catch (Exception ex) { RootboundWitchPlugin.Log.LogWarning((object)("Could not build the petrified tool texture from " + ((Object)source).name + ": " + ex.Message)); return null; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } } internal static class ReclaimedStaffVisual { internal sealed class SourceVisualSnapshot { private sealed class TransformState { private readonly Transform _target; private readonly string _name; private readonly bool _active; internal TransformState(Transform target) { _target = target; _name = ((Object)target).name; _active = ((Component)target).gameObject.activeSelf; } internal bool Restore() { if (!Object.op_Implicit((Object)(object)_target)) { return false; } bool result = ((Object)_target).name != _name || ((Component)_target).gameObject.activeSelf != _active; ((Object)_target).name = _name; ((Component)_target).gameObject.SetActive(_active); return result; } } private sealed class RendererState { private readonly Renderer _target; private readonly bool _enabled; private readonly Material[] _materials; internal RendererState(Renderer target) { _target = target; _enabled = target.enabled; _materials = target.sharedMaterials; } internal bool Restore() { if (!Object.op_Implicit((Object)(object)_target)) { return false; } bool result = _target.enabled != _enabled || !_target.sharedMaterials.SequenceEqual(_materials); _target.enabled = _enabled; _target.sharedMaterials = _materials; return result; } } private sealed class LightState { private readonly Light _target; private readonly bool _enabled; private readonly Color _colour; private readonly float _intensity; private readonly float _range; private readonly LightShadows _shadows; internal LightState(Light target) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) _target = target; _enabled = ((Behaviour)target).enabled; _colour = target.color; _intensity = target.intensity; _range = target.range; _shadows = target.shadows; } internal bool Restore() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_target)) { return false; } bool result = ((Behaviour)_target).enabled != _enabled || _target.color != _colour || !Mathf.Approximately(_target.intensity, _intensity) || !Mathf.Approximately(_target.range, _range) || _target.shadows != _shadows; ((Behaviour)_target).enabled = _enabled; _target.color = _colour; _target.intensity = _intensity; _target.range = _range; _target.shadows = _shadows; return result; } } private sealed class ParticleState { private readonly ParticleSystem _target; private readonly bool _emissionEnabled; private readonly MinMaxGradient _startColour; internal ParticleState(ParticleSystem target) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) _target = target; EmissionModule emission = target.emission; _emissionEnabled = ((EmissionModule)(ref emission)).enabled; MainModule main = target.main; _startColour = ((MainModule)(ref main)).startColor; } internal bool Restore() { //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_0021: 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_0049: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_target)) { return false; } EmissionModule emission = _target.emission; MainModule main = _target.main; bool result = ((EmissionModule)(ref emission)).enabled != _emissionEnabled; ((EmissionModule)(ref emission)).enabled = _emissionEnabled; ((MainModule)(ref main)).startColor = _startColour; return result; } } private readonly GameObject _source; private readonly HashSet _transforms; private readonly HashSet _lights; private readonly HashSet _particles; private readonly List _transformStates; private readonly List _lightStates; private readonly List _particleStates; private readonly List _rendererStates; private bool _restored; internal SourceVisualSnapshot(GameObject source) { _source = source; _transforms = new HashSet(); _lights = new HashSet(); _particles = new HashSet(); _transformStates = new List(); _lightStates = new List(); _particleStates = new List(); _rendererStates = new List(); if (Object.op_Implicit((Object)(object)source)) { Transform[] componentsInChildren = source.GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { _transforms.Add(val); _transformStates.Add(new TransformState(val)); } Light[] componentsInChildren2 = source.GetComponentsInChildren(true); foreach (Light val2 in componentsInChildren2) { _lights.Add(val2); _lightStates.Add(new LightState(val2)); } ParticleSystem[] componentsInChildren3 = source.GetComponentsInChildren(true); foreach (ParticleSystem val3 in componentsInChildren3) { _particles.Add(val3); _particleStates.Add(new ParticleState(val3)); } Renderer[] componentsInChildren4 = source.GetComponentsInChildren(true); foreach (Renderer target in componentsInChildren4) { _rendererStates.Add(new RendererState(target)); } } } internal void Restore(string consumerName) { if (_restored || !Object.op_Implicit((Object)(object)_source)) { return; } _restored = true; bool flag = false; foreach (Transform item in _source.GetComponentsInChildren(true).OrderByDescending(Depth)) { if ((Object)(object)item != (Object)(object)_source.transform && !_transforms.Contains(item)) { Object.DestroyImmediate((Object)(object)((Component)item).gameObject); flag = true; } } Light[] componentsInChildren = _source.GetComponentsInChildren(true); foreach (Light val in componentsInChildren) { if (!_lights.Contains(val)) { Object.DestroyImmediate((Object)(object)val); flag = true; } } ParticleSystem[] componentsInChildren2 = _source.GetComponentsInChildren(true); foreach (ParticleSystem val2 in componentsInChildren2) { if (!_particles.Contains(val2)) { Object.DestroyImmediate((Object)(object)val2); flag = true; } } foreach (RendererState rendererState in _rendererStates) { flag |= rendererState.Restore(); } foreach (ParticleState particleState in _particleStates) { flag |= particleState.Restore(); } foreach (LightState lightState in _lightStates) { flag |= lightState.Restore(); } foreach (TransformState transformState in _transformStates) { flag |= transformState.Restore(); } if (flag) { RootboundWitchPlugin.Log.LogWarning((object)(consumerName + " attempted to alter source prefab " + ((Object)_source).name + "; Rootbound restored the source before registration completed.")); } } private static int Depth(Transform transform) { int num = 0; Transform val = transform; while ((Object)(object)val != (Object)null) { num++; val = val.parent; } return num; } } private static readonly Color DeadStone = new Color(0.2f, 0.19f, 0.16f, 1f); private static readonly Color DeadMoss = new Color(0.23f, 0.31f, 0.17f, 1f); internal static SourceVisualSnapshot CaptureSource(GameObject source) { return new SourceVisualSnapshot(source); } internal static void Apply(GameObject itemPrefab) { //IL_004a: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: 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_00b8: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)itemPrefab)) { return; } Light[] componentsInChildren = itemPrefab.GetComponentsInChildren(true); foreach (Light obj in componentsInChildren) { ((Behaviour)obj).enabled = false; obj.intensity = 0f; } ParticleSystem[] componentsInChildren2 = itemPrefab.GetComponentsInChildren(true); foreach (ParticleSystem obj2 in componentsInChildren2) { obj2.Stop(true, (ParticleSystemStopBehavior)0); EmissionModule emission = obj2.emission; ((EmissionModule)(ref emission)).enabled = false; } Material val = null; Renderer[] componentsInChildren3 = itemPrefab.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren3) { Material[] sharedMaterials = val2.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; int num = 0; int num2 = 0; for (int j = 0; j < sharedMaterials.Length; j++) { if (Object.op_Implicit((Object)(object)sharedMaterials[j])) { num++; Material val3 = new Material(sharedMaterials[j]); KillEmission(val3); bool flag = MuteRedCore(val3); ((Object)val3).name = ((Object)sharedMaterials[j]).name + (flag ? "_RootboundDeadCore" : "_RootboundDead"); if (flag) { num2++; } array[j] = val3; if ((Object)(object)val == (Object)null && !flag) { val = val3; } } } val2.sharedMaterials = array; if (num > 0 && num2 == num && !((Object)((Component)val2).gameObject).name.StartsWith("Rootbound_DeadCore_", StringComparison.Ordinal)) { ((Object)((Component)val2).gameObject).name = "Rootbound_DeadCore_" + ((Object)((Component)val2).gameObject).name; } } if ((Object)(object)val != (Object)null) { Material material = CreateProceduralMaterial(val, "RootboundSproutMaterial", DeadMoss); Material material2 = CreateProceduralMaterial(val, "RootboundOvergrowthMaterial", new Color(0.16f, 0.075f, 0.028f, 1f)); Transform parent = CreateGrowthAxis(FindEquippedVisualRoot(itemPrefab.transform)); AddRootOvergrowth(parent, material2); AddSprout(parent, new Vector3(0.045f, 0.4f, 0f), 0.18f, material, 18f); AddSprout(parent, new Vector3(-0.035f, 0.7f, 0.025f), 0.15f, material, -23f); AddSprout(parent, new Vector3(0.035f, 0.99f, -0.025f), 0.13f, material, 41f); } } internal static Transform FindEquippedVisualRoot(Transform itemRoot) { //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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: 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) List list = new List(); List list2 = new List(); Transform[] componentsInChildren = ((Component)itemRoot).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)(object)itemRoot)) { if (((Object)val).name.Equals("attach", StringComparison.OrdinalIgnoreCase)) { list.Add(val); } else if (((Object)val).name.StartsWith("attach_", StringComparison.OrdinalIgnoreCase)) { list2.Add(val); } } } List list3 = ((list.Count > 0) ? list : list2); if (list3.Count == 0) { return itemRoot; } Transform result = list3[0]; float num = -1f; foreach (Transform item in list3) { if (TryGetLocalVisualBounds(item, out var bounds)) { Vector3 size = ((Bounds)(ref bounds)).size; float num2 = Mathf.Max(size.x, Mathf.Max(size.y, size.z)) * Mathf.Max(0.001f, size.x + size.y + size.z); if (num2 > num) { num = num2; result = item; } } } return result; } internal static Transform CreateGrowthAxis(Transform visualRoot) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //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) //IL_004b: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00e6: 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_00ee: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Rootbound_OvergrowthAxis"); val.transform.SetParent(visualRoot, false); if (!TryGetLocalVisualBounds(visualRoot, out var bounds)) { val.transform.localRotation = Quaternion.FromToRotation(Vector3.up, Vector3.forward); return val.transform; } Vector3 size = ((Bounds)(ref bounds)).size; Vector3 val2 = ((size.x >= size.y && size.x >= size.z) ? Vector3.right : ((size.z >= size.y) ? Vector3.forward : Vector3.up)); float num = AxisValue(((Bounds)(ref bounds)).min, val2); float num2 = AxisValue(((Bounds)(ref bounds)).max, val2); float num3 = Mathf.Max(0.25f, num2 - num); float num4 = num3 * 0.055f; float num5 = Mathf.Max(0.2f, num3 - num4 * 2f) / 1.02f; Vector3 val3 = ((Bounds)(ref bounds)).center - val2 * AxisValue(((Bounds)(ref bounds)).center, val2); val.transform.localPosition = val3 + val2 * (num + num4 - 0.16f * num5); val.transform.localRotation = Quaternion.FromToRotation(Vector3.up, val2); val.transform.localScale = new Vector3(1f, num5, 1f); RootboundWitchPlugin.Log.LogInfo((object)$"Rootbound Crook overgrowth aligned to {AxisName(val2)} across {num3:0.000} local metres."); return val.transform; } internal static void RemoveGeneratedOvergrowth(GameObject itemPrefab) { if (!Object.op_Implicit((Object)(object)itemPrefab)) { return; } Transform[] array = (from transform in itemPrefab.GetComponentsInChildren(true) where (Object)(object)transform != (Object)(object)itemPrefab.transform && ((Object)transform).name.Equals("Rootbound_OvergrowthAxis", StringComparison.Ordinal) select transform).ToArray(); foreach (Transform val in array) { if (Object.op_Implicit((Object)(object)val)) { Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } } RootboundWitchPlugin.Log.LogInfo((object)"Mycelial Crook shed the generated walnut overgrowth; only the reclaimed Surtling-staff structure remains."); } private static bool TryGetLocalVisualBounds(Transform root, out Bounds bounds) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) bool found = false; bounds = new Bounds(Vector3.zero, Vector3.zero); MeshFilter[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (MeshFilter val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val.sharedMesh) && !((Object)((Component)val).gameObject).name.StartsWith("Rootbound_", StringComparison.Ordinal)) { EncapsulateBounds(root, ((Component)val).transform, val.sharedMesh.bounds, ref bounds, ref found); } } SkinnedMeshRenderer[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val2 in componentsInChildren2) { if (Object.op_Implicit((Object)(object)val2.sharedMesh) && !((Object)((Component)val2).gameObject).name.StartsWith("Rootbound_", StringComparison.Ordinal)) { EncapsulateBounds(root, ((Component)val2).transform, ((Renderer)val2).localBounds, ref bounds, ref found); } } return found; } private static void EncapsulateBounds(Transform target, Transform source, Bounds sourceBounds, ref Bounds aggregate, ref bool found) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_004d: 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_0059: Unknown result type (might be due to invalid IL or missing references) Vector3 center = ((Bounds)(ref sourceBounds)).center; Vector3 extents = ((Bounds)(ref sourceBounds)).extents; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Vector3 val = center + Vector3.Scale(extents, new Vector3((float)i, (float)j, (float)k)); Vector3 val2 = target.InverseTransformPoint(source.TransformPoint(val)); if (!found) { aggregate = new Bounds(val2, Vector3.zero); found = true; } else { ((Bounds)(ref aggregate)).Encapsulate(val2); } } } } } private static float AxisValue(Vector3 value, Vector3 axis) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Vector3.Dot(value, axis); } private static string AxisName(Vector3 axis) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (axis == Vector3.right) { return "local X"; } if (axis == Vector3.forward) { return "local Z"; } return "local Y"; } private static void AddRootOvergrowth(Transform parent, Material material) { //IL_0073: 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) //IL_00df: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) List list = new List(); List list2 = new List(); for (int i = 0; i < 22; i++) { float num = (float)i / 21f; float num2 = num * (float)Math.PI * 5.1f; float num3 = Mathf.Lerp(0.043f, 0.065f, Mathf.Sin(num * (float)Math.PI) * 0.65f); list.Add(new Vector3(Mathf.Sin(num2) * num3, Mathf.Lerp(0.16f, 1.18f, num), Mathf.Cos(num2) * num3)); list2.Add(0.016f + Mathf.Sin(num * (float)Math.PI * 4f) * 0.0035f); } AddTube(parent, "Rootbound_ConstrictionRoot", list, list2, 5, material); AddBranch(parent, material, "Rootbound_RootArmA", (IList)(object)new Vector3[4] { new Vector3(0.015f, 0.43f, 0f), new Vector3(0.095f, 0.52f, 0.025f), new Vector3(0.17f, 0.62f, 0.065f), new Vector3(0.22f, 0.73f, 0.1f) }, 0.029f); AddBranch(parent, material, "Rootbound_RootArmB", (IList)(object)new Vector3[4] { new Vector3(-0.01f, 0.69f, 0.01f), new Vector3(-0.1f, 0.78f, -0.035f), new Vector3(-0.17f, 0.91f, -0.07f), new Vector3(-0.2f, 1.03f, -0.11f) }, 0.026f); AddBranch(parent, material, "Rootbound_RootArmC", (IList)(object)new Vector3[3] { new Vector3(0.02f, 0.91f, -0.015f), new Vector3(0.09f, 1f, -0.065f), new Vector3(0.13f, 1.1f, -0.12f) }, 0.022f); } private static void AddBranch(Transform parent, Material material, string name, IList centers, float baseRadius) { List list = new List(); for (int i = 0; i < centers.Count; i++) { float num = (float)i / (float)Mathf.Max(1, centers.Count - 1); list.Add(Mathf.Lerp(baseRadius, 0.004f, num)); } AddTube(parent, name, centers, list, 5, material); } private static void AddTube(Transform parent, string name, IList centers, IList radii, int sides, Material material) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.AddComponent().sharedMesh = BuildTubeMesh(name + "Mesh", centers, radii, sides); MeshRenderer obj = val.AddComponent(); ((Renderer)obj).sharedMaterial = material; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)obj).receiveShadows = true; } private static Mesh BuildTubeMesh(string name, IList centers, IList radii, int sides) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_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) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0081: Unknown result type (might be due to invalid IL or missing references) //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_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown //IL_009f: 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_00ad: 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_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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) List list = new List(); List list2 = new List(); for (int i = 0; i < centers.Count; i++) { Vector3 val = centers[Mathf.Max(0, i - 1)]; Vector3 val2 = centers[Mathf.Min(centers.Count - 1, i + 1)] - val; Vector3 normalized = ((Vector3)(ref val2)).normalized; Vector3 val3 = Vector3.Cross(normalized, Vector3.up); if (((Vector3)(ref val3)).sqrMagnitude < 0.001f) { val3 = Vector3.right; } ((Vector3)(ref val3)).Normalize(); val2 = Vector3.Cross(normalized, val3); Vector3 normalized2 = ((Vector3)(ref val2)).normalized; for (int j = 0; j < sides; j++) { float num = (float)j * (float)Math.PI * 2f / (float)sides; list.Add(centers[i] + (val3 * Mathf.Cos(num) + normalized2 * Mathf.Sin(num)) * radii[i]); } } for (int k = 0; k < centers.Count - 1; k++) { for (int l = 0; l < sides; l++) { int num2 = (l + 1) % sides; int item = k * sides + l; int item2 = k * sides + num2; int item3 = (k + 1) * sides + num2; int item4 = (k + 1) * sides + l; list2.Add(item); list2.Add(item2); list2.Add(item3); list2.Add(item); list2.Add(item3); list2.Add(item4); } } Mesh val4 = new Mesh { name = name }; val4.SetVertices(list); val4.SetTriangles(list2, 0); val4.RecalculateNormals(); val4.RecalculateBounds(); return val4; } private static void KillEmission(Material material) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); } if (material.HasProperty("_EmissionMap")) { material.SetTexture("_EmissionMap", (Texture)null); } material.DisableKeyword("_EMISSION"); material.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)4; } private static bool MuteRedCore(Material material) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0044: 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) //IL_0059: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[2] { "_Color", "_BaseColor" }; foreach (string text in array) { if (material.HasProperty(text)) { Color color = material.GetColor(text); if (color.r > color.g * 1.15f && color.r > color.b * 1.15f) { SetBaseColor(material, DeadStone); return true; } } } if (((Object)material).name.IndexOf("surtling", StringComparison.OrdinalIgnoreCase) < 0 && ((Object)material).name.IndexOf("ember", StringComparison.OrdinalIgnoreCase) < 0) { return ((Object)material).name.IndexOf("firecore", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static Material CreateProceduralMaterial(Material source, string name, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0015: Expected O, but got Unknown Material val = new Material(source) { name = name }; PrepareProceduralMaterial(val, color); return val; } private static void PrepareProceduralMaterial(Material material, Color color) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) KillEmission(material); Texture2D val = BuildProceduralTexture(((Object)material).name + "Texture", color); if (material.HasProperty("_MainTex")) { material.SetTexture("_MainTex", (Texture)(object)val); } if (material.HasProperty("_BaseMap")) { material.SetTexture("_BaseMap", (Texture)(object)val); } if (material.HasProperty("_BumpMap")) { material.SetTexture("_BumpMap", (Texture)null); } if (material.HasProperty("_MetallicGlossMap")) { material.SetTexture("_MetallicGlossMap", (Texture)null); } if (material.HasProperty("_Metallic")) { material.SetFloat("_Metallic", 0f); } if (material.HasProperty("_Glossiness")) { material.SetFloat("_Glossiness", 0.18f); } if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 0f); } if (material.HasProperty("_Mode")) { material.SetFloat("_Mode", 0f); } if (material.HasProperty("_SrcBlend")) { material.SetInt("_SrcBlend", 1); } if (material.HasProperty("_DstBlend")) { material.SetInt("_DstBlend", 0); } if (material.HasProperty("_ZWrite")) { material.SetInt("_ZWrite", 1); } material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = -1; SetBaseColor(material, color); if (material.HasProperty("_TintColor")) { material.SetColor("_TintColor", color); } float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(color, ref num, ref num2, ref num3); if (material.HasProperty("_Hue")) { material.SetFloat("_Hue", num); } if (material.HasProperty("_Saturation")) { material.SetFloat("_Saturation", num2); } if (material.HasProperty("_Value")) { material.SetFloat("_Value", num3); } } private static Texture2D BuildProceduralTexture(string name, Color baseColour) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0055: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(4, 4, (TextureFormat)4, false) { name = name, filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)0, hideFlags = (HideFlags)61 }; Color[] array = (Color[])(object)new Color[16]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { float num = (float)((j * 5 + i * 3 + (j ^ i)) % 5 - 2) * 0.055f; array[i * 4 + j] = new Color(Mathf.Clamp01(baseColour.r * (1f + num)), Mathf.Clamp01(baseColour.g * (1f + num)), Mathf.Clamp01(baseColour.b * (1f + num)), 1f); } } val.SetPixels(array); val.Apply(false, true); return val; } private static void SetBaseColor(Material material, Color color) { //IL_0013: 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) if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", color); } } private static void AddSprout(Transform parent, Vector3 localPosition, float height, Material material, float yaw) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Rootbound_LowPolySprout"); val.transform.SetParent(parent, false); val.transform.localPosition = localPosition; val.transform.localRotation = Quaternion.Euler(0f, yaw, 8f); Mesh sharedMesh = BuildCrossedSprout(height); val.AddComponent().sharedMesh = sharedMesh; MeshRenderer obj = val.AddComponent(); ((Renderer)obj).sharedMaterial = material; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)obj).receiveShadows = true; } private static Mesh BuildCrossedSprout(float height) { //IL_002a: 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_0046: 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) //IL_006b: 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_0087: 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_00b5: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0136: 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_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown float num = height * 0.09f; float num2 = height * 0.3f; List vertices = new List(); List list = new List(); AddQuad(vertices, list, new Vector3(0f - num, 0f, 0f), new Vector3(num, 0f, 0f), new Vector3(num, height, 0f), new Vector3(0f - num, height, 0f)); AddQuad(vertices, list, new Vector3(0f, 0f, 0f - num), new Vector3(0f, 0f, num), new Vector3(0f, height, num), new Vector3(0f, height, 0f - num)); float num3 = height * 0.62f; AddQuad(vertices, list, new Vector3(0f, num3, 0f), new Vector3(num2, num3 + num2 * 0.22f, 0f), new Vector3(num2 * 1.15f, num3 + num2 * 0.48f, 0f), new Vector3(num2 * 0.15f, num3 + num2 * 0.3f, 0f)); AddQuad(vertices, list, new Vector3(0f, num3 + num2 * 0.18f, 0f), new Vector3(0f - num2, num3 + num2 * 0.4f, 0f), new Vector3((0f - num2) * 1.15f, num3 + num2 * 0.66f, 0f), new Vector3((0f - num2) * 0.15f, num3 + num2 * 0.48f, 0f)); Mesh val = new Mesh { name = "Rootbound_LowPolySproutMesh" }; val.SetVertices(vertices); val.SetTriangles(list, 0); val.RecalculateNormals(); val.RecalculateBounds(); return val; } private static void AddQuad(List vertices, List triangles, Vector3 a, Vector3 b, Vector3 c, Vector3 d) { //IL_0008: 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) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) int count = vertices.Count; vertices.Add(a); vertices.Add(b); vertices.Add(c); vertices.Add(d); triangles.Add(count); triangles.Add(count + 1); triangles.Add(count + 2); triangles.Add(count); triangles.Add(count + 2); triangles.Add(count + 3); triangles.Add(count + 2); triangles.Add(count + 1); triangles.Add(count); triangles.Add(count + 3); triangles.Add(count + 2); triangles.Add(count); } } internal static class RootboundAura { private const string EffectName = "SE_RootboundSharedVigor"; private static StatusEffect _effect; private static float _nextUpdate; internal static void Register(Sprite icon) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown if (!((Object)(object)_effect != (Object)null)) { SE_Stats val = ScriptableObject.CreateInstance(); ((Object)val).name = "SE_RootboundSharedVigor"; ((StatusEffect)val).m_name = "$se_rootbound_shared_vigor"; ((StatusEffect)val).m_tooltip = "$se_rootbound_shared_vigor_tooltip"; ((StatusEffect)val).m_icon = icon; ((StatusEffect)val).m_hidden = false; ((StatusEffect)val).m_effectsOnlyOnPlayer = true; ((StatusEffect)val).m_ttl = 2.5f; val.m_staminaRegenMultiplier = Mathf.Max(0f, RootboundWitchPlugin.SharedStaminaMultiplier.Value); ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val, false)); _effect = (StatusEffect)(object)val; } } internal static void UpdateLocal(Player receiver) { if (Time.time < _nextUpdate) { return; } _nextUpdate = Time.time + 0.75f; if (!((Object)(object)receiver == (Object)null) && !((Character)receiver).IsDead() && !((Object)(object)_effect == (Object)null)) { SEMan sEMan = ((Character)receiver).GetSEMan(); if (!RootboundWitchPlugin.EnableSharedStaminaAura.Value) { sEMan.RemoveStatusEffect(_effect.NameHash(), true); } else if (HasEmitterInRange(receiver)) { sEMan.AddStatusEffect(_effect, true, 0, 0f, (short)(-1)); } else { sEMan.RemoveStatusEffect(_effect.NameHash(), true); } } } internal static bool ShouldSlowWearer(Player wearer) { //IL_003d: 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) if (!RootboundWitchPlugin.EnableSharedStaminaAura.Value || !IsEmitter(wearer)) { return false; } float num = AuraRadiusSquared(); List allPlayers = Player.GetAllPlayers(); for (int i = 0; i < allPlayers.Count; i++) { Player val = allPlayers[i]; if (IsEligibleOtherPlayer(wearer, val)) { Vector3 val2 = ((Component)val).transform.position - ((Component)wearer).transform.position; if (((Vector3)(ref val2)).sqrMagnitude <= num) { return true; } } } return false; } private static bool HasEmitterInRange(Player receiver) { //IL_002f: 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_003f: 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) float num = AuraRadiusSquared(); List allPlayers = Player.GetAllPlayers(); for (int i = 0; i < allPlayers.Count; i++) { Player val = allPlayers[i]; if (IsEligibleOtherPlayer(receiver, val) && IsEmitter(val)) { Vector3 val2 = ((Component)val).transform.position - ((Component)receiver).transform.position; if (((Vector3)(ref val2)).sqrMagnitude <= num) { return true; } } } return false; } private static bool IsEmitter(Player player) { if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { return false; } return RootboundNetworkState.HasKinship(player); } private static bool IsEligibleOtherPlayer(Player origin, Player candidate) { if ((Object)(object)candidate != (Object)null && (Object)(object)candidate != (Object)(object)origin) { return !((Character)candidate).IsDead(); } return false; } private static float AuraRadiusSquared() { float num = Mathf.Max(0f, RootboundWitchPlugin.SharedStaminaRadius.Value); return num * num; } } internal static class RootboundBackpackIntegration { private const string BackpacksGuid = "org.bepinex.plugins.backpacks"; private const string ConfigFileName = "Backpacks.RootboundWitch.generated.yml"; private const string Definition = "# Generated by ADARC Rootbound Witch. This namespaced file belongs to the mod.\n\"Rootbound Satchel\":\n description: \"A small pack of bark, hide and dead village-root. It grows with the same four-biome pilgrimage as the witch.\"\n size: 4x3\n unique: global\n weight factor: 0.80\n appearance:\n Sleepbag: hidden\n BackpackStrapTop: hidden\n MetalclipLeft: hidden\n MetalclipFrontRight: hidden\n MetalclipFrontLeft: hidden\n BackpackBody: 435332\n BackpackFlap: 26351f\n PouchFront: 53643c\n PouchLeft: 53643c\n crafting:\n station: Workbench\n level: 1\n costs:\n Entrails: 8\n TrophyDraugr: 1\n LeatherScraps: 6\n FineWood: 4\n upgrade:\n 1:\n Carapace: 8\n Softtissue: 6\n Eitr: 4\n size: 5x3\n 2:\n AskHide: 8\n CelestialFeather: 4\n CharredBone: 8\n size: 5x4\n 3:\n Frostcore: 3\n Frostwood: 12\n MooseHide: 6\n size: 6x4\n"; internal static void InstallAndReload() { if (!Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.backpacks", out var value) || (Object)(object)value.Instance == (Object)null) { throw new InvalidOperationException("Smoothbrain Backpacks 1.3.8 is a required Rootbound Witch dependency but is not loaded."); } File.WriteAllText(Path.Combine(Paths.ConfigPath, "Backpacks.RootboundWitch.generated.yml"), "# Generated by ADARC Rootbound Witch. This namespaced file belongs to the mod.\n\"Rootbound Satchel\":\n description: \"A small pack of bark, hide and dead village-root. It grows with the same four-biome pilgrimage as the witch.\"\n size: 4x3\n unique: global\n weight factor: 0.80\n appearance:\n Sleepbag: hidden\n BackpackStrapTop: hidden\n MetalclipLeft: hidden\n MetalclipFrontRight: hidden\n MetalclipFrontLeft: hidden\n BackpackBody: 435332\n BackpackFlap: 26351f\n PouchFront: 53643c\n PouchLeft: 53643c\n crafting:\n station: Workbench\n level: 1\n costs:\n Entrails: 8\n TrophyDraugr: 1\n LeatherScraps: 6\n FineWood: 4\n upgrade:\n 1:\n Carapace: 8\n Softtissue: 6\n Eitr: 4\n size: 5x3\n 2:\n AskHide: 8\n CelestialFeather: 4\n CharredBone: 8\n size: 5x4\n 3:\n Frostcore: 3\n Frostwood: 12\n MooseHide: 6\n size: 6x4\n"); ConfigEntryBase val = null; foreach (KeyValuePair item in value.Instance.Config) { if (string.Equals(item.Key.Section, "2 - Backpack", StringComparison.OrdinalIgnoreCase) && string.Equals(item.Key.Key, "Use External YAML", StringComparison.OrdinalIgnoreCase)) { val = item.Value; break; } } if (val == null) { throw new InvalidOperationException("Backpacks loaded, but its 'Use External YAML' setting was not found."); } val.SetSerializedValue("On"); value.Instance.Config.Save(); Type type = ((object)value.Instance).GetType().Assembly.GetType("Backpacks.ConfigLoader", throwOnError: false); MethodInfo? obj = ((type != null) ? type.GetMethod("reloadConfigFile", BindingFlags.Static | BindingFlags.Public) : null); if (obj == null) { throw new MissingMethodException("Backpacks.ConfigLoader.reloadConfigFile"); } obj.Invoke(null, null); PermafrostVisuals.BindBackpackApi(((object)value.Instance).GetType().Assembly); RootboundWitchPlugin.Log.LogInfo((object)"Rootbound Satchel definition installed through Smoothbrain Backpacks and reloaded."); } } internal static class RootboundCharm { private static StatusEffect _effect; internal static void Register() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindJormundling(); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("The live Jormundling item ($item_trinketflametaleitr) was not found."); } CustomItem val2 = new CustomItem("RootboundCharm", ((Object)val).name); SharedData shared = val2.ItemDrop.m_itemData.m_shared; _effect = CreateEffect((shared.m_icons != null && shared.m_icons.Length != 0) ? shared.m_icons[0] : null); shared.m_name = "$item_rootbound_charm"; shared.m_description = "$item_rootbound_charm_desc"; shared.m_itemType = (ItemType)24; shared.m_maxQuality = 1; shared.m_maxStackSize = 1; shared.m_equipStatusEffect = _effect; ItemManager.Instance.AddItem(val2); AddRecipe(val2.ItemDrop); } private static StatusEffect CreateEffect(Sprite icon) { //IL_003f: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown SE_Stats val = ScriptableObject.CreateInstance(); ((Object)val).name = "SE_RootboundCharm"; ((StatusEffect)val).m_name = "$se_rootbound_charm"; ((StatusEffect)val).m_tooltip = "$se_rootbound_charm_tooltip"; ((StatusEffect)val).m_icon = icon; ((StatusEffect)val).m_hidden = false; ((StatusEffect)val).m_effectsOnlyOnPlayer = true; val.m_skillLevel = (SkillType)9; val.m_skillLevelModifier = RootboundWitchPlugin.CharmElementalMagic.Value; val.m_skillLevel2 = (SkillType)10; val.m_skillLevelModifier2 = RootboundWitchPlugin.CharmBloodMagic.Value; val.m_maxMaxFallSpeed = 5f; val.m_fallDamageModifier = -1f; ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val, false)); return (StatusEffect)(object)val; } private static GameObject FindJormundling() { if ((Object)(object)ObjectDB.instance != (Object)null) { GameObject val = ((IEnumerable)ObjectDB.instance.m_items).FirstOrDefault((Func)delegate(GameObject prefab) { ItemDrop val2 = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent() : null); return (Object)(object)val2 != (Object)null && val2.m_itemData != null && val2.m_itemData.m_shared != null && string.Equals(val2.m_itemData.m_shared.m_name, "$item_trinketflametaleitr", StringComparison.Ordinal); }); if (Object.op_Implicit((Object)(object)val)) { return val; } } return new string[3] { "TrinketFlametalEitr", "trinketflametaleitr", "Jormundling" }.Select(RootboundContent.FindPrefab).FirstOrDefault((Func)((GameObject prefab) => Object.op_Implicit((Object)(object)prefab))); } private static void AddRecipe(ItemDrop result) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown Recipe val = ScriptableObject.CreateInstance(); ((Object)val).name = "Recipe_RootboundCharm"; val.m_item = result; val.m_amount = 1; val.m_enabled = true; val.m_minStationLevel = 1; GameObject val2 = RootboundContent.FindPrefab("piece_workbench"); val.m_craftingStation = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); val.m_resources = (Requirement[])(object)new Requirement[4] { Requirement("Entrails", 10), Requirement("TrophyDraugr", 1), Requirement("AncientSeed", 3), Requirement("FineWood", 8) }; if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val, false, false))) { throw new InvalidOperationException("Jotunn rejected Recipe_RootboundCharm"); } } private static Requirement Requirement(string prefabName, int amount) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown GameObject val = RootboundContent.FindPrefab(prefabName); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("Rootbound Charm material is absent: " + prefabName); } return new Requirement { m_resItem = val2, m_amount = amount, m_amountPerLevel = 0, m_recover = true, m_upgraderResource = false }; } } [HarmonyPatch(typeof(Player), "ActivateGuardianPower")] internal static class RootboundCharmGuardianCooldownPatch { private static void Prefix(Player __instance, out float __state) { __state = __instance.m_guardianPowerCooldown; } private static void Postfix(Player __instance, float __state) { if (__state <= 0f && __instance.m_guardianPowerCooldown > 0f && RootboundState.IsCharmEquipped(__instance)) { __instance.m_guardianPowerCooldown = Mathf.Max(0f, RootboundWitchPlugin.CharmPowerCooldownSeconds.Value); } } } internal static class RootboundCharterAbomination { private const string SummonPrefabName = "RootboundCharterAbominationCompanion"; private static readonly FieldRef AttackCharacter = AccessTools.FieldRefAccess("m_character"); private static readonly FieldRef AttackWeapon = AccessTools.FieldRefAccess("m_weapon"); private static GameObject _summonPrefab; internal static void Register() { if (!TryRegisterCompanionPrefab()) { RootboundWitchPlugin.Log.LogWarning((object)"The Galdr Charter registered, but its living Abomination source is not loaded yet; the mod will retry when the Charter is used."); } } internal static void ConfigureSummonAttack(Attack attack, SharedData roots, float eitr) { if (roots != null && roots.m_attack != null) { attack.m_startEffect = roots.m_attack.m_startEffect; attack.m_triggerEffect = roots.m_attack.m_triggerEffect; attack.m_burstEffect = roots.m_attack.m_burstEffect; attack.m_trailStartEffect = roots.m_attack.m_trailStartEffect; } attack.m_attackEitr = eitr; attack.m_attackEitrAdd = 0f; attack.m_attackHealth = 0f; attack.m_attackHealthPercentage = 0f; attack.m_projectiles = 1; attack.m_projectileBursts = 1; attack.m_damageMultiplier = 0f; attack.m_forceMultiplier = 0f; } internal static bool IsOurAttack(Attack attack) { if (attack != null) { return RootboundState.HasPrefab(AttackWeapon.Invoke(attack), "RootboundGaldrCharter"); } return false; } internal static void Use(Attack attack) { //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_007e: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) Humanoid obj = AttackCharacter.Invoke(attack); Player val = (Player)(object)((obj is Player) ? obj : null); if (!RootboundSummonRecall.HasLocalAttackAuthority(val)) { return; } RootboundGaldrCharter.HasHandGaldr(val); if (!Object.op_Implicit((Object)(object)_summonPrefab) && !TryRegisterCompanionPrefab()) { RootboundWitchPlugin.Log.LogError((object)"Galdr Charter summon requested, but the live Abomination prefab could not be loaded."); return; } if (attack.m_attackEitr <= 0.001f) { if (RootboundAbominationOwnership.Recall(val.GetPlayerID())) { RootboundState.Show("$msg_rootbound_abomination_recalled"); } return; } RootboundAbominationOwnership.Recall(val.GetPlayerID()); Vector3 val2 = FindSpawnPoint(val); RootboundAbominationOwnership.QueueSpawn(val, val2); if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.SpawnObject(val2, ((Component)val).transform.rotation, _summonPrefab); } else { GameObject obj2 = Object.Instantiate(_summonPrefab, val2, ((Component)val).transform.rotation); obj2.SetActive(true); RootboundAbominationOwnership component = obj2.GetComponent(); if ((Object)(object)component != (Object)null) { component.Assign(val); } } RootboundState.Show("$msg_rootbound_abomination_summoned"); } private static bool TryRegisterCompanionPrefab() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a8: 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_00b8: 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_00c8: 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) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_summonPrefab)) { return true; } GameObject val = RootboundContent.FindPrefab("Abomination"); if (!IsLivingAbomination(val)) { return false; } _summonPrefab = PrefabManager.Instance.CreateClonedPrefab("RootboundCharterAbominationCompanion", val); Character component = _summonPrefab.GetComponent(); MonsterAI component2 = _summonPrefab.GetComponent(); component.m_name = "$enemy_rootbound_abomination"; component.m_faction = (Faction)11; component.m_health = Mathf.Max(component.m_health, RootboundWitchPlugin.CharterAbominationBaseHealth.Value); component.m_regenAllHPTime = 240f; DamageModifiers damageModifiers = component.m_damageModifiers; damageModifiers.m_blunt = (DamageModifier)1; damageModifiers.m_slash = (DamageModifier)1; damageModifiers.m_pierce = (DamageModifier)5; damageModifiers.m_fire = (DamageModifier)1; damageModifiers.m_frost = (DamageModifier)1; damageModifiers.m_lightning = (DamageModifier)1; damageModifiers.m_poison = (DamageModifier)3; damageModifiers.m_spirit = (DamageModifier)3; damageModifiers.m_nonPlayer = (DamageModifier)1; component.m_damageModifiers = damageModifiers; ((BaseAI)component2).m_mistVision = true; ((BaseAI)component2).m_viewRange = Mathf.Max(((BaseAI)component2).m_viewRange, 60f); ((BaseAI)component2).m_hearRange = Mathf.Max(((BaseAI)component2).m_hearRange, 40f); component2.m_alertRange = Mathf.Max(component2.m_alertRange, 45f); component2.m_maxChaseDistance = Mathf.Max(component2.m_maxChaseDistance, 80f); component2.m_fleeIfLowHealth = 0f; component2.m_fleeIfHurtWhenTargetCantBeReached = false; CharacterDrop component3 = _summonPrefab.GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.m_drops.Clear(); } Tameable component4 = _summonPrefab.GetComponent(); if ((Object)(object)component4 != (Object)null) { component4.m_startsTamed = true; component4.m_commandable = false; component4.m_unsummonOnOwnerLogoutSeconds = 10f; } _summonPrefab.AddComponent(); PrefabManager.Instance.AddPrefab(new CustomPrefab(_summonPrefab, true)); RootboundWitchPlugin.Log.LogInfo((object)($"Charter Abomination cloned from {((Object)val).name}: base health {component.m_health}, " + $"level {RootboundWitchPlugin.CharterAbominationLevel.Value}, Mistlands vision, no drops.")); return true; } private static bool IsLivingAbomination(GameObject prefab) { if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null && (Object)(object)prefab.GetComponent() != (Object)null) { return (Object)(object)prefab.GetComponent() != (Object)null; } return false; } private static Vector3 FindSpawnPoint(Player player) { //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_0032: 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_003c: 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_003e: 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_0083: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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) float num = Mathf.Max(15f, RootboundWitchPlugin.CharterAbominationFollowDistance.Value + 2f); Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * num; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val + Vector3.up * 10f, Vector3.down, ref val2, 30f, -1, (QueryTriggerInteraction)1)) { val = ((RaycastHit)(ref val2)).point + Vector3.up * 0.2f; } return val; } } internal sealed class RootboundAbominationOwnership : MonoBehaviour { private sealed class PendingSpawn { internal readonly long OwnerId; internal readonly Vector3 Position; internal readonly float ExpiresAt; internal PendingSpawn(long ownerId, Vector3 position, float expiresAt) { //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) OwnerId = ownerId; Position = position; ExpiresAt = expiresAt; } } private const string OwnerKey = "ADARC_RootboundAbominationOwner"; private const string StrengthenedKey = "ADARC_RootboundAbominationStrengthened"; private static readonly HashSet Active = new HashSet(); private static readonly List Pending = new List(); private ZNetView _view; private MonsterAI _ai; private Character _character; private long _ownerId; private float _nextFollowCheck; private float _nextRegeneration; private float _standingIdleSoundInterval; private float _standingIdleSoundChance; private bool _capturedStandingVoice; private void Awake() { _view = ((Component)this).GetComponent(); _ai = ((Component)this).GetComponent(); _character = ((Component)this).GetComponent(); CaptureStandingVoice(); Active.Add(this); TryClaimPendingSpawn(); } private void OnDestroy() { Active.Remove(this); } private void Update() { UpdateWalkingVoice(); if (Time.time >= _nextFollowCheck) { _nextFollowCheck = Time.time + 2f; TryClaimPendingSpawn(); AttachToOwner(); } if (Time.time >= _nextRegeneration) { _nextRegeneration = Time.time + 1f; Regenerate(); } } private void CaptureStandingVoice() { if (!((Object)(object)_ai == (Object)null) && !_capturedStandingVoice) { _standingIdleSoundInterval = ((BaseAI)_ai).m_idleSoundInterval; _standingIdleSoundChance = ((BaseAI)_ai).m_idleSoundChance; _capturedStandingVoice = true; } } private void UpdateWalkingVoice() { //IL_0032: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_ai == (Object)null) && !((Object)(object)_character == (Object)null)) { CaptureStandingVoice(); if (_capturedStandingVoice) { Vector3 velocity = _character.GetVelocity(); bool flag = velocity.x * velocity.x + velocity.z * velocity.z > 0.09f; ((BaseAI)_ai).m_idleSoundInterval = _standingIdleSoundInterval; ((BaseAI)_ai).m_idleSoundChance = (flag ? 0f : _standingIdleSoundChance); } } } internal static void QueueSpawn(Player player, Vector3 position) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { long ownerId = player.GetPlayerID(); Pending.RemoveAll((PendingSpawn request) => request.OwnerId == ownerId || request.ExpiresAt <= Time.time); Pending.Add(new PendingSpawn(ownerId, position, Time.time + 20f)); } } internal void Assign(Player player) { if (!((Object)(object)player == (Object)null)) { _ownerId = player.GetPlayerID(); if ((Object)(object)_view != (Object)null && _view.GetZDO() != null) { _view.GetZDO().Set("ADARC_RootboundAbominationOwner", _ownerId); } Configure(player); } } internal static bool Recall(long playerId) { //IL_0060: 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) bool result = false; Player val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player player) => (Object)(object)player != (Object)null && player.GetPlayerID() == playerId)); RootboundAbominationOwnership[] array = Active.ToArray(); foreach (RootboundAbominationOwnership rootboundAbominationOwnership in array) { if (!((Object)(object)rootboundAbominationOwnership == (Object)null)) { long num2 = rootboundAbominationOwnership.OwnerId(); bool flag = num2 == 0L && (Object)(object)val != (Object)null && Vector3.Distance(((Component)rootboundAbominationOwnership).transform.position, ((Component)val).transform.position) <= 120f; if (num2 == playerId || flag) { rootboundAbominationOwnership.Kill(); result = true; } } } Pending.RemoveAll((PendingSpawn request) => request.OwnerId == playerId); return result; } private void AttachToOwner() { long ownerId = OwnerId(); Player val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player player) => (Object)(object)player != (Object)null && player.GetPlayerID() == ownerId)); if ((Object)(object)val != (Object)null) { Configure(val); } } private void Configure(Player owner) { if ((Object)(object)_view == (Object)null) { _view = ((Component)this).GetComponent(); } if ((Object)(object)_ai == (Object)null) { _ai = ((Component)this).GetComponent(); } if ((Object)(object)_character == (Object)null) { _character = ((Component)this).GetComponent(); } if ((Object)(object)_ai != (Object)null) { _ai.MakeTame(); _ai.SetFollowTarget(((Component)owner).gameObject); _ai.SetDespawnInDay(false); } if ((Object)(object)_character != (Object)null && (Object)(object)_view != (Object)null && _view.GetZDO() != null && _view.IsOwner()) { int num = Mathf.Max(1, RootboundWitchPlugin.CharterAbominationLevel.Value); if (_character.GetLevel() != num) { _character.SetLevel(num); } if (!_view.GetZDO().GetBool("ADARC_RootboundAbominationStrengthened", false)) { _character.SetHealth(_character.GetMaxHealth()); _view.GetZDO().Set("ADARC_RootboundAbominationStrengthened", true); } } } private void Regenerate() { if (!((Object)(object)_character == (Object)null) && !_character.IsDead() && !((Object)(object)_view == (Object)null) && _view.GetZDO() != null && _view.IsOwner()) { float num = _character.GetMaxHealth() - _character.GetHealth(); if (num > 0f) { _character.Heal(Mathf.Min(num, Mathf.Max(0f, RootboundWitchPlugin.CharterAbominationRegenPerSecond.Value)), true); } } } internal bool HoldAtFollowDistance(GameObject target) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)target) || (Object)(object)_character == (Object)null || Vector3.Distance(((Component)this).transform.position, target.transform.position) >= Mathf.Max(3f, RootboundWitchPlugin.CharterAbominationFollowDistance.Value)) { return false; } _character.SetMoveDir(Vector3.zero); _character.SetRun(false); _character.StopMovementXZ(); return true; } private long OwnerId() { if ((Object)(object)_view != (Object)null && _view.GetZDO() != null) { long num = _view.GetZDO().GetLong("ADARC_RootboundAbominationOwner", 0L); if (num != 0L) { _ownerId = num; } } return _ownerId; } private void TryClaimPendingSpawn() { if (OwnerId() != 0L || (Object)(object)_view == (Object)null || _view.GetZDO() == null || !_view.IsOwner()) { return; } Pending.RemoveAll((PendingSpawn pendingSpawn) => pendingSpawn.ExpiresAt <= Time.time); PendingSpawn request = (from candidate in Pending where Vector3.Distance(candidate.Position, ((Component)this).transform.position) <= 35f orderby Vector3.Distance(candidate.Position, ((Component)this).transform.position) select candidate).FirstOrDefault(); if (request != null) { Pending.Remove(request); Player val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player player) => (Object)(object)player != (Object)null && player.GetPlayerID() == request.OwnerId)); if ((Object)(object)val != (Object)null) { Assign(val); } } } private void Kill() { RootboundSummonRecall.Kill(((Object)(object)_character != (Object)null) ? _character : ((Component)this).GetComponent(), _view); } } [HarmonyPatch(typeof(BaseAI), "Follow")] internal static class RootboundAbominationFollowDistancePatch { private static bool Prefix(BaseAI __instance, GameObject go) { RootboundAbominationOwnership rootboundAbominationOwnership = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent() : null); if ((Object)(object)rootboundAbominationOwnership != (Object)null && rootboundAbominationOwnership.HoldAtFollowDistance(go)) { return false; } RootboundModerOwnership rootboundModerOwnership = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent() : null); if (!((Object)(object)rootboundModerOwnership == (Object)null)) { return !rootboundModerOwnership.HoldAtFollowDistance(go); } return true; } } internal static class RootboundContent { private sealed class TierMaterial { internal readonly int Quality; internal readonly string PrefabCandidates; internal readonly string LocalizationToken; internal readonly int Amount; internal TierMaterial(int quality, string prefabCandidates, string localizationToken, int amount) { Quality = quality; PrefabCandidates = prefabCandidates; LocalizationToken = localizationToken; Amount = amount; } } private sealed class SimpleMaterial { internal readonly string PrefabName; internal readonly string LocalizationToken; internal readonly int Amount; internal SimpleMaterial(string prefabName, string localizationToken, int amount) { PrefabName = prefabName; LocalizationToken = localizationToken; Amount = amount; } } internal const string SetName = "Rootbound"; internal const string HelmetPrefab = "RootboundMask"; internal const string ChestPrefab = "RootboundHarness"; internal const string LegsPrefab = "RootboundLeggings"; internal const string StaffPrefab = "RootboundCrook"; internal const string FrostedRootPrefab = "FrostedRoot"; internal const string MossbreadPrefab = "RootboundMossbread"; internal const string BilberryMashPrefab = "RootboundBilberryMash"; internal const string KvasturScrollPrefab = "RootboundKvasturScroll"; internal const string GaldrCharterPrefab = "RootboundGaldrCharter"; internal const string CharmPrefab = "RootboundCharm"; internal const string WispPrefab = "RootboundWisp"; internal const string ModerSigilPrefab = "RootboundModerSigil"; internal const string MushroomStaffPrefab = "MycelialCrook"; internal const string PetrifiedPickPrefab = "PetrifiedRootPick"; internal const string PetrifiedAxePrefab = "PetrifiedRootAxe"; private static bool _registered; private static StatusEffect _kinshipEffect; internal static void Register() { if (_registered) { return; } try { AddLocalizations(); _kinshipEffect = CreateKinshipEffect(); RootboundAura.Register(FindPrefab("HelmetRoot").GetComponent().m_itemData.GetIcon()); RootboundNetworkState.Register(FindPrefab("HelmetRoot").GetComponent().m_itemData.GetIcon()); if (RootboundWitchPlugin.EnableArmour.Value) { RegisterArmourSet(); BogWitchBackGrowth.Prepare(); } if (RootboundWitchPlugin.EnablePetrifiedTools.Value) { RegisterPetrifiedTools(); } if (RootboundWitchPlugin.EnableStaff.Value) { RegisterCrook(); RegisterFrostedRoot(); if (RootboundWitchPlugin.EnableMushroomStaff.Value) { RootboundMushroomStaff.Register(); } } if (RootboundWitchPlugin.EnableFoods.Value) { RegisterFoods(); } if (RootboundWitchPlugin.EnableKvasturScroll.Value) { RootboundKvasturScroll.Register(); } if (RootboundWitchPlugin.EnableCharm.Value) { RootboundCharm.Register(); } if (RootboundWitchPlugin.EnableRootboundWisp.Value) { RootboundWisp.Register(); } if (RootboundWitchPlugin.EnableGaldrCharter.Value) { RootboundGaldrCharter.Register(); RootboundMeatReclamation.Register(); if (RootboundWitchPlugin.EnableModerCompanion.Value) { RootboundModerCompanion.Register(); } } _registered = true; RootboundWitchPlugin.Log.LogInfo((object)"Rootbound content registered against the live vanilla prefab table."); } catch (Exception ex) { RootboundWitchPlugin.Log.LogError((object)("Rootbound content registration failed. No partial retry will be attempted this session.\n" + ex)); } finally { PrefabManager.OnVanillaPrefabsAvailable -= Register; } } private static void RegisterArmourSet() { RegisterArmourPiece("RootboundMask", "HelmetRoot", "$item_rootbound_mask", "$item_rootbound_mask_desc", 8, 6, 4, 2); RegisterArmourPiece("RootboundHarness", "ArmorRootChest", "$item_rootbound_harness", "$item_rootbound_harness_desc", 15, 12, 8, 4); RegisterArmourPiece("RootboundLeggings", "ArmorRootLegs", "$item_rootbound_leggings", "$item_rootbound_leggings_desc", 12, 10, 6, 3); } private static void RegisterArmourPiece(string prefabName, string sourcePrefab, string displayName, string description, int entrails, int carapace, int ashHide, int frostCore) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown EnsurePrefabExists(sourcePrefab); CustomItem val = new CustomItem(prefabName, sourcePrefab); SharedData shared = val.ItemDrop.m_itemData.m_shared; shared.m_name = displayName; shared.m_description = description; shared.m_setName = "Rootbound"; shared.m_setSize = 3; shared.m_setStatusEffect = _kinshipEffect; shared.m_maxQuality = 4; shared.m_armor = 26f; shared.m_armorPerLevel = 6f; shared.m_eitrRegenModifier = 0f; ItemManager.Instance.AddItem(val); AddTieredRecipe("Recipe_" + prefabName, val.ItemDrop, new TierMaterial(1, "Entrails", "$item_entrails", entrails), new TierMaterial(1, "TrophyDraugr", "$item_trophy_draugr", 1), new TierMaterial(2, "Carapace", "$item_carapace", carapace), new TierMaterial(2, "Softtissue", "$item_softtissue", Math.Max(4, carapace - 2)), new TierMaterial(2, "Eitr", "$item_eitr", Math.Max(3, carapace / 2)), new TierMaterial(3, "AskHide", "$item_askhide", ashHide), new TierMaterial(3, "CelestialFeather", "$item_celestialfeather", Math.Max(2, ashHide / 2)), new TierMaterial(3, "CharredBone", "$item_charredbone", ashHide), new TierMaterial(4, "FrostCore|Frostcore", "$item_frostcore", frostCore), new TierMaterial(4, "Frostwood|FrostWood|Timberwood", "$item_frostwood", frostCore * 4), new TierMaterial(4, "MooseHide|Moosehide", "$item_moosehide", frostCore * 2)); } private static void RegisterCrook() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) string text = FirstAvailablePrefab(RootboundWitchPlugin.StaffVisualCandidates.Value); if (text == null) { throw new InvalidOperationException("Neither the preferred Surtling Staff nor vanilla Staff of Embers visual prefab exists."); } GameObject obj = FindPrefab("StaffGreenRoots"); if (!Object.op_Implicit((Object)(object)obj)) { throw new InvalidOperationException("StaffGreenRoots is missing; the Rootbound Crook will not substitute a different spell."); } ReclaimedStaffVisual.SourceVisualSnapshot sourceVisualSnapshot = ReclaimedStaffVisual.CaptureSource(FindPrefab(text)); CustomItem val = new CustomItem("RootboundCrook", text); SharedData shared = val.ItemDrop.m_itemData.m_shared; SharedData shared2 = obj.GetComponent().m_itemData.m_shared; shared.m_name = "$item_rootbound_crook"; shared.m_description = "$item_rootbound_crook_desc"; shared.m_maxQuality = shared2.m_maxQuality; shared.m_skillType = shared2.m_skillType; shared.m_attack = ((shared2.m_attack != null) ? shared2.m_attack.Clone() : null); shared.m_secondaryAttack = RootboundCrookSecondary.BuildAttack(shared2); if (shared.m_attack != null) { shared.m_attack.m_projectiles = 3; shared.m_attack.m_projectileAccuracy = 0f; shared.m_attack.m_projectileAccuracyMin = 0f; shared.m_attack.m_attackHealth = 0f; shared.m_attack.m_attackHealthPercentage = 0f; shared.m_attack.m_attackHealthLowBlockUse = false; shared.m_attack.m_attackHealthReturnHit = 0f; } shared.m_secondaryAttack.m_attackHealth = 0f; shared.m_secondaryAttack.m_attackHealthPercentage = 0f; shared.m_secondaryAttack.m_attackHealthLowBlockUse = false; shared.m_secondaryAttack.m_attackHealthReturnHit = 0f; DraugrRotVisuals.ApplyToAttack(shared.m_attack); shared.m_damages = shared2.m_damages; shared.m_damagesPerLevel = shared2.m_damagesPerLevel; shared.m_attackForce = shared2.m_attackForce; shared.m_backstabBonus = shared2.m_backstabBonus; shared.m_attackStatusEffect = shared2.m_attackStatusEffect; shared.m_attackStatusEffectChance = shared2.m_attackStatusEffectChance; shared.m_hitEffect = shared2.m_hitEffect; shared.m_hitTerrainEffect = shared2.m_hitTerrainEffect; ReclaimedStaffVisual.Apply(val.ItemPrefab); sourceVisualSnapshot.Restore("Rootbound Crook"); ItemManager.Instance.AddItem(val); RootboundCrookSecondary.Register(obj); AddTieredRecipe("Recipe_RootboundCrook", val.ItemDrop, new TierMaterial(1, "Entrails", "$item_entrails", 12), new TierMaterial(1, "TrophyDraugr", "$item_trophy_draugr", 1), new TierMaterial(1, "AncientSeed", "$item_ancientseed", 3), new TierMaterial(1, "FineWood", "$item_finewood", 10), new TierMaterial(2, "Eitr", "$item_eitr", 15), new TierMaterial(2, "YggdrasilWood", "$item_yggdrasilwood", 10), new TierMaterial(2, "Mandible", "$item_mandible", 5), new TierMaterial(3, "AskHide", "$item_askhide", 6), new TierMaterial(3, "CelestialFeather", "$item_celestialfeather", 4), new TierMaterial(3, "CharredBone", "$item_charredbone", 8), new TierMaterial(4, "FrostCore|Frostcore", "$item_frostcore", 3), new TierMaterial(4, "Frostwood|FrostWood|Timberwood", "$item_frostwood", 12), new TierMaterial(4, "MooseHide|Moosehide", "$item_moosehide", 4)); RootboundWitchPlugin.Log.LogInfo((object)("Rootbound Crook visual=" + text + "; attack=StaffGreenRoots (damage and targeting copied without rebalance).")); } private static void RegisterPetrifiedTools() { CustomItem val = RegisterPetrifiedTool("PetrifiedRootPick", "PickaxeAntler", "$item_petrified_root_pick", "$item_petrified_root_pick_desc", pick: true); AddTieredRecipe("Recipe_PetrifiedRootPick", val.ItemDrop, new TierMaterial(1, "HardAntler", "$item_hardantler", 2), new TierMaterial(1, "RoundLog", "$item_roundlog", 10), new TierMaterial(1, "Entrails", "$item_entrails", 6), new TierMaterial(1, "Resin", "$item_resin", 6), new TierMaterial(2, "YggdrasilWood", "$item_yggdrasilwood", 10), new TierMaterial(2, "Mandible", "$item_mandible", 5), new TierMaterial(2, "Sap", "$item_sap", 6), new TierMaterial(3, "Blackwood|Ashwood", "$item_blackwood", 12), new TierMaterial(3, "CharredBone", "$item_charredbone", 8), new TierMaterial(3, "AskHide", "$item_askhide", 4), new TierMaterial(4, "Frostwood|FrostWood|Timberwood", "$item_frostwood", 15), new TierMaterial(4, "FrostCore|Frostcore", "$item_frostcore", 4), new TierMaterial(4, "MooseHide|Moosehide", "$item_moosehide", 4)); CustomItem val2 = RegisterPetrifiedTool("PetrifiedRootAxe", "AxeBronze", "$item_petrified_root_axe", "$item_petrified_root_axe_desc", pick: false); AddTieredRecipe("Recipe_PetrifiedRootAxe", val2.ItemDrop, new TierMaterial(1, "HardAntler", "$item_hardantler", 2), new TierMaterial(1, "RoundLog", "$item_roundlog", 12), new TierMaterial(1, "AncientSeed", "$item_ancientseed", 3), new TierMaterial(1, "Resin", "$item_resin", 8), new TierMaterial(2, "YggdrasilWood", "$item_yggdrasilwood", 10), new TierMaterial(2, "Mandible", "$item_mandible", 5), new TierMaterial(2, "Sap", "$item_sap", 6), new TierMaterial(3, "Blackwood|Ashwood", "$item_blackwood", 12), new TierMaterial(3, "CharredBone", "$item_charredbone", 8), new TierMaterial(3, "AskHide", "$item_askhide", 4), new TierMaterial(4, "Frostwood|FrostWood|Timberwood", "$item_frostwood", 15), new TierMaterial(4, "FrostCore|Frostcore", "$item_frostcore", 4), new TierMaterial(4, "MooseHide|Moosehide", "$item_moosehide", 4)); RootboundWitchPlugin.Log.LogInfo((object)($"Petrified harvesting tools registered with tool tier {Mathf.Max(1, RootboundWitchPlugin.PetrifiedToolTier.Value)}; " + "damage and durability remain quality-scaled rather than becoming instant endgame weapons.")); } private static CustomItem RegisterPetrifiedTool(string prefabName, string sourcePrefab, string displayName, string description, bool pick) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0076: 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_00bd: 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_0082: 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_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) EnsurePrefabExists(sourcePrefab); CustomItem val = new CustomItem(prefabName, sourcePrefab); SharedData shared = val.ItemDrop.m_itemData.m_shared; shared.m_name = displayName; shared.m_description = description; shared.m_maxQuality = 4; shared.m_toolTier = Mathf.Max(1, RootboundWitchPlugin.PetrifiedToolTier.Value); shared.m_maxDurability = Mathf.Max(shared.m_maxDurability, 220f); shared.m_durabilityPerLevel = Mathf.Max(shared.m_durabilityPerLevel, 80f); DamageTypes damagesPerLevel = shared.m_damagesPerLevel; if (pick) { damagesPerLevel.m_pickaxe = Mathf.Max(damagesPerLevel.m_pickaxe, 8f); damagesPerLevel.m_pierce = Mathf.Max(damagesPerLevel.m_pierce, 2f); PetrifiedToolVisuals.ApplyPick(val.ItemPrefab); } else { damagesPerLevel.m_chop = Mathf.Max(damagesPerLevel.m_chop, 8f); damagesPerLevel.m_slash = Mathf.Max(damagesPerLevel.m_slash, 4f); PetrifiedToolVisuals.ApplyAxe(val.ItemPrefab); } shared.m_damagesPerLevel = damagesPerLevel; ItemManager.Instance.AddItem(val); return val; } private static void RegisterFrostedRoot() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) string text = FirstAvailablePrefab(RootboundWitchPlugin.StaffVisualCandidates.Value); GameObject val = FindPrefab("StaffFrostOrbs"); GameObject val2 = FindPrefab("StaffFireball"); if (text == null || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2)) { throw new InvalidOperationException("Frosted Root requires a reclaimed staff body plus live StaffFrostOrbs and StaffFireball prefabs."); } SharedData shared = val.GetComponent().m_itemData.m_shared; SharedData shared2 = val2.GetComponent().m_itemData.m_shared; Attack val3 = shared.m_attack ?? shared2.m_attack; if (shared2.m_attack == null || val3 == null) { throw new InvalidOperationException("No live fireball-cast projectile architecture exists for Frosted Root."); } ReclaimedStaffVisual.SourceVisualSnapshot sourceVisualSnapshot = ReclaimedStaffVisual.CaptureSource(FindPrefab(text)); CustomItem val4 = new CustomItem("FrostedRoot", text); SharedData shared3 = val4.ItemDrop.m_itemData.m_shared; shared3.m_name = "$item_frosted_root"; shared3.m_description = "$item_frosted_root_desc"; shared3.m_maxQuality = 4; shared3.m_skillType = shared.m_skillType; shared3.m_attack = FrostedRootAttacks.BuildPrimary(shared2.m_attack); GameObject val5 = FindPrefab("StaffGreenRoots"); if (!Object.op_Implicit((Object)(object)val5)) { throw new InvalidOperationException("StaffGreenRoots is missing; Frosted Root cannot build its freezing field."); } shared3.m_secondaryAttack = RootboundCrookSecondary.BuildAttack(val5.GetComponent().m_itemData.m_shared); shared3.m_secondaryAttack.m_spawnOnTrigger = null; shared3.m_secondaryAttack.m_spawnOnHit = null; shared3.m_secondaryAttack.m_spawnOnHitChance = 0f; CopyMagicResourceCosts(val3, shared3.m_attack, secondary: false); CopyMagicResourceCosts(val3, shared3.m_secondaryAttack, secondary: true); shared3.m_attack.m_attackEitr = 35f; shared3.m_attack.m_attackEitrAdd = 0f; RemoveCastEffects(shared3.m_attack); RemoveCastEffects(shared3.m_secondaryAttack); shared3.m_damages = shared.m_damages; shared3.m_damagesPerLevel = new DamageTypes { m_frost = 20f }; shared3.m_attackForce = shared.m_attackForce; shared3.m_backstabBonus = shared.m_backstabBonus; shared3.m_attackStatusEffect = shared.m_attackStatusEffect; shared3.m_attackStatusEffectChance = shared.m_attackStatusEffectChance; shared3.m_hitEffect = shared.m_hitEffect; shared3.m_hitTerrainEffect = shared.m_hitTerrainEffect; shared3.m_weight = shared.m_weight; shared3.m_maxDurability = shared.m_maxDurability; shared3.m_durabilityPerLevel = shared.m_durabilityPerLevel; ReclaimedStaffVisual.Apply(val4.ItemPrefab); FrostedStaffVisual.Apply(val4.ItemPrefab); sourceVisualSnapshot.Restore("Frosted Root"); ItemManager.Instance.AddItem(val4); AddTieredRecipe("Recipe_FrostedRoot", val4.ItemDrop, new TierMaterial(1, "RootboundCrook", "$item_rootbound_crook", 1), new TierMaterial(1, "FrostCore|Frostcore", "$item_frostcore", 6), new TierMaterial(1, "Frostwood|FrostWood", "$item_frostwood", 24), new TierMaterial(2, "FrostCore|Frostcore", "$item_frostcore", 4), new TierMaterial(2, "Frostwood|FrostWood", "$item_frostwood", 12), new TierMaterial(3, "FrostCore|Frostcore", "$item_frostcore", 5), new TierMaterial(3, "Frostwood|FrostWood", "$item_frostwood", 15), new TierMaterial(4, "FrostCore|Frostcore", "$item_frostcore", 6), new TierMaterial(4, "Frostwood|FrostWood", "$item_frostwood", 18)); RootboundWitchPlugin.Log.LogInfo((object)"Frosted Root registered at live StaffFrostOrbs damage with +20 frost damage per quality; Moder primary remains sky-directed; secondary is the proven immobilizing Crook field with frost in place of poison."); } private static void CopyMagicResourceCosts(Attack source, Attack target, bool secondary) { if (source != null && target != null) { target.m_attackEitr = (secondary ? Mathf.Max(source.m_attackEitr, 45f) : source.m_attackEitr); target.m_attackEitrAdd = source.m_attackEitrAdd; target.m_attackStamina = source.m_attackStamina; target.m_attackHealth = 0f; target.m_attackHealthPercentage = 0f; } } private static void RemoveCastEffects(Attack attack) { if (attack != null) { attack.m_startEffect = EmptyEffectList(); attack.m_triggerEffect = EmptyEffectList(); attack.m_burstEffect = EmptyEffectList(); attack.m_trailStartEffect = EmptyEffectList(); } } private static EffectList EmptyEffectList() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new EffectList { m_effectPrefabs = Array.Empty() }; } private static void RegisterFoods() { CustomItem val = CreateFood("RootboundMossbread", "Bread", "$item_rootbound_mossbread", "$item_rootbound_mossbread_desc", 22f, 32f, 22f, 1200f, 3f); AddSimpleRecipe("Recipe_RootboundMossbread", val.ItemDrop, new SimpleMaterial("Dandelion", "$item_dandelion", 3), new SimpleMaterial("Mushroom", "$item_mushroom", 2), new SimpleMaterial("Honey", "$item_honey", 2)); CustomItem val2 = CreateFood("RootboundBilberryMash", "QueensJam", "$item_rootbound_bilberrymash", "$item_rootbound_bilberrymash_desc", 20f, 25f, 34f, 1400f, 3f); AddSimpleRecipe("Recipe_RootboundBilberryMash", val2.ItemDrop, new SimpleMaterial("Blueberries", "$item_blueberries", 4), new SimpleMaterial("MushroomYellow", "$item_mushroomyellow", 2), new SimpleMaterial("Honey", "$item_honey", 2)); } private static CustomItem CreateFood(string prefabName, string sourcePrefab, string displayName, string description, float health, float stamina, float eitr, float burnTime, float regen) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown EnsurePrefabExists(sourcePrefab); CustomItem val = new CustomItem(prefabName, sourcePrefab); SharedData shared = val.ItemDrop.m_itemData.m_shared; shared.m_name = displayName; shared.m_description = description; shared.m_food = health; shared.m_foodStamina = stamina; shared.m_foodEitr = eitr; shared.m_foodBurnTime = burnTime; shared.m_foodRegen = regen; shared.m_maxStackSize = 20; ItemManager.Instance.AddItem(val); return val; } private static StatusEffect CreateKinshipEffect() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown SE_Stats val = ScriptableObject.CreateInstance(); ((Object)val).name = "SE_RootboundKinship"; ((StatusEffect)val).m_name = "$se_rootbound_kinship"; ((StatusEffect)val).m_tooltip = "$se_rootbound_kinship_tooltip"; ((StatusEffect)val).m_icon = FindPrefab("HelmetRoot").GetComponent().m_itemData.GetIcon(); ((StatusEffect)val).m_hidden = false; ((StatusEffect)val).m_effectsOnlyOnPlayer = true; ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val, false)); return (StatusEffect)(object)val; } private static void AddTieredRecipe(string recipeName, ItemDrop result, params TierMaterial[] costs) { //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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown Recipe val = NewRecipe(recipeName, result); List list = new List(); foreach (TierMaterial tierMaterial in costs) { ItemDrop resItem = ResolveMaterial(tierMaterial.PrefabCandidates, tierMaterial.LocalizationToken); Requirement val2 = new Requirement { m_resItem = resItem, m_amount = ((tierMaterial.Quality == 1) ? 1 : 0), m_amountPerLevel = 0, m_recover = true, m_upgraderResource = false }; list.Add(val2); TieredRecipeCosts.Register(val2, tierMaterial.Quality, tierMaterial.Amount); } val.m_resources = list.ToArray(); if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val, false, false))) { throw new InvalidOperationException("Jotunn rejected " + recipeName); } } private static void AddSimpleRecipe(string recipeName, ItemDrop result, params SimpleMaterial[] costs) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown Recipe val = NewRecipe(recipeName, result); val.m_resources = ((IEnumerable)costs).Select((Func)((SimpleMaterial cost) => new Requirement { m_resItem = ResolveMaterial(cost.PrefabName, cost.LocalizationToken), m_amount = cost.Amount, m_amountPerLevel = 0, m_recover = true, m_upgraderResource = false })).ToArray(); if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val, false, false))) { throw new InvalidOperationException("Jotunn rejected " + recipeName); } } private static Recipe NewRecipe(string recipeName, ItemDrop result) { GameObject val = FindPrefab("piece_workbench"); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("piece_workbench is missing."); } Recipe obj = ScriptableObject.CreateInstance(); ((Object)obj).name = recipeName; obj.m_item = result; obj.m_amount = 1; obj.m_enabled = true; obj.m_craftingStation = val.GetComponent(); obj.m_repairStation = obj.m_craftingStation; obj.m_minStationLevel = 1; obj.m_requireOnlyOneIngredient = false; obj.m_qualityResultAmountMultiplier = 1f; return obj; } internal static GameObject FindPrefab(string name) { GameObject prefab = PrefabManager.Instance.GetPrefab(name); if (Object.op_Implicit((Object)(object)prefab)) { return prefab; } if ((Object)(object)ZNetScene.instance != (Object)null) { prefab = ZNetScene.instance.GetPrefab(name); } return prefab; } private static string FirstAvailablePrefab(string candidates) { foreach (string item in SplitCandidates(candidates)) { if (Object.op_Implicit((Object)(object)FindPrefab(item))) { return item; } } return null; } private static void EnsurePrefabExists(string prefabName) { if (!Object.op_Implicit((Object)(object)FindPrefab(prefabName))) { throw new InvalidOperationException("Required prefab is missing: " + prefabName); } } private static ItemDrop ResolveMaterial(string prefabCandidates, string localizationToken) { foreach (string item in SplitCandidates(prefabCandidates)) { GameObject val = FindPrefab(item); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if ((Object)(object)val2 != (Object)null) { return val2; } } IEnumerable enumerable = Enumerable.Empty(); if ((Object)(object)ZNetScene.instance != (Object)null) { enumerable = ZNetScene.instance.m_prefabs.Concat(ZNetScene.instance.m_nonNetViewPrefabs); } if ((Object)(object)ObjectDB.instance != (Object)null) { enumerable = enumerable.Concat(ObjectDB.instance.m_items); } ItemDrop val3 = (from go in enumerable where Object.op_Implicit((Object)(object)go) select go.GetComponent()).FirstOrDefault((Func)((ItemDrop drop) => (Object)(object)drop != (Object)null && string.Equals(drop.m_itemData.m_shared.m_name, localizationToken, StringComparison.OrdinalIgnoreCase))); if ((Object)(object)val3 != (Object)null) { RootboundWitchPlugin.Log.LogInfo((object)("Resolved " + localizationToken + " to live prefab " + ((Object)((Component)val3).gameObject).name + ".")); return val3; } throw new InvalidOperationException("Could not resolve recipe material candidates [" + prefabCandidates + "] or token " + localizationToken + "."); } private static IEnumerable SplitCandidates(string candidates) { return from value in (candidates ?? string.Empty).Split(new char[3] { ',', '|', ';' }, StringSplitOptions.RemoveEmptyEntries) select value.Trim() into value where value.Length > 0 select value; } private static void AddLocalizations() { Dictionary dictionary = new Dictionary { ["item_rootbound_mask"] = "Rootbound Mask", ["item_rootbound_mask_desc"] = "A dead face reclaimed by the forest. Plains armour at first growth; it hardens with each biome without shedding its skin.", ["item_rootbound_harness"] = "Rootbound Harness", ["item_rootbound_harness_desc"] = "A living cuirass harvested from the draugr-haunted Meadows. Its roots hold a static reserve of eitr.", ["item_rootbound_leggings"] = "Rootbound Leggings", ["item_rootbound_leggings_desc"] = "Moss, bark and old sinew. At final growth the green blights white and answers the Deep North.", ["item_petrified_root_pick"] = "Petrified Root Pick", ["item_petrified_root_pick_desc"] = "Eikthyr's antler fossilized into old walnut root. It opens every seam without asking forged metal to touch the forest.", ["item_petrified_root_axe"] = "Petrified Root Axe", ["item_petrified_root_axe_desc"] = "A bronze-age silhouette with no bronze left in it. The corewood blade can fell every biome's timber while each growth improves its pace.", ["item_rootbound_crook"] = "Rootbound Crook", ["item_rootbound_crook_desc"] = "A Surtling implement gone cold. Nature has occupied the corpse; the Staff of the Wild answers from within. Secondary attack raises a poisonous root field without blunt force.", ["item_frosted_root"] = "Frosted Root", ["item_frosted_root_desc"] = "Coreless, snow-strangled wood. An empty gesture rains Moder's ice; its second motion raises a freezing root prison around the aimed ground.", ["item_rootbound_mossbread"] = "Mossbread", ["item_rootbound_mossbread_desc"] = "The forest feeds you before it clothes you. A small, steady eitr meal made without flesh.", ["item_rootbound_bilberrymash"] = "Bilberry Mash", ["item_rootbound_bilberrymash_desc"] = "Cold berries, yellow fungus and honey crushed into an early draught of eitr.", ["item_rootbound_kvastur_scroll"] = "Rootbound Kvastur Scroll", ["item_rootbound_kvastur_scroll_desc"] = "The Bog Witch recognizes the forest's mark. Primary attack calls one Kvastur companion; secondary attack recalls it.", ["item_rootbound_kvastur_scroll_tooltip"] = "One broom. One witch. No accidental broom army.", ["item_rootbound_galdr_charter"] = "Rootbound Galdr Charter", ["item_rootbound_galdr_charter_desc"] = "A private dispensation from the Bog Witch. The fully ripened work of a Galdr table may now be performed by hand. Primary attack calls one strengthened Abomination; secondary attack recalls it.", ["item_rootbound_galdr_charter_tooltip"] = "Permanently exposes the highest-tier loaded Galdr recipes and binds one Mistlands-grade Abomination companion.", ["enemy_rootbound_abomination"] = "Charter Abomination", ["item_rootbound_moder_sigil"] = "Rootbound Moder Sigil", ["item_rootbound_moder_sigil_desc"] = "A Galdr Charter covenant bearing the three trophies of Hildir's trials. Primary attack calls one lesser Moder; secondary attack recalls it.", ["enemy_rootbound_moder"] = "Rootbound Moder", ["item_rootbound_charm"] = "Rootbound Charm", ["item_rootbound_charm_desc"] = "A Jormundling husk colonized by quieter roots. It holds magic close, arrests a fall, and makes the old powers answer sooner.", ["se_rootbound_charm"] = "Rootbound Organ", ["se_rootbound_charm_tooltip"] = "+40 Elemental Magic, +40 Blood Magic, +40 eitr, feather fall, and seven-minute Forsaken-power recovery.", ["item_rootbound_wisp"] = "Rootbound Wisp", ["item_rootbound_wisp_desc"] = "A Wisplight taught to carry more than mist. It preserves the ordinary wisp and adds 150 carry weight without occupying the Rootbound Charm's trinket slot.", ["item_mycelial_crook"] = "Mycelial Crook", ["item_mycelial_crook_desc"] = "A coreless reclaimed crook crowned by luminous fungus. Primary attack plants a red mushroom; secondary attack plants a yellow mushroom bright enough to illuminate a room.", ["se_rootbound_kinship"] = "Recognized by Root", ["se_rootbound_kinship_tooltip"] = "Greydwarves read the complete shape as kin. At second growth, Dvergers read it as a forest enemy. Metal, meat, worked stone and fire read it differently.", ["se_rootbound_ensnared"] = "Rootbound", ["se_rootbound_ensnared_tooltip"] = "Primal roots hold the body while poison moves through it.", ["se_rootbound_shared_vigor"] = "Borrowed Root", ["se_rootbound_shared_vigor_tooltip"] = "A Rootbound ally is surrendering motion to double your stamina regeneration.", ["se_rootbound_dverger_mark"] = "Dverger Hostility Mark", ["se_rootbound_dverger_mark_tooltip"] = "The forest shape is mature enough for Dvergers to recognize it as an enemy.", ["msg_rootbound_reject_metal"] = "The roots reject worked metal.", ["msg_rootbound_reject_meat"] = "The forest will not carry dead flesh.", ["msg_rootbound_rooted"] = "You take root.", ["msg_rootbound_uprooted"] = "The hold releases.", ["msg_rootbound_kvastur_summoned"] = "Kvastur answers the forest's mark.", ["msg_rootbound_kvastur_recalled"] = "Kvastur returns to the quiet.", ["msg_rootbound_abomination_summoned"] = "The Charter's larger signature rises.", ["msg_rootbound_abomination_recalled"] = "The Abomination sinks beneath the rootline.", ["msg_rootbound_moder_summoned"] = "A lesser Moder answers the Charter.", ["msg_rootbound_moder_recalled"] = "The frost-drake covenant closes.", ["msg_rootbound_mushroom_red"] = "Red fruit takes hold.", ["msg_rootbound_mushroom_yellow"] = "The chamber grows its own lamp." }; CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, dictionary); } } internal static class RootboundCrookSecondary { private const string EnsnareEffectName = "SE_RootboundEnsnared"; private static readonly FieldRef AttackCharacter = AccessTools.FieldRefAccess("m_character"); private static readonly FieldRef AttackWeapon = AccessTools.FieldRefAccess("m_weapon"); private static readonly FieldRef IsSecondary = AccessTools.FieldRefAccess("m_currentAttackIsSecondary"); private static StatusEffect _ensnare; private static GameObject _rootVisual; private static GameObject _frostVisual; internal static Attack BuildAttack(SharedData rootSpell) { Attack val = null; GameObject val2 = RootboundContent.FindPrefab("BDS_DvergerStaffIce"); ItemDrop val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); if ((Object)(object)val3 != (Object)null) { val = val3.m_itemData.m_shared.m_secondaryAttack; } if (val == null) { val = rootSpell.m_secondaryAttack ?? rootSpell.m_attack; } if (val == null) { throw new InvalidOperationException("No projectile attack exists from which to build the Crook's secondary cast."); } Attack val4 = val.Clone(); if (rootSpell.m_attack != null) { val4.m_startEffect = rootSpell.m_attack.m_startEffect; val4.m_triggerEffect = rootSpell.m_attack.m_triggerEffect; val4.m_burstEffect = rootSpell.m_attack.m_burstEffect; val4.m_trailStartEffect = rootSpell.m_attack.m_trailStartEffect; val4.m_attackEitr = Mathf.Max(20f, rootSpell.m_attack.m_attackEitr); } val4.m_projectiles = 1; val4.m_projectileBursts = 1; val4.m_damageMultiplier = 0f; val4.m_forceMultiplier = 0f; return val4; } internal static void Register(GameObject rootSpellPrefab) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown if ((Object)(object)_ensnare == (Object)null) { RootboundEnsnareStatusEffect rootboundEnsnareStatusEffect = ScriptableObject.CreateInstance(); ((Object)rootboundEnsnareStatusEffect).name = "SE_RootboundEnsnared"; ((StatusEffect)rootboundEnsnareStatusEffect).m_name = "$se_rootbound_ensnared"; ((StatusEffect)rootboundEnsnareStatusEffect).m_tooltip = "$se_rootbound_ensnared_tooltip"; ((StatusEffect)rootboundEnsnareStatusEffect).m_ttl = Mathf.Max(0.25f, RootboundWitchPlugin.CrookSecondaryEnsnareSeconds.Value); ((SE_Stats)rootboundEnsnareStatusEffect).m_speedModifier = -1f; ((StatusEffect)rootboundEnsnareStatusEffect).m_icon = rootSpellPrefab.GetComponent().m_itemData.GetIcon(); ((StatusEffect)rootboundEnsnareStatusEffect).m_hidden = false; ((StatusEffect)rootboundEnsnareStatusEffect).m_effectsOnlyOnPlayer = false; ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)rootboundEnsnareStatusEffect, false)); _ensnare = (StatusEffect)(object)rootboundEnsnareStatusEffect; } _rootVisual = BuildRootVisual(rootSpellPrefab, frosted: false); _frostVisual = BuildRootVisual(rootSpellPrefab, frosted: true); } internal static bool IsOurSecondary(Attack attack) { if (attack == null) { return false; } ItemData item = AttackWeapon.Invoke(attack); Humanoid val = AttackCharacter.Invoke(attack); if ((RootboundState.HasPrefab(item, "RootboundCrook") || RootboundState.HasPrefab(item, "FrostedRoot")) && (Object)(object)val != (Object)null) { return IsSecondary.Invoke(val); } return false; } internal static void Cast(Attack attack) { //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_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_003c: 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_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_00b1: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Expected O, but got Unknown Humanoid obj = AttackCharacter.Invoke(attack); Player val = (Player)(object)((obj is Player) ? obj : null); ItemData val2 = AttackWeapon.Invoke(attack); if ((Object)(object)val == (Object)null || val2 == null) { return; } bool flag = RootboundState.HasPrefab(val2, "FrostedRoot"); Vector3 val3 = (flag ? (((Component)val).transform.position + Vector3.up * 0.05f) : FindTargetPoint(val)); float num = Mathf.Max(1f, RootboundWitchPlugin.CrookSecondaryRadius.Value); DamageTypes damage = val2.GetDamage(); float num2 = (flag ? Mathf.Max(0f, damage.m_frost) : (Mathf.Max(0f, damage.m_poison) * Mathf.Max(0f, RootboundWitchPlugin.CrookSecondaryPoisonMultiplier.Value))); GameObject val4 = (flag ? _frostVisual : _rootVisual); if (Object.op_Implicit((Object)(object)val4)) { GameObject obj2 = Object.Instantiate(val4, val3, Quaternion.identity); obj2.transform.localScale = Vector3.one * Mathf.Clamp(num / 6f, 0.65f, 2f); obj2.SetActive(true); } Character[] array = Character.GetAllCharacters().ToArray(); foreach (Character val5 in array) { if (!((Object)(object)val5 == (Object)null) && !((Object)(object)val5 == (Object)(object)val) && !val5.IsDead() && !(Vector3.Distance(val5.GetCenterPoint(), val3) > num) && BaseAI.IsEnemy((Character)(object)val, val5)) { val5.GetSEMan().AddStatusEffect(_ensnare, true, 0, 0f, (short)0); if (num2 > 0f) { HitData val6 = new HitData { m_damage = (flag ? new DamageTypes { m_frost = num2 } : new DamageTypes { m_poison = num2 }), m_dodgeable = false, m_blockable = false, m_ranged = true, m_point = val5.GetCenterPoint(), m_dir = Vector3.zero, m_pushForce = 0f, m_backstabBonus = 1f, m_staggerMultiplier = 0f, m_skill = val2.m_shared.m_skillType, m_itemLevel = (short)val2.m_quality }; val6.SetAttacker((Character)(object)val); val5.Damage(val6); } } } } private static Vector3 FindTargetPoint(Player caster) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0045: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) Vector3 eyePoint = ((Character)caster).GetEyePoint(); Vector3 lookDir = ((Character)caster).GetLookDir(); Vector3 normalized = ((Vector3)(ref lookDir)).normalized; RaycastHit val2 = default(RaycastHit); Vector3 val = (Physics.Raycast(eyePoint, normalized, ref val2, 16f, -1, (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val2)).point : (eyePoint + normalized * 9f)); RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val + Vector3.up * 5f, Vector3.down, ref val3, 12f, -1, (QueryTriggerInteraction)1)) { val = ((RaycastHit)(ref val3)).point + Vector3.up * 0.05f; } return val; } private static GameObject BuildRootVisual(GameObject rootSpellPrefab, bool frosted) { List list = new List(); AddAttackVisuals(rootSpellPrefab, list); AddAttackVisuals(FindItemByToken("$item_crossbow_ripper_nature"), list); AddAttackVisuals(FindItemByToken("$item_spear_splitner_nature"), list); GameObject val = ((IEnumerable)list).FirstOrDefault((Func)((GameObject candidate) => Object.op_Implicit((Object)(object)candidate) && (candidate.GetComponentsInChildren(true).Length != 0 || candidate.GetComponentsInChildren(true).Length != 0))); if (!Object.op_Implicit((Object)(object)val)) { RootboundWitchPlugin.Log.LogWarning((object)"No jade/primal root visual prefab was found; secondary mechanics remain active without the field cosmetic."); return null; } GameObject val2 = Object.Instantiate(val); ((Object)val2).name = (frosted ? "FrostedRoot_FreezingFieldVisual" : "RootboundCrook_RootFieldVisual"); val2.SetActive(false); Collider[] componentsInChildren = val2.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren[num]); } Rigidbody[] componentsInChildren2 = val2.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren2.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[num]); } Aoe[] componentsInChildren3 = val2.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren3.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[num]); } Projectile[] componentsInChildren4 = val2.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren4.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[num]); } ZNetView[] componentsInChildren5 = val2.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren5.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren5[num]); } ZSyncTransform[] componentsInChildren6 = val2.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren6.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren6[num]); } if (frosted) { RecolourFrost(val2); } else { DraugrRotVisuals.Recolour(val2); } val2.AddComponent(); Object.DontDestroyOnLoad((Object)(object)val2); RootboundWitchPlugin.Log.LogInfo((object)((frosted ? "Frosted Root freezing" : "Crook poison") + " field visual harvested from " + ((Object)val).name + ".")); return val2; } private static void RecolourFrost(GameObject visual) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_007e: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00f8: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(0.72f, 0.88f, 1f, 0.72f); Renderer[] componentsInChildren = visual.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { Material[] sharedMaterials = val2.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int j = 0; j < sharedMaterials.Length; j++) { if (Object.op_Implicit((Object)(object)sharedMaterials[j])) { Material val3 = new Material(sharedMaterials[j]) { name = ((Object)sharedMaterials[j]).name + "_FrostField" }; if (val3.HasProperty("_Color")) { val3.SetColor("_Color", val); } if (val3.HasProperty("_BaseColor")) { val3.SetColor("_BaseColor", val); } if (val3.HasProperty("_TintColor")) { val3.SetColor("_TintColor", val); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", new Color(0.18f, 0.34f, 0.48f, 1f)); } array[j] = val3; } } val2.sharedMaterials = array; } ParticleSystem[] componentsInChildren2 = visual.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { MainModule main = componentsInChildren2[i].main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(val); } Light[] componentsInChildren3 = visual.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { componentsInChildren3[i].color = new Color(0.48f, 0.72f, 1f, 1f); } } private static void AddAttackVisuals(GameObject itemPrefab, List candidates) { ItemDrop val = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent() : null); if (!((Object)(object)val == (Object)null)) { AddAttackVisuals(val.m_itemData.m_shared.m_attack, candidates); AddAttackVisuals(val.m_itemData.m_shared.m_secondaryAttack, candidates); } } private static void AddAttackVisuals(Attack attack, List candidates) { if (attack == null) { return; } if (Object.op_Implicit((Object)(object)attack.m_spawnOnTrigger)) { candidates.Add(attack.m_spawnOnTrigger); } if (Object.op_Implicit((Object)(object)attack.m_spawnOnHit)) { candidates.Add(attack.m_spawnOnHit); } if (Object.op_Implicit((Object)(object)attack.m_attackProjectile)) { Projectile component = attack.m_attackProjectile.GetComponent(); if ((Object)(object)component != (Object)null && Object.op_Implicit((Object)(object)component.m_spawnOnHit)) { candidates.Insert(0, component.m_spawnOnHit); } candidates.Add(attack.m_attackProjectile); } } private static GameObject FindItemByToken(string token) { if ((Object)(object)ObjectDB.instance == (Object)null) { return null; } return ((IEnumerable)ObjectDB.instance.m_items).FirstOrDefault((Func)delegate(GameObject item) { ItemDrop val = (Object.op_Implicit((Object)(object)item) ? item.GetComponent() : null); return (Object)(object)val != (Object)null && string.Equals(val.m_itemData.m_shared.m_name, token, StringComparison.OrdinalIgnoreCase); }); } } internal sealed class RootboundEnsnareStatusEffect : SE_Stats { public override void UpdateStatusEffect(float dt) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) ((SE_Stats)this).UpdateStatusEffect(dt); if (!((Object)(object)((StatusEffect)this).m_character == (Object)null) && !((StatusEffect)this).m_character.IsDead()) { ((StatusEffect)this).m_character.SetMoveDir(Vector3.zero); ((StatusEffect)this).m_character.SetRun(false); ((StatusEffect)this).m_character.StopMovementXZ(); BaseAI component = ((Component)((StatusEffect)this).m_character).GetComponent(); if ((Object)(object)component != (Object)null) { component.StopMoving(); } } } } internal sealed class RootboundVisualExpiry : MonoBehaviour { private float _expiresAt; private void OnEnable() { _expiresAt = Time.time + Mathf.Max(1f, RootboundWitchPlugin.CrookSecondaryEnsnareSeconds.Value); } private void Update() { if (Time.time >= _expiresAt) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } [HarmonyPatch(typeof(Attack), "FireProjectileBurst")] internal static class RootboundCrookSecondaryPatch { private static bool Prefix(Attack __instance) { if (RootboundCharterAbomination.IsOurAttack(__instance)) { RootboundCharterAbomination.Use(__instance); return false; } if (RootboundKvasturScroll.IsOurAttack(__instance)) { RootboundKvasturScroll.Use(__instance); return false; } if (RootboundModerCompanion.IsOurAttack(__instance)) { RootboundModerCompanion.Use(__instance); return false; } if (RootboundMushroomStaff.IsOurAttack(__instance)) { RootboundMushroomStaff.Use(__instance); return false; } if (!RootboundCrookSecondary.IsOurSecondary(__instance)) { return true; } RootboundCrookSecondary.Cast(__instance); return false; } } internal static class RootboundDoubleJump { private static bool _spent; internal static void UpdateGroundState(Player player) { if ((Object)(object)player == (Object)null || !RootboundState.IsFullSet(player) || ((Character)player).IsOnGround()) { _spent = false; } } internal static bool TryConsume(Player player) { //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_00af: 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) if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || _spent || !RootboundState.IsFullSet(player) || ((Character)player).IsOnGround() || ((Character)player).IsDead() || ((Character)player).IsEncumbered() || ((Character)player).InDodge() || ((Character)player).IsSwimming() || Object.op_Implicit((Object)(object)GrapplingPoint.m_localGrappler)) { return false; } float jumpStaminaUsage = ((Character)player).m_jumpStaminaUsage; ((Character)player).GetSEMan().ModifyJumpStaminaUsage(((Character)player).m_jumpStaminaUsage, ref jumpStaminaUsage, true); if (!((Character)player).HaveStamina(jumpStaminaUsage)) { return false; } ((Character)player).UseStamina(jumpStaminaUsage); float skillFactor = ((Character)player).GetSkillFactor((SkillType)100); float num = ((Character)player).m_jumpForce * (1f + skillFactor * 0.4f); Vector3 velocity = ((Character)player).GetVelocity(); velocity.y = Mathf.Max(velocity.y, num); ((Character)player).ForceJump(velocity, true); _spent = true; return true; } } [HarmonyPatch(typeof(Character), "Jump")] internal static class RootboundDoubleJumpPatch { private static bool Prefix(Character __instance) { return !RootboundDoubleJump.TryConsume((Player)(object)((__instance is Player) ? __instance : null)); } } internal static class RootboundGaldrCharter { internal const string KvasturPurchaseKey = "ADARC_RootboundKvasturPurchased"; internal const string CharterPurchaseKey = "ADARC_RootboundGaldrCharterPurchased"; private const string HandRecipePrefix = "Recipe_RootboundHandGaldr_"; private static readonly Dictionary HandRecipes = new Dictionary(); private static readonly List CharterOnlyRecipes = new List(); private static ItemDrop _charter; private static TradeItem _tradeItem; private static bool _loggedRecipeSet; internal static void Register() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) string text = (Object.op_Implicit((Object)(object)RootboundContent.FindPrefab("StaffSkeleton")) ? "StaffSkeleton" : "StaffFireball"); GameObject val = RootboundContent.FindPrefab(text); GameObject val2 = RootboundContent.FindPrefab("StaffGreenRoots"); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2)) { throw new InvalidOperationException("A summon-scroll attack source or StaffGreenRoots is missing for the Rootbound Galdr Charter."); } CustomItem val3 = new CustomItem("RootboundGaldrCharter", text); SharedData shared = val3.ItemDrop.m_itemData.m_shared; SharedData shared2 = val.GetComponent().m_itemData.m_shared; SharedData shared3 = val2.GetComponent().m_itemData.m_shared; Attack attack = shared2.m_attack.Clone(); Attack secondaryAttack = RootboundSummonRecall.BuildAxeStrikeAttack(); RootboundCharterAbomination.ConfigureSummonAttack(attack, shared3, RootboundWitchPlugin.CharterAbominationSummonEitr.Value); shared.m_name = "$item_rootbound_galdr_charter"; shared.m_description = "$item_rootbound_galdr_charter_desc"; shared.m_maxQuality = 1; shared.m_maxStackSize = 1; shared.m_weight = 0.2f; shared.m_value = Math.Max(0, RootboundWitchPlugin.GaldrCharterPrice.Value); shared.m_attack = attack; shared.m_secondaryAttack = secondaryAttack; shared.m_damages = default(DamageTypes); shared.m_damagesPerLevel = default(DamageTypes); shared.m_attackForce = 0f; ScrollVisual.Apply(val3.ItemPrefab, val3.ItemDrop); ItemManager.Instance.AddItem(val3); _charter = val3.ItemDrop; RootboundCharterAbomination.Register(); } internal static TradeItem GetTradeItem() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if (_tradeItem == null && (Object)(object)_charter != (Object)null) { _tradeItem = new TradeItem { m_prefab = _charter, m_stack = 1, m_price = Math.Max(0, RootboundWitchPlugin.GaldrCharterPrice.Value), m_requiredGlobalKey = string.Empty, m_buyKey = "ADARC_RootboundGaldrCharterPurchased" }; } if (_tradeItem != null) { _tradeItem.m_price = Math.Max(0, RootboundWitchPlugin.GaldrCharterPrice.Value); _tradeItem.m_buyKey = "ADARC_RootboundGaldrCharterPurchased"; } return _tradeItem; } internal static bool HasKvasturRecognition(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (((Humanoid)player).HaveUniqueKey("ADARC_RootboundKvasturPurchased")) { return true; } if (HasItem(player, "RootboundKvasturScroll")) { ((Humanoid)player).AddUniqueKey("ADARC_RootboundKvasturPurchased"); return true; } return false; } internal static bool HasHandGaldr(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (((Humanoid)player).HaveUniqueKey("ADARC_RootboundGaldrCharterPurchased")) { return true; } if (HasItem(player, "RootboundGaldrCharter")) { ((Humanoid)player).AddUniqueKey("ADARC_RootboundGaldrCharterPurchased"); return true; } return false; } internal static void RegisterCharterOnlyRecipe(Recipe recipe) { if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null) { throw new ArgumentNullException("recipe"); } recipe.m_craftingStation = null; recipe.m_repairStation = null; recipe.m_minStationLevel = 1; if (!CharterOnlyRecipes.Contains(recipe)) { CharterOnlyRecipes.Add(recipe); } } internal static void AddAvailableHandRecipes(Player player, List available) { if (!RootboundWitchPlugin.EnableGaldrCharter.Value || (Object)(object)player == (Object)null || available == null || (Object)(object)player.GetCurrentCraftingStation() != (Object)null || !HasHandGaldr(player) || (Object)(object)ObjectDB.instance == (Object)null) { return; } foreach (Recipe charterOnlyRecipe in CharterOnlyRecipes) { if ((Object)(object)charterOnlyRecipe != (Object)null && charterOnlyRecipe.m_enabled && (Object)(object)charterOnlyRecipe.m_item != (Object)null && !available.Contains(charterOnlyRecipe)) { available.Add(charterOnlyRecipe); } } List list = ObjectDB.instance.m_recipes.Where(IsGaldrRecipe).ToList(); if (list.Count == 0) { return; } int fullLevel = list.Max((Recipe recipe) => Math.Max(1, recipe.m_minStationLevel)); List list2 = list.Where((Recipe recipe) => Math.Max(1, recipe.m_minStationLevel) == fullLevel).ToList(); foreach (Recipe item in list2) { int instanceID = ((Object)item).GetInstanceID(); if (!HandRecipes.TryGetValue(instanceID, out var value) || (Object)(object)value == (Object)null) { value = Object.Instantiate(item); ((Object)value).name = "Recipe_RootboundHandGaldr_" + ((Object)item).name + "_" + instanceID; value.m_craftingStation = null; value.m_repairStation = null; value.m_minStationLevel = 1; HandRecipes[instanceID] = value; } if (value.m_enabled && (Object)(object)value.m_item != (Object)null && !available.Contains(value)) { available.Add(value); } } if (!_loggedRecipeSet) { _loggedRecipeSet = true; RootboundWitchPlugin.Log.LogInfo((object)$"Rootbound Galdr Charter exposed {list2.Count} hand recipe(s) from live Galdr-table level {fullLevel}."); } } private static bool IsGaldrRecipe(Recipe recipe) { if ((Object)(object)recipe == (Object)null || !recipe.m_enabled || (Object)(object)recipe.m_item == (Object)null || (Object)(object)recipe.m_craftingStation == (Object)null) { return false; } string text = (((Object)((Component)recipe.m_craftingStation).gameObject).name + " " + recipe.m_craftingStation.m_name).ToLowerInvariant(); if (!text.Contains("magetable") && !text.Contains("galdr")) { return text.Contains("$piece_magetable"); } return true; } private static bool HasItem(Player player, string prefabName) { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory != null) { return inventory.GetAllItems().Any((ItemData item) => RootboundState.HasPrefab(item, prefabName)); } return false; } } [HarmonyPatch(typeof(Player), "GetAvailableRecipes")] internal static class RootboundHandGaldrRecipesPatch { private static void Postfix(Player __instance, ref List available) { RootboundGaldrCharter.AddAvailableHandRecipes(__instance, available); } } [HarmonyPatch(typeof(Character), "OnDeath")] internal static class RootboundKinshipPenalty { private static readonly FieldRef LastHit = AccessTools.FieldRefAccess("m_lastHit"); private static void Prefix(Character __instance) { if (!RootboundWitchPlugin.EnableAnimalKillPenalty.Value || (Object)(object)__instance == (Object)null || !RootboundMeatReclamation.CreatureYieldsMeat(__instance)) { return; } HitData val = LastHit.Invoke(__instance); Player val2 = (Player)((val != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null || (Object)(object)val2 != (Object)(object)Player.m_localPlayer || !RootboundState.IsFullSet(val2)) { return; } float num = Mathf.Max(0f, RootboundWitchPlugin.AnimalKillSkillPenalty.Value); foreach (Skill item in from skill in ((Character)val2).GetSkills().GetSkillList() where skill != null && skill.m_info != null && ((int)skill.m_info.m_skill == 102 || (int)skill.m_info.m_skill == 100) select skill) { item.m_level = Mathf.Max(0f, item.m_level - num); item.m_accumulator = 0f; } RootboundWitchPlugin.Log.LogInfo((object)$"Forest kinship penalty: {__instance.m_name} cost the wearer {num:0.##} Running and Jumping levels."); } } internal static class RootboundKvasturScroll { private const string SummonPrefabName = "RootboundKvasturCompanion"; private static readonly FieldRef AttackCharacter = AccessTools.FieldRefAccess("m_character"); private static readonly FieldRef AttackWeapon = AccessTools.FieldRefAccess("m_weapon"); private static ItemDrop _scroll; private static GameObject _summonPrefab; private static TradeItem _tradeItem; private static SoftReference _sourceReference; internal static void Register() { RegisterScrollItem(); if (!TryRegisterCompanionPrefab()) { RootboundWitchPlugin.Log.LogWarning((object)"Rootbound Kvastur Scroll registered, but its living character source is not loaded yet; the mod will retry when the scroll is used."); } RootboundWitchPlugin.Log.LogInfo((object)"Rootbound Kvastur Scroll item registered as RootboundKvasturScroll."); } internal static bool IsOurAttack(Attack attack) { if (attack != null) { return RootboundState.HasPrefab(AttackWeapon.Invoke(attack), "RootboundKvasturScroll"); } return false; } internal static void Use(Attack attack) { //IL_0070: 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_0077: 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_00b3: 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_0096: Unknown result type (might be due to invalid IL or missing references) Humanoid obj = AttackCharacter.Invoke(attack); Player val = (Player)(object)((obj is Player) ? obj : null); if (!RootboundSummonRecall.HasLocalAttackAuthority(val)) { return; } if (!Object.op_Implicit((Object)(object)_summonPrefab) && !TryRegisterCompanionPrefab()) { RootboundWitchPlugin.Log.LogError((object)"Rootbound Kvastur summon requested, but BogWitchKvastur could not be loaded."); return; } if (attack.m_attackEitr <= 0.001f) { if (RootboundKvasturOwnership.Recall(val.GetPlayerID())) { RootboundState.Show("$msg_rootbound_kvastur_recalled"); } return; } RootboundKvasturOwnership.Recall(val.GetPlayerID()); Vector3 val2 = FindSpawnPoint(val); RootboundKvasturOwnership.QueueSpawn(val, val2); if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.SpawnObject(val2, ((Component)val).transform.rotation, _summonPrefab); } else { GameObject obj2 = Object.Instantiate(_summonPrefab, val2, ((Component)val).transform.rotation); obj2.SetActive(true); obj2.GetComponent().Assign(val); } RootboundState.Show("$msg_rootbound_kvastur_summoned"); } internal static TradeItem GetTradeItem() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if (_tradeItem == null && (Object)(object)_scroll != (Object)null) { _tradeItem = new TradeItem { m_prefab = _scroll, m_stack = 1, m_price = Math.Max(0, RootboundWitchPlugin.KvasturScrollPrice.Value), m_requiredGlobalKey = string.Empty, m_buyKey = "ADARC_RootboundKvasturPurchased" }; } if (_tradeItem != null) { _tradeItem.m_price = Math.Max(0, RootboundWitchPlugin.KvasturScrollPrice.Value); _tradeItem.m_buyKey = "ADARC_RootboundKvasturPurchased"; } return _tradeItem; } internal static bool IsBogWitch(Trader trader) { if ((Object)(object)trader == (Object)null) { return false; } string text = (((Object)((Component)trader).gameObject).name + " " + trader.m_name).ToLowerInvariant(); if (!text.Contains("bogwitch") && !text.Contains("bog witch")) { return text.Contains("$npc_bogwitch"); } return true; } private static void RegisterCompanionPrefab(GameObject kvastur) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)_summonPrefab)) { _summonPrefab = PrefabManager.Instance.CreateClonedPrefab("RootboundKvasturCompanion", kvastur); _summonPrefab.AddComponent(); Tameable component = _summonPrefab.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_startsTamed = true; component.m_commandable = false; component.m_unsummonOnOwnerLogoutSeconds = 10f; } CharacterDrop component2 = _summonPrefab.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.m_drops.Clear(); } PrefabManager.Instance.AddPrefab(new CustomPrefab(_summonPrefab, true)); RootboundWitchPlugin.Log.LogInfo((object)($"Rootbound Kvastur source={((Object)kvastur).name}; character={(Object)(object)_summonPrefab.GetComponent() != (Object)null}; " + $"monsterAI={(Object)(object)_summonPrefab.GetComponent() != (Object)null}; znet={(Object)(object)_summonPrefab.GetComponent() != (Object)null}.")); } } private static void RegisterScrollItem() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) string text = (Object.op_Implicit((Object)(object)RootboundContent.FindPrefab("StaffSkeleton")) ? "StaffSkeleton" : "StaffFireball"); GameObject val = RootboundContent.FindPrefab(text); GameObject val2 = RootboundContent.FindPrefab("StaffGreenRoots"); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2)) { throw new InvalidOperationException("A summon-scroll attack source or StaffGreenRoots is missing."); } CustomItem val3 = new CustomItem("RootboundKvasturScroll", text); SharedData shared = val3.ItemDrop.m_itemData.m_shared; SharedData shared2 = val2.GetComponent().m_itemData.m_shared; Attack attack = val.GetComponent().m_itemData.m_shared.m_attack.Clone(); Attack secondaryAttack = RootboundSummonRecall.BuildAxeStrikeAttack(); ConfigureSummonAttack(attack, shared2, 22f); shared.m_name = "$item_rootbound_kvastur_scroll"; shared.m_description = "$item_rootbound_kvastur_scroll_desc"; shared.m_maxQuality = 1; shared.m_maxStackSize = 1; shared.m_weight = 0.5f; shared.m_value = Math.Max(0, RootboundWitchPlugin.KvasturScrollPrice.Value); shared.m_attack = attack; shared.m_secondaryAttack = secondaryAttack; shared.m_damages = default(DamageTypes); shared.m_damagesPerLevel = default(DamageTypes); shared.m_attackForce = 0f; ScrollVisual.Apply(val3.ItemPrefab, val3.ItemDrop); ItemManager.Instance.AddItem(val3); _scroll = val3.ItemDrop; } private static void ConfigureSummonAttack(Attack attack, SharedData roots, float eitr) { if (roots.m_attack != null) { attack.m_startEffect = roots.m_attack.m_startEffect; attack.m_triggerEffect = roots.m_attack.m_triggerEffect; attack.m_burstEffect = roots.m_attack.m_burstEffect; attack.m_trailStartEffect = roots.m_attack.m_trailStartEffect; } attack.m_attackEitr = eitr; attack.m_projectiles = 1; attack.m_projectileBursts = 1; attack.m_damageMultiplier = 0f; attack.m_forceMultiplier = 0f; } private static GameObject ResolveKvastur() { string[] array = new string[2] { "BogWitchKvastur", "Kvastur" }; for (int i = 0; i < array.Length; i++) { GameObject val = RootboundContent.FindPrefab(array[i]); if (IsLivingKvastur(val)) { return val; } } if ((Object)(object)ZNetScene.instance == (Object)null) { return LoadSoftReferencedKvastur(); } GameObject val2 = ZNetScene.instance.m_prefabs.Concat(ZNetScene.instance.m_nonNetViewPrefabs).FirstOrDefault((Func)delegate(GameObject prefab) { Character val4 = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent() : null); return IsLivingKvastur(prefab) && (Object)(object)val4 != (Object)null && string.Equals(val4.m_name, "$enemy_kvastur", StringComparison.OrdinalIgnoreCase); }); if (Object.op_Implicit((Object)(object)val2)) { return val2; } GameObject val3 = ZNetScene.instance.m_prefabs.Concat(ZNetScene.instance.m_nonNetViewPrefabs).FirstOrDefault((Func)((GameObject prefab) => IsLivingKvastur(prefab) && ((Object)prefab).name.IndexOf("kvastur", StringComparison.OrdinalIgnoreCase) >= 0)); if (!Object.op_Implicit((Object)(object)val3)) { return LoadSoftReferencedKvastur(); } return val3; } private static bool TryRegisterCompanionPrefab() { if (Object.op_Implicit((Object)(object)_summonPrefab)) { return true; } GameObject val = ResolveKvastur(); if (!IsLivingKvastur(val)) { return false; } RegisterCompanionPrefab(val); return true; } private static GameObject LoadSoftReferencedKvastur() { //IL_000a: 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) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) try { _sourceReference = AssetManager.Instance.GetSoftReference("BogWitchKvastur"); _ = _sourceReference; if (!_sourceReference.IsValid) { return null; } _sourceReference.Load(); _sourceReference.WaitForLoadToComplete(); GameObject asset = _sourceReference.Asset; if (Object.op_Implicit((Object)(object)asset)) { _sourceReference.HoldReference(); RootboundWitchPlugin.Log.LogInfo((object)"Loaded living Kvastur from Jotunn's extended soft-reference table."); } return asset; } catch (Exception ex) { RootboundWitchPlugin.Log.LogWarning((object)("Soft-reference load for BogWitchKvastur failed: " + ex.Message)); return null; } } private static bool IsLivingKvastur(GameObject prefab) { if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null && (Object)(object)prefab.GetComponent() != (Object)null) { return (Object)(object)prefab.GetComponent() != (Object)null; } return false; } private static Vector3 FindSpawnPoint(Player player) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0027: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_006b: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * 2.5f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val + Vector3.up * 3f, Vector3.down, ref val2, 8f, -1, (QueryTriggerInteraction)1)) { val = ((RaycastHit)(ref val2)).point + Vector3.up * 0.15f; } return val; } } internal sealed class RootboundKvasturOwnership : MonoBehaviour { private sealed class PendingSpawn { internal readonly long OwnerId; internal readonly Vector3 Position; internal readonly float ExpiresAt; internal PendingSpawn(long ownerId, Vector3 position, float expiresAt) { //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) OwnerId = ownerId; Position = position; ExpiresAt = expiresAt; } } private const string OwnerKey = "ADARC_RootboundKvasturOwner"; private static readonly HashSet Active = new HashSet(); private static readonly List Pending = new List(); private ZNetView _view; private MonsterAI _ai; private long _ownerId; private float _nextFollowCheck; private void Awake() { _view = ((Component)this).GetComponent(); _ai = ((Component)this).GetComponent(); Active.Add(this); TryClaimPendingSpawn(); } private void OnDestroy() { Active.Remove(this); } private void Update() { if (!(Time.time < _nextFollowCheck)) { _nextFollowCheck = Time.time + 2f; TryClaimPendingSpawn(); AttachToOwner(); } } internal static void QueueSpawn(Player player, Vector3 position) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { long ownerId = player.GetPlayerID(); Pending.RemoveAll((PendingSpawn request) => request.OwnerId == ownerId || request.ExpiresAt <= Time.time); Pending.Add(new PendingSpawn(ownerId, position, Time.time + 20f)); } } internal void Assign(Player player) { if (!((Object)(object)player == (Object)null)) { _ownerId = player.GetPlayerID(); if ((Object)(object)_view != (Object)null && _view.GetZDO() != null) { _view.GetZDO().Set("ADARC_RootboundKvasturOwner", _ownerId); } Configure(player); } } internal static bool Recall(long playerId) { //IL_0060: 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) bool result = false; Player val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player player) => (Object)(object)player != (Object)null && player.GetPlayerID() == playerId)); RootboundKvasturOwnership[] array = Active.ToArray(); foreach (RootboundKvasturOwnership rootboundKvasturOwnership in array) { if (!((Object)(object)rootboundKvasturOwnership == (Object)null)) { long num2 = rootboundKvasturOwnership.OwnerId(); bool flag = num2 == 0L && (Object)(object)val != (Object)null && Vector3.Distance(((Component)rootboundKvasturOwnership).transform.position, ((Component)val).transform.position) <= 80f; if (num2 == playerId || flag) { rootboundKvasturOwnership.Kill(); result = true; } } } Pending.RemoveAll((PendingSpawn request) => request.OwnerId == playerId); return result; } private void AttachToOwner() { long ownerId = OwnerId(); Player val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player player) => (Object)(object)player != (Object)null && player.GetPlayerID() == ownerId)); if ((Object)(object)val != (Object)null) { Configure(val); } } private void Configure(Player owner) { if ((Object)(object)_view == (Object)null) { _view = ((Component)this).GetComponent(); } if ((Object)(object)_ai == (Object)null) { _ai = ((Component)this).GetComponent(); } if ((Object)(object)_ai != (Object)null) { _ai.MakeTame(); _ai.SetFollowTarget(((Component)owner).gameObject); _ai.SetDespawnInDay(false); } } private long OwnerId() { if ((Object)(object)_view != (Object)null && _view.GetZDO() != null) { long num = _view.GetZDO().GetLong("ADARC_RootboundKvasturOwner", 0L); if (num != 0L) { _ownerId = num; } } return _ownerId; } private void TryClaimPendingSpawn() { if (OwnerId() != 0L || (Object)(object)_view == (Object)null || _view.GetZDO() == null || !_view.IsOwner()) { return; } Pending.RemoveAll((PendingSpawn pendingSpawn) => pendingSpawn.ExpiresAt <= Time.time); PendingSpawn request = (from candidate in Pending where Vector3.Distance(candidate.Position, ((Component)this).transform.position) <= 20f orderby Vector3.Distance(candidate.Position, ((Component)this).transform.position) select candidate).FirstOrDefault(); if (request != null) { Pending.Remove(request); Player val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player player) => (Object)(object)player != (Object)null && player.GetPlayerID() == request.OwnerId)); if ((Object)(object)val != (Object)null) { Assign(val); } } } private void Kill() { RootboundSummonRecall.Kill(((Component)this).GetComponent(), _view); } } [HarmonyPatch(typeof(Trader), "GetAvailableItems")] internal static class RootboundBogWitchTradePatch { private static void Postfix(Trader __instance, ref List __result) { Player localPlayer = Player.m_localPlayer; if (!RootboundWitchPlugin.EnableKvasturScroll.Value || !RootboundKvasturScroll.IsBogWitch(__instance) || !RootboundState.IsFullSet(localPlayer)) { return; } TradeItem scroll = RootboundKvasturScroll.GetTradeItem(); if (scroll != null && __result.All((TradeItem item) => (Object)(object)item.m_prefab != (Object)(object)scroll.m_prefab)) { __result.Add(scroll); } if (RootboundWitchPlugin.EnableGaldrCharter.Value && RootboundGaldrCharter.HasKvasturRecognition(localPlayer)) { TradeItem charter = RootboundGaldrCharter.GetTradeItem(); if (charter != null && __result.All((TradeItem item) => (Object)(object)item.m_prefab != (Object)(object)charter.m_prefab)) { __result.Add(charter); } } } } internal static class ScrollVisual { private static readonly Color Parchment = new Color(0.62f, 0.5f, 0.3f, 1f); private static readonly Color MossInk = new Color(0.16f, 0.28f, 0.11f, 1f); internal static void Apply(GameObject prefab, ItemDrop drop) { //IL_002c: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0087: 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) Renderer val = prefab.GetComponentsInChildren(true).FirstOrDefault(); Material val2 = ((!((Object)(object)val != (Object)null) || !Object.op_Implicit((Object)(object)val.sharedMaterial)) ? ((Material)null) : new Material(val.sharedMaterial)); Renderer[] componentsInChildren = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } if ((Object)(object)val2 != (Object)null) { Material val3 = new Material(val2) { name = "RootboundScroll_Parchment" }; Material val4 = new Material(val2) { name = "RootboundScroll_MossInk" }; SetColor(val3, Parchment); SetColor(val4, MossInk); AddScrollMesh(prefab.transform, val3, val4); } Texture2D val5 = BuildIcon(); drop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { Sprite.Create(val5, new Rect(0f, 0f, (float)((Texture)val5).width, (float)((Texture)val5).height), new Vector2(0.5f, 0.5f), 64f) }; } private static void AddScrollMesh(Transform parent, Material paper, Material ink) { //IL_003e: 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_00ba: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)obj).name = "Rootbound_ScrollBody"; Object.DestroyImmediate((Object)(object)obj.GetComponent()); obj.transform.SetParent(parent, false); obj.transform.localPosition = new Vector3(0f, 0.58f, 0f); obj.transform.localScale = new Vector3(0.34f, 0.025f, 0.22f); obj.GetComponent().sharedMaterial = paper; for (int i = -1; i <= 1; i += 2) { GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)2); ((Object)obj2).name = "Rootbound_ScrollRoll"; Object.DestroyImmediate((Object)(object)obj2.GetComponent()); obj2.transform.SetParent(parent, false); obj2.transform.localPosition = new Vector3((float)i * 0.18f, 0.58f, 0f); obj2.transform.localRotation = Quaternion.Euler(90f, 0f, 0f); obj2.transform.localScale = new Vector3(0.045f, 0.13f, 0.045f); obj2.GetComponent().sharedMaterial = paper; } GameObject obj3 = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)obj3).name = "Rootbound_ScrollMark"; Object.DestroyImmediate((Object)(object)obj3.GetComponent()); obj3.transform.SetParent(parent, false); obj3.transform.localPosition = new Vector3(0f, 0.597f, 0f); obj3.transform.localScale = new Vector3(0.07f, 0.008f, 0.15f); obj3.GetComponent().sharedMaterial = ink; } private static Texture2D BuildIcon() { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_009c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { name = "Rootbound_KvasturScrollIcon", filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1 }; Color[] array = Enumerable.Repeat(new Color(0f, 0f, 0f, 0f), 4096).ToArray(); for (int i = 14; i < 50; i++) { for (int j = 12; j < 52; j++) { bool flag = j < 16 || j > 47 || i < 18 || i > 45; array[i * 64 + j] = (Color)(flag ? new Color(0.28f, 0.19f, 0.09f, 1f) : Parchment); } } for (int k = 22; k < 42; k++) { int num = 32 + Mathf.RoundToInt(Mathf.Sin((float)k * 0.55f) * 6f); for (int l = -2; l <= 2; l++) { array[k * 64 + Mathf.Clamp(num + l, 0, 63)] = MossInk; } } val.SetPixels(array); val.Apply(false, true); return val; } private static void SetColor(Material material, Color color) { //IL_0013: 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_0045: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", color); } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); } material.DisableKeyword("_EMISSION"); } } internal static class RootboundMeatReclamation { private static readonly string[] DirectAnimalTokens = new string[18] { "meat", "fish", "necktail", "neck_tail", "bloodbag", "blood_bag", "egg", "sausage", "serpentstew", "wolfjerky", "deerstew", "loxpie", "bloodpudding", "meatplatter", "misthare", "chickensoup", "harepie", "seekeraspic" }; private static bool _registered; private static readonly HashSet MeatItems = new HashSet(StringComparer.OrdinalIgnoreCase); internal static void Register() { //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Expected O, but got Unknown if (_registered) { return; } if ((Object)(object)ObjectDB.instance == (Object)null) { throw new InvalidOperationException("ObjectDB is unavailable for Charter meat reclamation."); } GameObject val = RootboundContent.FindPrefab("Sap"); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("Vanilla Sap is unavailable for Charter meat reclamation."); } Dictionary dictionary = (from @group in (from prefab in ObjectDB.instance.m_items where Object.op_Implicit((Object)(object)prefab) select prefab.GetComponent()).Where(IsConvertibleItemType).GroupBy((ItemDrop drop) => PrefabName(drop), StringComparer.OrdinalIgnoreCase) where !string.IsNullOrEmpty(@group.Key) select @group).ToDictionary, string, ItemDrop>((IGrouping group) => group.Key, (IGrouping group) => group.First(), StringComparer.OrdinalIgnoreCase); HashSet meatItems = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair item in dictionary) { if (IsDirectAnimalItem(item.Value)) { meatItems.Add(item.Key); } } bool flag; do { flag = false; foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && IsConvertibleItemType(recipe.m_item) && recipe.m_resources != null) { string text = PrefabName(recipe.m_item); if (!string.IsNullOrEmpty(text) && !meatItems.Contains(text) && recipe.m_resources.Any((Requirement requirement) => requirement != null && (Object)(object)requirement.m_resItem != (Object)null && meatItems.Contains(PrefabName(requirement.m_resItem)))) { meatItems.Add(text); flag = true; } } } } while (flag); int num = 0; foreach (string item2 in meatItems.OrderBy((string name) => name, StringComparer.OrdinalIgnoreCase)) { if (dictionary.TryGetValue(item2, out var value) && !((Object)(object)value == (Object)(object)val2)) { Recipe val3 = ScriptableObject.CreateInstance(); ((Object)val3).name = "Recipe_RootboundReclaimToSap_" + SafeName(item2); val3.m_item = val2; val3.m_amount = 1; val3.m_enabled = true; val3.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = value, m_amount = 1, m_recover = true } }; RootboundGaldrCharter.RegisterCharterOnlyRecipe(val3); num++; } } MeatItems.Clear(); MeatItems.UnionWith(meatItems); _registered = true; RootboundWitchPlugin.Log.LogInfo((object)$"Galdr Charter registered {num} live meat-to-Sap reclamation recipes at one Sap per item."); } internal static bool CreatureYieldsMeat(Character creature) { if ((Object)(object)creature == (Object)null || creature is Player) { return false; } CharacterDrop component = ((Component)creature).GetComponent(); if ((Object)(object)component != (Object)null && component.m_drops != null) { return component.m_drops.Any((Drop drop) => drop != null && Object.op_Implicit((Object)(object)drop.m_prefab) && MeatItems.Contains(((Object)drop.m_prefab).name.Replace("(Clone)", string.Empty).Trim())); } return false; } private static bool IsConvertibleItemType(ItemDrop drop) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 if ((Object)(object)drop == (Object)null || drop.m_itemData == null || drop.m_itemData.m_shared == null) { return false; } ItemType itemType = drop.m_itemData.m_shared.m_itemType; if ((int)itemType != 1) { return (int)itemType == 2; } return true; } private static bool IsDirectAnimalItem(ItemDrop drop) { ItemData itemData = drop.m_itemData; if (RootboundState.IsAnimalFood(itemData)) { return true; } string text = (PrefabName(drop) + " " + itemData.m_shared.m_name).ToLowerInvariant(); IEnumerable second = from token in (RootboundWitchPlugin.AnimalFoodTokens.Value ?? string.Empty).Split(new char[3] { ',', ';', '|' }, StringSplitOptions.RemoveEmptyEntries) select token.Trim().ToLowerInvariant() into token where token.Length > 0 select token; return DirectAnimalTokens.Concat(second).Any(text.Contains); } private static string PrefabName(ItemDrop drop) { if ((Object)(object)drop == (Object)null) { return string.Empty; } return ((Object)((Component)drop).gameObject).name.Replace("(Clone)", string.Empty).Trim(); } private static string SafeName(string value) { return new string(value.Select((char character) => (!char.IsLetterOrDigit(character)) ? '_' : character).ToArray()); } } internal static class RootboundState { private static readonly FieldRef Helmet = AccessTools.FieldRefAccess("m_helmetItem"); private static readonly FieldRef Chest = AccessTools.FieldRefAccess("m_chestItem"); private static readonly FieldRef Legs = AccessTools.FieldRefAccess("m_legItem"); private static readonly FieldRef Right = AccessTools.FieldRefAccess("m_rightItem"); private static readonly FieldRef Left = AccessTools.FieldRefAccess("m_leftItem"); private static readonly FieldRef Shoulder = AccessTools.FieldRefAccess("m_shoulderItem"); private static readonly FieldRef Utility = AccessTools.FieldRefAccess("m_utilityItem"); private static readonly FieldRef Trinket = AccessTools.FieldRefAccess("m_trinketItem"); internal static IEnumerable Armour(Player player) { if (!((Object)(object)player == (Object)null)) { yield return Helmet.Invoke((Humanoid)(object)player); yield return Chest.Invoke((Humanoid)(object)player); yield return Legs.Invoke((Humanoid)(object)player); } } internal static IEnumerable NonArmourEquipment(Player player) { if (!((Object)(object)player == (Object)null)) { yield return Right.Invoke((Humanoid)(object)player); yield return Left.Invoke((Humanoid)(object)player); yield return Shoulder.Invoke((Humanoid)(object)player); yield return Utility.Invoke((Humanoid)(object)player); yield return Trinket.Invoke((Humanoid)(object)player); } } internal static bool HasMatureCrookEquipped(Player player) { if ((Object)(object)player == (Object)null) { return false; } ItemData val = Right.Invoke((Humanoid)(object)player); ItemData val2 = Left.Invoke((Humanoid)(object)player); if (!HasPrefab(val, "RootboundCrook") || val.m_quality < 2) { if (HasPrefab(val2, "RootboundCrook")) { return val2.m_quality >= 2; } return false; } return true; } internal static bool IsDvergerMarked(Player player) { if ((Object)(object)player != (Object)null) { if ((!IsFullSet(player) || MinimumQuality(player) < 2) && !HasMatureCrookEquipped(player)) { return RootboundNetworkState.HasDvergerMark(player); } return true; } return false; } internal static bool IsFullSet(Player player) { ItemData[] array = Armour(player).ToArray(); if (array.Length == 3 && HasPrefab(array[0], "RootboundMask") && HasPrefab(array[1], "RootboundHarness")) { return HasPrefab(array[2], "RootboundLeggings"); } return false; } internal static int MinimumQuality(Player player) { if (!IsFullSet(player)) { return 0; } return (from item in Armour(player) where item != null select item).Min((ItemData item) => item.m_quality); } internal static int EquippedPieceCount(Player player) { return Armour(player).Count(IsRootboundPiece); } internal static float StaticEitr(Player player) { return Armour(player).Where(IsRootboundPiece).Sum((ItemData item) => 6f + 6f * (float)Mathf.Clamp(item.m_quality, 1, 4)) + (IsCharmEquipped(player) ? Mathf.Max(0f, RootboundWitchPlugin.CharmStaticEitr.Value) : 0f); } internal static bool IsCharmEquipped(Player player) { if ((Object)(object)player != (Object)null) { return HasPrefab(Trinket.Invoke((Humanoid)(object)player), "RootboundCharm"); } return false; } internal static float EitrRegenModifier(Player player) { return Armour(player).Where(IsRootboundPiece).Sum((ItemData item) => 0.08f + 0.04f * (float)(Mathf.Clamp(item.m_quality, 1, 4) - 1)); } internal static bool IsPermafrost(Player player) { if (IsFullSet(player)) { return MinimumQuality(player) >= 4; } return false; } internal static bool HasPrefab(ItemData item, string prefabName) { return string.Equals(PrefabName(item), prefabName, StringComparison.OrdinalIgnoreCase); } internal static bool IsRootboundPiece(ItemData item) { string a = PrefabName(item); if (!string.Equals(a, "RootboundMask", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "RootboundHarness", StringComparison.OrdinalIgnoreCase)) { return string.Equals(a, "RootboundLeggings", StringComparison.OrdinalIgnoreCase); } return true; } internal static string PrefabName(ItemData item) { if (item == null || !Object.op_Implicit((Object)(object)item.m_dropPrefab)) { return string.Empty; } return ((Object)item.m_dropPrefab).name.Replace("(Clone)", string.Empty).Trim(); } internal static bool IsAnimalFood(ItemData item) { if (item == null || item.m_shared == null || item.m_shared.m_food <= 0f) { return false; } string probe = (PrefabName(item) + " " + item.m_shared.m_name).ToLowerInvariant(); return SplitTokens(RootboundWitchPlugin.AnimalFoodTokens.Value).Any((string token) => probe.Contains(token)); } internal static bool IsMetalEquipment(ItemData item) { //IL_0021: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null || IsRootboundPiece(item)) { return false; } ItemType itemType = item.m_shared.m_itemType; if ((int)itemType == 1 || (int)itemType == 2 || (int)itemType == 13 || (int)itemType <= 0) { return false; } HashSet metals = new HashSet(SplitTokens(RootboundWitchPlugin.MetalIngredientPrefabs.Value), StringComparer.OrdinalIgnoreCase); if ((Object)(object)ObjectDB.instance != (Object)null) { Recipe recipe = ObjectDB.instance.GetRecipe(item); if ((Object)(object)recipe != (Object)null && recipe.m_resources != null && recipe.m_resources.Any((Requirement requirement) => requirement != null && (Object)(object)requirement.m_resItem != (Object)null && metals.Contains(((Object)((Component)requirement.m_resItem).gameObject).name.Replace("(Clone)", string.Empty)))) { return true; } } string probe = (PrefabName(item) + " " + item.m_shared.m_name).ToLowerInvariant(); return metals.Any((string metal) => probe.Contains(metal.ToLowerInvariant())); } internal static bool IsGreydwarf(Character character) { if ((Object)(object)character == (Object)null) { return false; } string text = (((Object)((Component)character).gameObject).name + " " + character.GetHoverName()).ToLowerInvariant(); if (!text.Contains("greyling") && !text.Contains("grayling") && !text.Contains("greydwarf") && !text.Contains("graydwarf") && !text.Contains("grey dwarf")) { return text.Contains("gray dwarf"); } return true; } internal static bool IsDverger(Character character) { if ((Object)(object)character == (Object)null) { return false; } string text = (((Object)((Component)character).gameObject).name + " " + character.GetHoverName()).ToLowerInvariant(); if (!text.Contains("dverger")) { return text.Contains("dvergr"); } return true; } internal static bool IsHomeBiome(Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 Biome currentBiome = player.GetCurrentBiome(); if (IsPermafrost(player)) { return (int)currentBiome == 64; } if ((int)currentBiome != 8) { return (int)currentBiome == 512; } return true; } internal static void RejectEquippedMetal(Player player) { if (RootboundWitchPlugin.EnableRestrictions.Value && IsFullSet(player)) { ItemData[] array = NonArmourEquipment(player).Where(IsMetalEquipment).Distinct().ToArray(); foreach (ItemData val in array) { ((Humanoid)player).UnequipItem(val, true); Show("$msg_rootbound_reject_metal"); } } } internal static void Show(string localizationToken) { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, localizationToken, 0, (Sprite)null, false, true); } } private static IEnumerable SplitTokens(string raw) { return from value in (raw ?? string.Empty).Split(new char[3] { ',', ';', '|' }, StringSplitOptions.RemoveEmptyEntries) select value.Trim().ToLowerInvariant() into value where value.Length > 0 select value; } } internal sealed class RootboundRuntime : MonoBehaviour { private readonly Collider[] _treeHits = (Collider[])(object)new Collider[96]; private float _stationaryFor; private float _rootedUntil; private float _rootCooldownUntil; private float _environmentTick; private bool _wasActive; private bool _uprootRequested; internal static bool IsRootedLocal { get; private set; } internal void RequestUproot() { _uprootRequested = true; } private void Update() { Player localPlayer = Player.m_localPlayer; RootboundAura.UpdateLocal(localPlayer); RootboundNetworkState.UpdateLocal(localPlayer); RootboundDoubleJump.UpdateGroundState(localPlayer); bool flag = (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && RootboundState.IsFullSet(localPlayer); BogWitchBackGrowth.Update(localPlayer, flag); if (!flag) { ResetInactive(); return; } if (!_wasActive) { RootboundState.RejectEquippedMetal(localPlayer); _wasActive = true; } float time = Time.time; float deltaTime = Time.deltaTime; UpdateRootHold(localPlayer, time, deltaTime); _environmentTick += deltaTime; if (_environmentTick >= 1f) { float environmentTick = _environmentTick; _environmentTick = 0f; ApplyEnvironment(localPlayer, environmentTick); RootboundState.RejectEquippedMetal(localPlayer); } PermafrostVisuals.Update(localPlayer, RootboundWitchPlugin.EnablePermafrostTint.Value && RootboundState.IsPermafrost(localPlayer)); } private void UpdateRootHold(Player player, float now, float dt) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (!RootboundWitchPlugin.EnableRooting.Value) { IsRootedLocal = false; _stationaryFor = 0f; _uprootRequested = false; return; } if (IsRootedLocal) { ((Character)player).Heal(RootboundWitchPlugin.RootHealPerSecond.Value * dt, true); if (now < _rootedUntil || !_uprootRequested) { return; } IsRootedLocal = false; _uprootRequested = false; _rootCooldownUntil = now + Mathf.Max(0f, RootboundWitchPlugin.RootCooldown.Value); RootboundState.Show("$msg_rootbound_uprooted"); } Vector3 velocity = ((Character)player).GetVelocity(); velocity.y = 0f; bool flag = ((Character)player).IsOnGround() && ((Vector3)(ref velocity)).sqrMagnitude < 0.0225f; _stationaryFor = (flag ? (_stationaryFor + dt) : 0f); if (flag && now >= _rootCooldownUntil && _stationaryFor >= Mathf.Max(0.25f, RootboundWitchPlugin.RootDelay.Value)) { IsRootedLocal = true; _rootedUntil = now + Mathf.Max(0.25f, RootboundWitchPlugin.RootDuration.Value); _uprootRequested = false; _stationaryFor = 0f; RootboundState.Show("$msg_rootbound_rooted"); } } private void ApplyEnvironment(Player player, float seconds) { if (RootboundWitchPlugin.EnableTreeBlessing.Value && EnvironmentSupports(player)) { ((Character)player).Heal(RootboundWitchPlugin.TreeHealPerSecond.Value * seconds, true); } if (RootboundWitchPlugin.EnableStoneWither.Value && IsStandingOnWorkedStone(player)) { ((Character)player).UseHealth(RootboundWitchPlugin.StoneWitherPerSecond.Value * seconds); } } private bool EnvironmentSupports(Player player) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if (RootboundState.IsPermafrost(player)) { return (int)player.GetCurrentBiome() == 64; } int num = Physics.OverlapSphereNonAlloc(((Component)player).transform.position, Mathf.Max(1f, RootboundWitchPlugin.TreeRadius.Value), _treeHits, -1, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { if ((Object)(object)_treeHits[i] != (Object)null && (Object)(object)((Component)_treeHits[i]).GetComponentInParent() != (Object)null) { return true; } } return false; } private static bool IsStandingOnWorkedStone(Player player) { //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) RaycastHit val = default(RaycastHit); if (!Physics.Raycast(((Component)player).transform.position + Vector3.up * 0.25f, Vector3.down, ref val, 2.25f, -1, (QueryTriggerInteraction)1)) { return false; } Piece val2 = (((Object)(object)((RaycastHit)(ref val)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent() : null); if ((Object)(object)val2 == (Object)null) { return false; } string text = ((Object)((Component)val2).gameObject).name.ToLowerInvariant(); if (!text.Contains("stone")) { return text.Contains("marble"); } return true; } private void ResetInactive() { IsRootedLocal = false; _stationaryFor = 0f; _uprootRequested = false; _environmentTick = 0f; _wasActive = false; PermafrostVisuals.Clear(); } } [HarmonyPatch(typeof(Player), "SetMaxEitr")] internal static class RootboundMaxEitrPatch { private static void Prefix(Player __instance, ref float eitr, bool flashBar) { if (flashBar) { eitr += RootboundState.StaticEitr(__instance); } } } [HarmonyPatch(typeof(Player), "GetEquipmentEitrRegenModifier")] internal static class RootboundEitrRegenPatch { private static void Postfix(Player __instance, ref float __result) { __result += RootboundState.EitrRegenModifier(__instance); } } [HarmonyPatch(typeof(Humanoid), "CanConsumeItem")] internal static class RootboundFoodPatch { private static void Postfix(Humanoid __instance, ItemData item, ref bool __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (__result && RootboundWitchPlugin.EnableRestrictions.Value && RootboundState.IsFullSet(val) && RootboundState.IsAnimalFood(item)) { __result = false; if ((Object)(object)val == (Object)(object)Player.m_localPlayer) { RootboundState.Show("$msg_rootbound_reject_meat"); } } } } [HarmonyPatch(typeof(Humanoid), "EquipItem")] internal static class RootboundEquipPatch { private static bool Prefix(Humanoid __instance, ItemData item, ref bool __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (RootboundWitchPlugin.EnableRestrictions.Value && RootboundState.IsFullSet(val) && RootboundState.IsMetalEquipment(item)) { __result = false; if ((Object)(object)val == (Object)(object)Player.m_localPlayer) { RootboundState.Show("$msg_rootbound_reject_metal"); } return false; } return true; } } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] internal static class RootboundGreydwarfAlliancePatch { private static bool Prefix(Character a, Character b, ref bool __result) { Player player = (Player)(object)((a is Player) ? a : null); Player player2 = (Player)(object)((b is Player) ? b : null); if ((RootboundState.IsDvergerMarked(player) && RootboundState.IsDverger(b)) || (RootboundState.IsDvergerMarked(player2) && RootboundState.IsDverger(a))) { __result = true; return false; } if ((RootboundNetworkState.HasKinship(player) && RootboundState.IsGreydwarf(b)) || (RootboundNetworkState.HasKinship(player2) && RootboundState.IsGreydwarf(a))) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class RootboundDamagePatch { private static void Prefix(Character __instance, HitData hit) { Player player = (Player)(object)((__instance is Player) ? __instance : null); if (RootboundWitchPlugin.EnableRestrictions.Value && RootboundState.IsFullSet(player) && hit != null) { hit.m_damage.m_fire *= (RootboundState.IsPermafrost(player) ? RootboundWitchPlugin.PermafrostFireDamageMultiplier.Value : RootboundWitchPlugin.FireDamageMultiplier.Value); if (RootboundState.IsPermafrost(player)) { hit.m_damage.m_frost = 0f; } } } } [HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")] internal static class RootboundStaminaPatch { private static readonly FieldRef Character = AccessTools.FieldRefAccess("m_character"); private static void Postfix(SEMan __instance, ref float staminaMultiplier) { Character obj = Character.Invoke(__instance); Player player = (Player)(object)((obj is Player) ? obj : null); if (RootboundState.IsFullSet(player) && RootboundState.IsHomeBiome(player)) { staminaMultiplier *= Mathf.Max(0f, RootboundWitchPlugin.BiomeStaminaMultiplier.Value); } } } [HarmonyPatch(typeof(SEMan), "ApplyStatusEffectSpeedMods")] internal static class RootboundSharedVigorCostPatch { private static readonly FieldRef Character = AccessTools.FieldRefAccess("m_character"); private static void Postfix(SEMan __instance, ref float speed) { Character obj = Character.Invoke(__instance); Player val = (Player)(object)((obj is Player) ? obj : null); if ((Object)(object)val == (Object)(object)Player.m_localPlayer && RootboundAura.ShouldSlowWearer(val)) { speed *= Mathf.Clamp(RootboundWitchPlugin.SharedStaminaWearerSpeedMultiplier.Value, 0f, 1f); } } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class RootboundControlsPatch { private static void Prefix(Player __instance, ref Vector3 movedir, ref bool jump, ref bool run, ref bool autoRun, ref bool dodge) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)(object)Player.m_localPlayer) || !RootboundRuntime.IsRootedLocal) { return; } if (((((Vector3)(ref movedir)).sqrMagnitude > 0.0001f) | jump | run | autoRun | dodge) && (Object)(object)RootboundWitchPlugin.Instance != (Object)null) { RootboundRuntime component = ((Component)RootboundWitchPlugin.Instance).GetComponent(); if ((Object)(object)component != (Object)null) { component.RequestUproot(); } } movedir = Vector3.zero; jump = false; run = false; autoRun = false; dodge = false; } } [HarmonyPatch(typeof(ImpactEffect), "OnCollisionEnter")] internal static class RootboundFallingTreePatch { private static bool Prefix(ImpactEffect __instance, Collision info) { if ((Object)(object)((Component)__instance).GetComponentInParent() == (Object)null || info == null || (Object)(object)info.collider == (Object)null) { return true; } return !RootboundState.IsFullSet(((Component)info.collider).GetComponentInParent()); } } internal static class RootboundModerCompanion { private const string CompanionPrefab = "RootboundModerCompanion"; private static readonly FieldRef AttackCharacter = AccessTools.FieldRefAccess("m_character"); private static readonly FieldRef AttackWeapon = AccessTools.FieldRefAccess("m_weapon"); private static GameObject _companion; private static SoftReference _dragonReference; private static bool _companionRegistered; internal static void Register() { RegisterSigil(); if (!TryRegisterCompanion()) { RootboundWitchPlugin.Log.LogWarning((object)"Rootbound Moder Sigil registered; the live Dragon source will be loaded again when first used."); } } internal static bool IsOurAttack(Attack attack) { if (attack != null) { return RootboundState.HasPrefab(AttackWeapon.Invoke(attack), "RootboundModerSigil"); } return false; } internal static void Use(Attack attack) { //IL_0075: 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_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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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) Humanoid obj = AttackCharacter.Invoke(attack); Player val = (Player)(object)((obj is Player) ? obj : null); if (!RootboundSummonRecall.HasLocalAttackAuthority(val)) { return; } if (attack.m_attackEitr <= 0.001f) { if (RootboundModerOwnership.Recall(val.GetPlayerID())) { RootboundState.Show("$msg_rootbound_moder_recalled"); } return; } if (!Object.op_Implicit((Object)(object)_companion) && !TryRegisterCompanion()) { RootboundWitchPlugin.Log.LogError((object)"Rootbound Moder requested, but the live Dragon prefab is unavailable."); return; } RootboundModerOwnership.Recall(val.GetPlayerID()); Vector3 val2 = ((Component)val).transform.position + ((Component)val).transform.forward * 18f + Vector3.up * 8f; RootboundModerOwnership.QueueSpawn(val, val2); if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.SpawnObject(val2, ((Component)val).transform.rotation, _companion); } else { GameObject obj2 = Object.Instantiate(_companion, val2, ((Component)val).transform.rotation); obj2.SetActive(true); RootboundModerOwnership component = obj2.GetComponent(); if ((Object)(object)component != (Object)null) { component.Assign(val); } } RootboundState.Show("$msg_rootbound_moder_summoned"); } private static void RegisterSigil() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) string text = (Object.op_Implicit((Object)(object)RootboundContent.FindPrefab("StaffSkeleton")) ? "StaffSkeleton" : "StaffFireball"); GameObject obj = RootboundContent.FindPrefab(text); GameObject val = RootboundContent.FindPrefab("StaffIceShards") ?? RootboundContent.FindPrefab("StaffFrostOrbs"); if (!Object.op_Implicit((Object)(object)obj) || !Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("A summon item or frost-effect source is missing for the Moder Sigil."); } CustomItem val2 = new CustomItem("RootboundModerSigil", text); SharedData shared = val2.ItemDrop.m_itemData.m_shared; SharedData shared2 = obj.GetComponent().m_itemData.m_shared; SharedData shared3 = val.GetComponent().m_itemData.m_shared; Attack val3 = shared2.m_attack.Clone(); if (shared3.m_attack != null) { val3.m_startEffect = shared3.m_attack.m_startEffect; val3.m_triggerEffect = shared3.m_attack.m_triggerEffect; val3.m_burstEffect = shared3.m_attack.m_burstEffect; val3.m_trailStartEffect = shared3.m_attack.m_trailStartEffect; } val3.m_attackEitr = Mathf.Max(0f, RootboundWitchPlugin.ModerCompanionSummonEitr.Value); val3.m_attackEitrAdd = 0f; val3.m_attackHealth = 0f; val3.m_attackHealthPercentage = 0f; val3.m_projectiles = 1; val3.m_projectileBursts = 1; val3.m_damageMultiplier = 0f; val3.m_forceMultiplier = 0f; shared.m_name = "$item_rootbound_moder_sigil"; shared.m_description = "$item_rootbound_moder_sigil_desc"; shared.m_maxQuality = 1; shared.m_maxStackSize = 1; shared.m_weight = 0.2f; shared.m_attack = val3; shared.m_secondaryAttack = RootboundSummonRecall.BuildAxeStrikeAttack(); shared.m_damages = default(DamageTypes); shared.m_damagesPerLevel = default(DamageTypes); shared.m_attackForce = 0f; ScrollVisual.Apply(val2.ItemPrefab, val2.ItemDrop); ItemManager.Instance.AddItem(val2); Recipe val4 = ScriptableObject.CreateInstance(); ((Object)val4).name = "Recipe_RootboundModerSigil"; val4.m_item = val2.ItemDrop; val4.m_amount = 1; val4.m_enabled = true; val4.m_resources = (Requirement[])(object)new Requirement[3] { Trophy("TrophyCultist_Hildir", "$item_trophy_cultist_hildir"), Trophy("TrophySkeletonHildir", "$item_trophy_skeleton_hildir"), Trophy("TrophyGoblinBruteBros|TrophyGoblinBruteBrosBrute|TrophyGoblinBruteBrosShaman", "$item_trophy_goblinbrute_bros") }; RootboundGaldrCharter.RegisterCharterOnlyRecipe(val4); RootboundWitchPlugin.Log.LogInfo((object)"Rootbound Moder Sigil registered only in the Charter's stationless Galdr layer using one trophy from each Hildir trial."); } private static Requirement Trophy(string candidates, string token) { //IL_0032: 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_003e: 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_004d: Expected O, but got Unknown string[] array = candidates.Split('|'); for (int i = 0; i < array.Length; i++) { GameObject val = RootboundContent.FindPrefab(array[i]); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if ((Object)(object)val2 != (Object)null) { return new Requirement { m_resItem = val2, m_amount = 1, m_recover = true }; } } throw new InvalidOperationException("Hildir trophy is missing for " + token + ": " + candidates); } private static bool TryRegisterCompanion() { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_companion) && _companionRegistered) { return true; } string text = "resolve Dragon"; try { GameObject val = RootboundContent.FindPrefab("Dragon") ?? LoadDragon(); if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val.GetComponent() == (Object)null || (Object)(object)val.GetComponent() == (Object)null || (Object)(object)val.GetComponent() == (Object)null) { return false; } text = "clone Dragon prefab"; GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("RootboundModerCompanion", val); Character val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); MonsterAI val4 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); if (!Object.op_Implicit((Object)(object)val2) || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null) { return false; } text = "configure dormant Dragon clone"; val3.m_name = "$enemy_rootbound_moder"; val3.m_faction = (Faction)11; val3.m_boss = false; val3.m_dontHideBossHud = false; val3.m_bossEvent = string.Empty; val3.m_defeatSetGlobalKey = string.Empty; val3.m_health = Mathf.Max(1f, RootboundWitchPlugin.ModerCompanionHealth.Value); val4.m_fleeIfLowHealth = 0f; CharacterDrop component = val2.GetComponent(); if ((Object)(object)component != (Object)null && component.m_drops != null) { component.m_drops.Clear(); } Tameable component2 = val2.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.m_startsTamed = true; component2.m_commandable = false; component2.m_unsummonOnOwnerLogoutSeconds = 10f; } if ((Object)(object)val2.GetComponent() == (Object)null) { val2.AddComponent(); } text = "register network prefab"; PrefabManager.Instance.AddPrefab(new CustomPrefab(val2, true)); _companion = val2; _companionRegistered = true; RootboundWitchPlugin.Log.LogInfo((object)($"Rootbound Moder cloned from {((Object)val).name} as a non-boss companion with {val3.m_health:0} health and " + $"{RootboundWitchPlugin.ModerCompanionDamageMultiplier.Value:0.##}x damage.")); return true; } catch (Exception ex) { _companion = null; _companionRegistered = false; RootboundWitchPlugin.Log.LogWarning((object)("Rootbound Moder companion registration deferred during '" + text + "':\n" + ex)); return false; } } private static GameObject LoadDragon() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //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_0053: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[3] { "Dragon", "Moder", "Assets/Characters/Dragon/Dragon.prefab" }; foreach (string text in array) { try { _dragonReference = AssetManager.Instance.GetSoftReference(text); _ = _dragonReference; if (_dragonReference.IsValid) { _dragonReference.Load(); _dragonReference.WaitForLoadToComplete(); GameObject asset = _dragonReference.Asset; if (Object.op_Implicit((Object)(object)asset)) { _dragonReference.HoldReference(); return asset; } } } catch (Exception ex) { RootboundWitchPlugin.Log.LogWarning((object)("Soft-reference load for Moder candidate '" + text + "' failed: " + ex.Message)); } } return null; } } internal sealed class RootboundModerOwnership : MonoBehaviour { private sealed class PendingSpawn { internal readonly long OwnerId; internal readonly Vector3 Position; internal readonly float ExpiresAt; internal PendingSpawn(long ownerId, Vector3 position, float expiresAt) { //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) OwnerId = ownerId; Position = position; ExpiresAt = expiresAt; } } private const string OwnerKey = "ADARC_RootboundModerOwner"; private const string ConfiguredKey = "ADARC_RootboundModerConfigured"; private static readonly HashSet Active = new HashSet(); private static readonly List Pending = new List(); private ZNetView _view; private MonsterAI _ai; private Character _character; private long _ownerId; private float _nextUpdate; private float _combatIdleSoundInterval; private float _combatIdleSoundChance; private bool _capturedCombatVoice; private void Awake() { _view = ((Component)this).GetComponent(); _ai = ((Component)this).GetComponent(); _character = ((Component)this).GetComponent(); CaptureCombatVoice(); Active.Add(this); TryClaim(); } private void OnDestroy() { Active.Remove(this); } private void Update() { UpdateCombatVoice(); if (!(Time.time < _nextUpdate)) { _nextUpdate = Time.time + 2f; TryClaim(); Player val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerID() == OwnerId())); if ((Object)(object)val != (Object)null) { Configure(val); } } } private void CaptureCombatVoice() { if (!((Object)(object)_ai == (Object)null) && !_capturedCombatVoice) { _combatIdleSoundInterval = ((BaseAI)_ai).m_idleSoundInterval; _combatIdleSoundChance = ((BaseAI)_ai).m_idleSoundChance; _capturedCombatVoice = true; ((BaseAI)_ai).m_idleSoundChance = 0f; } } private void UpdateCombatVoice() { if (!((Object)(object)_ai == (Object)null) && !((Object)(object)_character == (Object)null)) { CaptureCombatVoice(); if (_capturedCombatVoice) { bool flag = _character.InAttack() || ((BaseAI)_ai).IsAlerted(); ((BaseAI)_ai).m_idleSoundInterval = _combatIdleSoundInterval; ((BaseAI)_ai).m_idleSoundChance = (flag ? _combatIdleSoundChance : 0f); } } } internal static void QueueSpawn(Player player, Vector3 position) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) long owner = player.GetPlayerID(); Pending.RemoveAll((PendingSpawn p) => p.OwnerId == owner || p.ExpiresAt <= Time.time); Pending.Add(new PendingSpawn(owner, position, Time.time + 20f)); } internal void Assign(Player player) { _ownerId = player.GetPlayerID(); if ((Object)(object)_view != (Object)null && _view.GetZDO() != null) { _view.GetZDO().Set("ADARC_RootboundModerOwner", _ownerId); } Configure(player); } internal static bool Recall(long playerId) { bool result = false; RootboundModerOwnership[] array = Active.ToArray(); foreach (RootboundModerOwnership rootboundModerOwnership in array) { if ((Object)(object)rootboundModerOwnership != (Object)null && rootboundModerOwnership.OwnerId() == playerId) { RootboundSummonRecall.Kill(rootboundModerOwnership._character, rootboundModerOwnership._view); result = true; } } Pending.RemoveAll((PendingSpawn p) => p.OwnerId == playerId); return result; } private void Configure(Player owner) { if ((Object)(object)_ai != (Object)null) { _ai.MakeTame(); _ai.SetFollowTarget(((Component)owner).gameObject); _ai.SetDespawnInDay(false); } if ((Object)(object)_character != (Object)null && (Object)(object)_view != (Object)null && _view.GetZDO() != null && _view.IsOwner() && !_view.GetZDO().GetBool("ADARC_RootboundModerConfigured", false)) { _character.SetLevel(1); _character.SetMaxHealth(Mathf.Max(1f, RootboundWitchPlugin.ModerCompanionHealth.Value)); _character.SetHealth(_character.GetMaxHealth()); _view.GetZDO().Set("ADARC_RootboundModerConfigured", true); } } internal bool HoldAtFollowDistance(GameObject target) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)target) || (Object)(object)_character == (Object)null || Vector3.Distance(((Component)this).transform.position, target.transform.position) >= Mathf.Max(3f, RootboundWitchPlugin.CharterAbominationFollowDistance.Value)) { return false; } _character.SetMoveDir(Vector3.zero); _character.SetRun(false); _character.StopMovementXZ(); return true; } private long OwnerId() { if ((Object)(object)_view != (Object)null && _view.GetZDO() != null) { long num = _view.GetZDO().GetLong("ADARC_RootboundModerOwner", 0L); if (num != 0L) { _ownerId = num; } } return _ownerId; } private void TryClaim() { if (OwnerId() != 0L || (Object)(object)_view == (Object)null || _view.GetZDO() == null || !_view.IsOwner()) { return; } Pending.RemoveAll((PendingSpawn p) => p.ExpiresAt <= Time.time); PendingSpawn request = (from p in Pending where Vector3.Distance(p.Position, ((Component)this).transform.position) <= 45f orderby Vector3.Distance(p.Position, ((Component)this).transform.position) select p).FirstOrDefault(); if (request != null) { Pending.Remove(request); Player val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerID() == request.OwnerId)); if ((Object)(object)val != (Object)null) { Assign(val); } } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class RootboundModerDamagePatch { private static void Prefix(HitData hit) { Character val = ((hit != null) ? hit.GetAttacker() : null); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent() != (Object)null) { hit.ApplyModifier(Mathf.Clamp(RootboundWitchPlugin.ModerCompanionDamageMultiplier.Value, 0f, 1f)); } } } internal static class RootboundMushroomStaff { private const string RedPlantPrefab = "RootboundPlantedRedMushroom"; private const string YellowPlantPrefab = "RootboundPlantedLuminousMushroom"; private static readonly FieldRef AttackCharacter = AccessTools.FieldRefAccess("m_character"); private static readonly FieldRef AttackWeapon = AccessTools.FieldRefAccess("m_weapon"); private static readonly FieldRef IsSecondary = AccessTools.FieldRefAccess("m_currentAttackIsSecondary"); private static GameObject _redItem; private static GameObject _yellowItem; private static GameObject _redPlant; private static GameObject _yellowPlant; internal static void Register() { _redItem = Require("Mushroom"); _yellowItem = Require("MushroomYellow"); _redPlant = RegisterPlant("RootboundPlantedRedMushroom", "Pickable_Mushroom", luminous: false); _yellowPlant = RegisterPlant("RootboundPlantedLuminousMushroom", "Pickable_Mushroom_yellow", luminous: true); RegisterStaff(); } internal static bool IsOurAttack(Attack attack) { if (attack != null) { return RootboundState.HasPrefab(AttackWeapon.Invoke(attack), "MycelialCrook"); } return false; } internal static void Use(Attack attack) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_004c: 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) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) Humanoid obj = AttackCharacter.Invoke(attack); Player val = (Player)(object)((obj is Player) ? obj : null); if (RootboundSummonRecall.HasLocalAttackAuthority(val)) { bool flag = IsSecondary.Invoke((Humanoid)(object)val); Vector3 eyePoint = ((Character)val).GetEyePoint(); Vector3 lookDir = ((Character)val).GetLookDir(); Vector3 origin = eyePoint + ((Vector3)(ref lookDir)).normalized * 0.75f; Vector3 target = FindTarget(val); GameObject obj2 = BuildFlightVisual(flag ? _yellowItem : _redItem, origin); obj2.AddComponent().Configure(flag ? _yellowPlant : _redPlant, target); obj2.SetActive(true); } } private static void RegisterStaff() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) string text = (Object.op_Implicit((Object)(object)RootboundContent.FindPrefab("BMP_SurtlingStaff")) ? "BMP_SurtlingStaff" : "StaffFireball"); GameObject obj = Require(text); SharedData shared = obj.GetComponent().m_itemData.m_shared; if (shared.m_attack == null) { throw new InvalidOperationException("Mycelial Crook has no live projectile-cast architecture."); } ReclaimedStaffVisual.SourceVisualSnapshot sourceVisualSnapshot = ReclaimedStaffVisual.CaptureSource(obj); CustomItem val = new CustomItem("MycelialCrook", text); SharedData shared2 = val.ItemDrop.m_itemData.m_shared; shared2.m_name = "$item_mycelial_crook"; shared2.m_description = "$item_mycelial_crook_desc"; shared2.m_maxQuality = 1; shared2.m_skillType = (SkillType)9; shared2.m_attack = shared.m_attack.Clone(); shared2.m_secondaryAttack = shared.m_attack.Clone(); ConfigurePlantAttack(shared2.m_attack, 2f); ConfigurePlantAttack(shared2.m_secondaryAttack, 5f); shared2.m_damages = default(DamageTypes); shared2.m_damagesPerLevel = default(DamageTypes); shared2.m_attackForce = 0f; ReclaimedStaffVisual.Apply(val.ItemPrefab); ReclaimedStaffVisual.RemoveGeneratedOvergrowth(val.ItemPrefab); MushroomStaffVisual.Apply(val.ItemPrefab, _yellowItem); sourceVisualSnapshot.Restore("Mycelial Crook"); ItemManager.Instance.AddItem(val); AddRecipe(val.ItemDrop); RootboundWitchPlugin.Log.LogInfo((object)"Mycelial Crook registered: red pickable on primary, room-bright luminous yellow pickable on secondary."); } private static void ConfigurePlantAttack(Attack attack, float eitr) { attack.m_attackEitr = eitr; attack.m_attackEitrAdd = 0f; attack.m_attackHealth = 0f; attack.m_attackHealthPercentage = 0f; attack.m_attackHealthLowBlockUse = false; attack.m_attackHealthReturnHit = 0f; attack.m_projectiles = 1; attack.m_projectileBursts = 1; attack.m_damageMultiplier = 0f; attack.m_forceMultiplier = 0f; } private static GameObject RegisterPlant(string cloneName, string sourceName, bool luminous) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown GameObject val = RootboundContent.FindPrefab(sourceName); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Live pickable mushroom prefab is missing: " + sourceName); } GameObject val2 = PrefabManager.Instance.CreateClonedPrefab(cloneName, val); ZNetView component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_persistent = true; } if (luminous) { MakeLuminous(val2); } PrefabManager.Instance.AddPrefab(new CustomPrefab(val2, true)); return val2; } private static void MakeLuminous(GameObject plant) { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0169: 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_007e: Expected O, but got Unknown //IL_0093: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(1f, 0.76f, 0.16f, 1f); Renderer[] componentsInChildren = plant.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { Material[] sharedMaterials = val2.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int j = 0; j < sharedMaterials.Length; j++) { if (Object.op_Implicit((Object)(object)sharedMaterials[j])) { Material val3 = new Material(sharedMaterials[j]) { name = ((Object)sharedMaterials[j]).name + "_RootboundLuminous" }; if (val3.HasProperty("_Color")) { val3.SetColor("_Color", val); } if (val3.HasProperty("_BaseColor")) { val3.SetColor("_BaseColor", val); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", val * 2.4f); val3.EnableKeyword("_EMISSION"); } array[j] = val3; } } val2.sharedMaterials = array; } GameObject val4 = new GameObject("RootboundLuminousMushroomLight"); val4.transform.SetParent(plant.transform, false); val4.transform.localPosition = Vector3.up * 0.35f; Light obj = val4.AddComponent(); obj.type = (LightType)2; obj.color = new Color(1f, 0.7f, 0.18f, 1f); obj.range = Mathf.Max(5f, RootboundWitchPlugin.LuminousMushroomRange.Value); obj.intensity = Mathf.Max(0.5f, RootboundWitchPlugin.LuminousMushroomIntensity.Value); obj.shadows = (LightShadows)2; obj.renderMode = (LightRenderMode)0; plant.AddComponent(); } private static Vector3 FindTarget(Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_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) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_009f: 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_008a: 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_009e: Unknown result type (might be due to invalid IL or missing references) Vector3 eyePoint = ((Character)player).GetEyePoint(); Vector3 lookDir = ((Character)player).GetLookDir(); Vector3 normalized = ((Vector3)(ref lookDir)).normalized; RaycastHit val = default(RaycastHit); if (Physics.Raycast(eyePoint, normalized, ref val, 4096f, -1, (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val)).point + ((RaycastHit)(ref val)).normal * 0.03f; } Vector3 val2 = eyePoint + normalized * 512f; RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val2 + Vector3.up * 2f, Vector3.down, ref val3, 180f, -1, (QueryTriggerInteraction)1)) { val2 = ((RaycastHit)(ref val3)).point + Vector3.up * 0.03f; } return val2; } private static GameObject BuildFlightVisual(GameObject itemPrefab, Vector3 origin) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0011: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("RootboundThrownMushroom"); val.transform.position = origin; Renderer val2 = ((IEnumerable)itemPrefab.GetComponentsInChildren(true)).FirstOrDefault((Func)((Renderer r) => r.enabled)); if ((Object)(object)val2 != (Object)null) { GameObject val3 = Object.Instantiate(((Component)val2).gameObject); ((Object)val3).name = "MushroomProjectileGraphic"; MonoBehaviour[] componentsInChildren = val3.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren.Length; num++) { Object.Destroy((Object)(object)componentsInChildren[num]); } Collider[] componentsInChildren2 = val3.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren2.Length; num++) { Object.Destroy((Object)(object)componentsInChildren2[num]); } Rigidbody[] componentsInChildren3 = val3.GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren3.Length; num++) { Object.Destroy((Object)(object)componentsInChildren3[num]); } val3.transform.SetParent(val.transform, false); val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.identity; val3.transform.localScale = Vector3.one * 0.75f; val3.SetActive(true); } return val; } private static void AddRecipe(ItemDrop result) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown Recipe val = ScriptableObject.CreateInstance(); ((Object)val).name = "Recipe_MycelialCrook"; val.m_item = result; val.m_amount = 1; val.m_enabled = true; val.m_minStationLevel = 1; GameObject val2 = RootboundContent.FindPrefab("piece_workbench"); val.m_craftingStation = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); val.m_repairStation = val.m_craftingStation; val.m_resources = (Requirement[])(object)new Requirement[4] { Requirement("RootboundCrook", 1), Requirement("Mushroom", 10), Requirement("MushroomYellow", 10), Requirement("Sap", 10) }; if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val, false, false))) { throw new InvalidOperationException("Jotunn rejected Recipe_MycelialCrook"); } } private static Requirement Requirement(string name, int amount) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown GameObject val = RootboundContent.FindPrefab(name); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("Mycelial Crook recipe material is missing: " + name); } return new Requirement { m_resItem = val2, m_amount = amount, m_recover = true }; } private static GameObject Require(string name) { GameObject obj = RootboundContent.FindPrefab(name); if (!Object.op_Implicit((Object)(object)obj)) { throw new InvalidOperationException("Required mushroom-staff prefab is missing: " + name); } return obj; } } internal sealed class RootboundMushroomFlight : MonoBehaviour { private GameObject _plant; private Vector3 _start; private Vector3 _target; private float _started; internal void Configure(GameObject plant, Vector3 target) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) _plant = plant; _target = target; _start = ((Component)this).transform.position; _started = Time.time; } private void Update() { //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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00d0: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01((Time.time - _started) / 0.65f); ((Component)this).transform.position = Vector3.Lerp(_start, _target, num) + Vector3.up * (Mathf.Sin(num * (float)Math.PI) * 2.2f); ((Component)this).transform.Rotate(220f * Time.deltaTime, 145f * Time.deltaTime, 90f * Time.deltaTime, (Space)1); if (num < 1f) { return; } if (Object.op_Implicit((Object)(object)_plant)) { Quaternion val = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f); if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.SpawnObject(_target, val, _plant); } else { Object.Instantiate(_plant, _target, val).SetActive(true); } } Object.Destroy((Object)(object)((Component)this).gameObject); } } internal static class MushroomStaffVisual { internal static void Apply(GameObject staff, GameObject yellowMushroom) { //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) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) FrostedStaffVisual.RemoveDeadCoreOnly(staff, "Mycelial Crook"); Light[] componentsInChildren = staff.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } ParticleSystem[] componentsInChildren2 = staff.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { EmissionModule emission = componentsInChildren2[i].emission; ((EmissionModule)(ref emission)).enabled = false; } Transform val = ReclaimedStaffVisual.CreateGrowthAxis(ReclaimedStaffVisual.FindEquippedVisualRoot(staff.transform)); ((Object)val).name = "MycelialCrook_CrownAxis"; Renderer val2 = ((IEnumerable)yellowMushroom.GetComponentsInChildren(true)).FirstOrDefault((Func)((Renderer r) => r.enabled)); if ((Object)(object)val2 == (Object)null) { return; } GameObject val3 = Object.Instantiate(((Component)val2).gameObject); ((Object)val3).name = "MycelialCrook_LuminousYellowCrown"; MonoBehaviour[] componentsInChildren3 = val3.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } Collider[] componentsInChildren4 = val3.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } val3.transform.SetParent(val, false); val3.transform.localPosition = new Vector3(0f, 1.11f, 0f); val3.transform.localRotation = Quaternion.identity; val3.transform.localScale = Vector3.one; val3.SetActive(true); NormalizeAndCenterCrown(val3, val.TransformPoint(new Vector3(0f, 1.11f, 0f)), 0.42f); Color val4 = default(Color); ((Color)(ref val4))..ctor(1f, 0.76f, 0.16f, 1f); Renderer[] componentsInChildren5 = val3.GetComponentsInChildren(true); foreach (Renderer val5 in componentsInChildren5) { Material[] sharedMaterials = val5.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int num = 0; num < sharedMaterials.Length; num++) { if (Object.op_Implicit((Object)(object)sharedMaterials[num])) { Material val6 = new Material(sharedMaterials[num]) { name = ((Object)sharedMaterials[num]).name + "_MycelialCrown" }; if (val6.HasProperty("_EmissionColor")) { val6.SetColor("_EmissionColor", val4 * 1.8f); val6.EnableKeyword("_EMISSION"); } array[num] = val6; } } val5.sharedMaterials = array; } RootboundWitchPlugin.Log.LogInfo((object)"Mycelial Crook removed its dead core and aligned a 0.42 metre emissive mushroom crown without a carried point light."); } private static void NormalizeAndCenterCrown(GameObject crown, Vector3 desiredCenter, float desiredSize) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_014c: 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) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) Renderer[] array = (from renderer in crown.GetComponentsInChildren(true) where renderer.enabled select renderer).ToArray(); if (array.Length == 0) { return; } Bounds bounds = array[0].bounds; for (int num = 1; num < array.Length; num++) { ((Bounds)(ref bounds)).Encapsulate(array[num].bounds); } float num2 = Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z)); if (num2 > 0.001f) { Transform transform = crown.transform; transform.localScale *= desiredSize / num2; } bounds = crown.GetComponentsInChildren(true).First((Renderer renderer) => renderer.enabled).bounds; foreach (Renderer item in (from renderer in crown.GetComponentsInChildren(true) where renderer.enabled select renderer).Skip(1)) { ((Bounds)(ref bounds)).Encapsulate(item.bounds); } Transform transform2 = crown.transform; transform2.position += desiredCenter - ((Bounds)(ref bounds)).center; } } internal sealed class RootboundLuminousMushroomLifetime : MonoBehaviour { private const float LightSeconds = 30f; private Pickable _pickable; private Light[] _lights; private float _expiresAt; private bool _extinguished; private void OnEnable() { _pickable = ((Component)this).GetComponent(); _lights = ((Component)this).GetComponentsInChildren(true); _expiresAt = Time.time + 30f; _extinguished = false; } private void Update() { if (_extinguished || (Time.time < _expiresAt && ((Object)(object)_pickable == (Object)null || !_pickable.GetPicked()))) { return; } Light[] array = _lights ?? Array.Empty(); foreach (Light val in array) { if (Object.op_Implicit((Object)(object)val)) { ((Behaviour)val).enabled = false; } } _extinguished = true; } } internal static class RootboundNetworkState { private const string KinshipName = "SE_RootboundKinship"; private const string DvergerMarkName = "SE_RootboundDvergerMarked"; private static StatusEffect _dvergerMark; private static float _nextUpdate; internal static void Register(Sprite icon) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown SE_Stats val = ScriptableObject.CreateInstance(); ((Object)val).name = "SE_RootboundDvergerMarked"; ((StatusEffect)val).m_name = "$se_rootbound_dverger_mark"; ((StatusEffect)val).m_tooltip = "$se_rootbound_dverger_mark_tooltip"; ((StatusEffect)val).m_icon = icon; ((StatusEffect)val).m_hidden = true; ((StatusEffect)val).m_effectsOnlyOnPlayer = true; ((StatusEffect)val).m_ttl = 2.5f; ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val, false)); _dvergerMark = (StatusEffect)(object)val; } internal static void UpdateLocal(Player player) { if (Time.time < _nextUpdate) { return; } _nextUpdate = Time.time + 0.75f; if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead() && !((Object)(object)_dvergerMark == (Object)null)) { if ((RootboundState.IsFullSet(player) && RootboundState.MinimumQuality(player) >= 2) || RootboundState.HasMatureCrookEquipped(player)) { ((Character)player).GetSEMan().AddStatusEffect(_dvergerMark, true, 0, 0f, (short)(-1)); } else { ((Character)player).GetSEMan().RemoveStatusEffect(_dvergerMark.NameHash(), true); } } } internal static bool HasKinship(Player player) { if ((Object)(object)player != (Object)null) { if (!RootboundState.IsFullSet(player)) { return HasNamedEffect(player, "SE_RootboundKinship"); } return true; } return false; } internal static bool HasDvergerMark(Player player) { if ((Object)(object)player != (Object)null) { return HasNamedEffect(player, "SE_RootboundDvergerMarked"); } return false; } private static bool HasNamedEffect(Player player, string effectName) { List statusEffects = ((Character)player).GetSEMan().GetStatusEffects(); for (int i = 0; i < statusEffects.Count; i++) { StatusEffect val = statusEffects[i]; if ((Object)(object)val != (Object)null && ((Object)val).name == effectName) { return true; } } return false; } } [HarmonyPatch] internal static class RootboundStaffTooltips { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[6] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int), typeof(bool) }, (Type[])null); } private static void Postfix(ItemData item, int qualityLevel, float worldLevel, ref string __result) { //IL_0032: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) if (item == null || item.m_shared == null) { return; } bool num = RootboundState.HasPrefab(item, "RootboundCrook"); bool flag = RootboundState.HasPrefab(item, "FrostedRoot"); if (num || flag) { DamageTypes damage = item.GetDamage(Math.Max(1, qualityLevel), worldLevel); StringBuilder stringBuilder = new StringBuilder(__result ?? string.Empty); stringBuilder.Append("\n\nRootbound attack ledger"); if (flag) { stringBuilder.Append("\nPrimary: 6 Moder shards; each ").Append(DescribeDamage(damage)); stringBuilder.Append("\nSecondary: freezing root field; ").Append(Format(damage.m_frost)).Append(" frost, ") .Append(Format(RootboundWitchPlugin.CrookSecondaryRadius.Value)) .Append(" m radius, ") .Append(Format(RootboundWitchPlugin.CrookSecondaryEnsnareSeconds.Value)) .Append(" s immobilize"); } else { float value = Math.Max(0f, damage.m_poison) * Math.Max(0f, RootboundWitchPlugin.CrookSecondaryPoisonMultiplier.Value); stringBuilder.Append("\nPrimary: 3 root projectiles; each ").Append(DescribeDamage(damage)); stringBuilder.Append("\nSecondary: poison root field; ").Append(Format(value)).Append(" poison, ") .Append(Format(RootboundWitchPlugin.CrookSecondaryRadius.Value)) .Append(" m radius, ") .Append(Format(RootboundWitchPlugin.CrookSecondaryEnsnareSeconds.Value)) .Append(" s immobilize"); } __result = stringBuilder.ToString(); } } private static string DescribeDamage(DamageTypes damage) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0083: 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) StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "raw", damage.m_damage); Append(stringBuilder, "blunt", damage.m_blunt); Append(stringBuilder, "slash", damage.m_slash); Append(stringBuilder, "pierce", damage.m_pierce); Append(stringBuilder, "fire", damage.m_fire); Append(stringBuilder, "frost", damage.m_frost); Append(stringBuilder, "lightning", damage.m_lightning); Append(stringBuilder, "poison", damage.m_poison); Append(stringBuilder, "spirit", damage.m_spirit); if (stringBuilder.Length <= 0) { return "0 damage"; } return stringBuilder.ToString(); } private static void Append(StringBuilder result, string name, float value) { if (!(value <= 0.001f)) { if (result.Length > 0) { result.Append(" + "); } result.Append(Format(value)).Append(' ').Append(name); } } private static string Format(float value) { return Math.Max(0f, value).ToString("0.#"); } } internal static class RootboundSummonRecall { private static readonly MethodInfo CheckDeath = AccessTools.Method(typeof(Character), "CheckDeath", (Type[])null, (Type[])null); internal static Attack BuildAxeStrikeAttack() { string[] array = new string[6] { "AxeBlackMetal", "AxeIron", "AxeBronze", "AxeFlint", "AxeStone", "AxeJotunBane" }; foreach (string text in array) { GameObject val = RootboundContent.FindPrefab(text); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); Attack val3 = (((Object)(object)val2 != (Object)null) ? val2.m_itemData.m_shared.m_secondaryAttack : null); if (val3 != null) { Attack obj = val3.Clone(); obj.m_attackStamina = 0f; obj.m_attackEitr = 0f; obj.m_attackEitrAdd = 0f; obj.m_attackHealth = 0f; obj.m_attackHealthPercentage = 0f; obj.m_attackHealthLowBlockUse = false; obj.m_attackHealthReturnHit = 0f; obj.m_damageMultiplier = 0f; obj.m_damageMultiplierPerMissingHP = 0f; obj.m_damageMultiplierByTotalHealthMissing = 0f; obj.m_forceMultiplier = 0f; obj.m_selfDamage = 0; RootboundWitchPlugin.Log.LogInfo((object)("Summon recall now uses the live " + text + " downward secondary-strike contract.")); return obj; } } throw new InvalidOperationException("No live one-handed axe secondary attack was available for summon recall."); } internal static bool HasLocalAttackAuthority(Player player) { if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return false; } ZNetView component = ((Component)player).GetComponent(); if (!((Object)(object)component == (Object)null) && component.GetZDO() != null) { return component.IsOwner(); } return true; } internal static void Kill(Character character, ZNetView view) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)character) && !character.IsDead()) { if ((Object)(object)view != (Object)null && view.GetZDO() != null && !view.IsOwner()) { view.ClaimOwnership(); } character.SetHealth(0f); if (CheckDeath != null) { CheckDeath.Invoke(character, null); } if (!character.IsDead()) { HitData val = new HitData(); val.m_damage.m_damage = Mathf.Min(90000f, Mathf.Max(10000f, character.GetMaxHealth() * 8f)); val.m_point = character.GetCenterPoint(); val.m_dir = Vector3.down; character.Damage(val); } } } } [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] internal static class RootboundSummonRecallAxeStrikePatch { private static bool Prefix(Attack __instance) { if (RootboundCharterAbomination.IsOurAttack(__instance)) { RootboundCharterAbomination.Use(__instance); return false; } if (RootboundKvasturScroll.IsOurAttack(__instance)) { RootboundKvasturScroll.Use(__instance); return false; } if (RootboundModerCompanion.IsOurAttack(__instance)) { RootboundModerCompanion.Use(__instance); return false; } return true; } } internal static class RootboundWisp { private static readonly FieldRef UtilityItem = AccessTools.FieldRefAccess("m_utilityItem"); internal static void Register() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) GameObject val = RootboundContent.FindPrefab("Demister"); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("The live Wisplight prefab 'Demister' is missing."); } CustomItem val3 = new CustomItem("RootboundWisp", ((Object)val).name); SharedData shared = val3.ItemDrop.m_itemData.m_shared; SharedData shared2 = val2.m_itemData.m_shared; shared.m_name = "$item_rootbound_wisp"; shared.m_description = "$item_rootbound_wisp_desc"; shared.m_itemType = (ItemType)18; shared.m_maxQuality = 1; shared.m_maxStackSize = 1; shared.m_equipStatusEffect = shared2.m_equipStatusEffect; shared.m_icons = shared2.m_icons; ItemManager.Instance.AddItem(val3); AddRecipe(val3.ItemDrop, val2); RootboundWitchPlugin.Log.LogInfo((object)"Rootbound Wisp cloned from the live Wisplight: mist-clearing preserved, +150 carry weight supplied independently."); } internal static bool IsEquipped(Player player) { if ((Object)(object)player != (Object)null) { return RootboundState.HasPrefab(UtilityItem.Invoke((Humanoid)(object)player), "RootboundWisp"); } return false; } private static void AddRecipe(ItemDrop result, ItemDrop wisplight) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //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_00be: 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_00cd: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown Recipe val = ScriptableObject.CreateInstance(); ((Object)val).name = "Recipe_RootboundWisp"; val.m_item = result; val.m_amount = 1; val.m_enabled = true; val.m_minStationLevel = 1; GameObject val2 = RootboundContent.FindPrefab("piece_workbench"); val.m_craftingStation = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); val.m_repairStation = val.m_craftingStation; GameObject val3 = RootboundContent.FindPrefab("Root"); ItemDrop val4 = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent() : null); if ((Object)(object)val4 == (Object)null) { throw new InvalidOperationException("Rootbound Wisp material is absent: Root."); } val.m_resources = (Requirement[])(object)new Requirement[2] { new Requirement { m_resItem = wisplight, m_amount = 1, m_recover = true }, new Requirement { m_resItem = val4, m_amount = 3, m_recover = true } }; if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val, false, false))) { throw new InvalidOperationException("Jotunn rejected Recipe_RootboundWisp"); } } } [HarmonyPatch(typeof(Player), "GetMaxCarryWeight")] internal static class RootboundWispCarryPatch { private static void Postfix(Player __instance, ref float __result) { if (RootboundWitchPlugin.EnableRootboundWisp.Value && RootboundWisp.IsEquipped(__instance)) { __result += Mathf.Max(0f, RootboundWitchPlugin.RootboundWispCarryWeight.Value); } } } [BepInPlugin("adarc.valheim.rootboundwitch", "Rootbound Witch", "0.4.11")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class RootboundWitchPlugin : BaseUnityPlugin { public const string PluginGuid = "adarc.valheim.rootboundwitch"; public const string PluginName = "Rootbound Witch"; public const string PluginVersion = "0.4.11"; internal static ManualLogSource Log; internal static RootboundWitchPlugin Instance; internal static ConfigEntry EnableArmour; internal static ConfigEntry EnablePetrifiedTools; internal static ConfigEntry EnableStaff; internal static ConfigEntry EnableFoods; internal static ConfigEntry EnableKvasturScroll; internal static ConfigEntry EnableGaldrCharter; internal static ConfigEntry EnableCharm; internal static ConfigEntry EnableRootboundWisp; internal static ConfigEntry EnableModerCompanion; internal static ConfigEntry EnableMushroomStaff; internal static ConfigEntry EnableBogWitchBackGrowth; internal static ConfigEntry EnableAnimalKillPenalty; internal static ConfigEntry EnableSharedStaminaAura; internal static ConfigEntry EnableRestrictions; internal static ConfigEntry EnableRooting; internal static ConfigEntry EnableTreeBlessing; internal static ConfigEntry EnableStoneWither; internal static ConfigEntry EnablePermafrostTint; internal static ConfigEntry FireDamageMultiplier; internal static ConfigEntry PermafrostFireDamageMultiplier; internal static ConfigEntry TreeRadius; internal static ConfigEntry TreeHealPerSecond; internal static ConfigEntry RootDelay; internal static ConfigEntry RootDuration; internal static ConfigEntry RootCooldown; internal static ConfigEntry RootHealPerSecond; internal static ConfigEntry StoneWitherPerSecond; internal static ConfigEntry BiomeStaminaMultiplier; internal static ConfigEntry CrookSecondaryRadius; internal static ConfigEntry CrookSecondaryEnsnareSeconds; internal static ConfigEntry CrookSecondaryPoisonMultiplier; internal static ConfigEntry KvasturScrollPrice; internal static ConfigEntry GaldrCharterPrice; internal static ConfigEntry CharterAbominationSummonEitr; internal static ConfigEntry CharterAbominationBaseHealth; internal static ConfigEntry CharterAbominationLevel; internal static ConfigEntry CharterAbominationRegenPerSecond; internal static ConfigEntry CharterAbominationFollowDistance; internal static ConfigEntry CharmElementalMagic; internal static ConfigEntry CharmBloodMagic; internal static ConfigEntry CharmStaticEitr; internal static ConfigEntry CharmPowerCooldownSeconds; internal static ConfigEntry RootboundWispCarryWeight; internal static ConfigEntry ModerCompanionSummonEitr; internal static ConfigEntry ModerCompanionHealth; internal static ConfigEntry ModerCompanionDamageMultiplier; internal static ConfigEntry LuminousMushroomRange; internal static ConfigEntry LuminousMushroomIntensity; internal static ConfigEntry BogWitchGrowthWidth; internal static ConfigEntry BogWitchGrowthHeight; internal static ConfigEntry BogWitchGrowthVerticalOffset; internal static ConfigEntry BogWitchGrowthBackOffset; internal static ConfigEntry AnimalKillSkillPenalty; internal static ConfigEntry SharedStaminaRadius; internal static ConfigEntry SharedStaminaMultiplier; internal static ConfigEntry SharedStaminaWearerSpeedMultiplier; internal static ConfigEntry PetrifiedToolTier; internal static ConfigEntry StaffVisualCandidates; internal static ConfigEntry MetalIngredientPrefabs; internal static ConfigEntry AnimalFoodTokens; private Harmony _harmony; private void Awake() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; BindConfiguration(); RootboundBackpackIntegration.InstallAndReload(); PrefabManager.OnVanillaPrefabsAvailable += RootboundContent.Register; _harmony = new Harmony("adarc.valheim.rootboundwitch"); _harmony.PatchAll(typeof(RootboundWitchPlugin).Assembly); ((Component)this).gameObject.AddComponent(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Rootbound Witch 0.4.11 awake; waiting for Jotunn's vanilla-prefab gate."); } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= RootboundContent.Register; PermafrostVisuals.Clear(); BogWitchBackGrowth.Clear(); if (_harmony != null) { _harmony.UnpatchSelf(); } } private void BindConfiguration() { EnableArmour = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Rootbound armour", true, "Register the separate Rootbound Mask, Harness and Leggings."); EnablePetrifiedTools = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable petrified harvesting tools", true, "Register the non-metal Petrified Root Pick and Petrified Root Axe for solo biome progression."); EnableStaff = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Rootbound Crook", true, "Register the dead Surtling-staff Rootbound Crook and its Deep North sister weapon, Frosted Root."); EnableFoods = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable forest eitr foods", true, "Register Mossbread and Bilberry Mash."); EnableKvasturScroll = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Kvastur summon scroll", true, "Let the Bog Witch sell a one-companion Kvastur summon/recall scroll while the complete Rootbound set is worn."); EnableGaldrCharter = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Rootbound Galdr Charter", true, "After the Kvastur scroll is purchased, let the Bog Witch sell a persistent unlock for hand-crafting the highest-tier Galdr-table recipes."); EnableCharm = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Rootbound charm", true, "Register the Jormundling-derived Rootbound charm with magic skills, static eitr, feather fall and a shorter Forsaken-power recovery."); EnableRootboundWisp = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Rootbound Wisp", true, "Register a Wisplight that retains its ordinary mist-clearing effect and adds carry capacity beside the Trinket-slot Rootbound charm."); EnableModerCompanion = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Rootbound Moder companion", true, "Add the Galdr-Charter-only Rootbound Moder Sigil and its owner-bound weaker Moder companion."); EnableMushroomStaff = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Mycelial Crook", true, "Register the yellow-mushroom-crowned staff that plants red and luminous yellow mushrooms."); EnableBogWitchBackGrowth = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable Bog Witch back growth", true, "Transplant only the Bog Witch's branch geometry onto a complete Rootbound wearer; no NPC rig or behaviour is copied."); EnableAnimalKillPenalty = ((BaseUnityPlugin)this).Config.Bind("02 - Transformation", "Animal kills cost mobility skill", true, "While the complete Rootbound kinship set is active, personally killing a creature whose live drop table contains meat reduces Running and Jumping."); EnableSharedStaminaAura = ((BaseUnityPlugin)this).Config.Bind("01 - Content", "Enable shared stamina aura", true, "A complete Rootbound set doubles nearby allies' stamina regeneration while surrendering some of the wearer's movement speed."); EnableRestrictions = ((BaseUnityPlugin)this).Config.Bind("02 - Transformation", "Enable restrictions", true, "When the full Rootbound set is worn: reject metal equipment, reject animal food and amplify fire."); EnableRooting = ((BaseUnityPlugin)this).Config.Bind("02 - Transformation", "Root when motionless", true, "Standing still on solid ground eventually roots the wearer in place and regenerates health."); EnableTreeBlessing = ((BaseUnityPlugin)this).Config.Bind("02 - Transformation", "Living tree blessing", true, "Regenerate near living trees; quality four instead regenerates in the Deep North."); EnableStoneWither = ((BaseUnityPlugin)this).Config.Bind("02 - Transformation", "Worked stone withers", true, "Standing on worked stone or black marble damages a full-set wearer."); EnablePermafrostTint = ((BaseUnityPlugin)this).Config.Bind("02 - Transformation", "Quality four permafrost tint", true, "Apply a pale, cold material tint to the locally equipped Rootbound visuals at quality four."); FireDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Fire multiplier", 1.5f, "Fire damage multiplier while Rootbound below quality four."); PermafrostFireDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Permafrost fire multiplier", 2f, "Fire damage multiplier while the complete set is quality four."); TreeRadius = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Living tree radius", 12f, "Metres searched for a living TreeBase."); TreeHealPerSecond = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Tree healing per second", 1.25f, "Passive health restored each second by the correct environment."); RootDelay = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Root delay", 4f, "Seconds motionless before taking root."); RootDuration = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Root duration", 2.75f, "Minimum seconds before movement input can uproot the wearer. Remaining still preserves the hold without flickering or rearming it."); RootCooldown = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Root cooldown", 10f, "Seconds after uprooting before another hold can begin."); RootHealPerSecond = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Root healing per second", 7f, "Health restored per second during a rooted hold."); StoneWitherPerSecond = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Stone wither per second", 2f, "Unarmoured health removed per second while standing on worked stone."); BiomeStaminaMultiplier = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Home biome stamina multiplier", 1.2f, "Stamina regeneration multiplier in Black Forest and Mistlands."); CrookSecondaryRadius = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Crook secondary radius", 7f, "Radius in metres of the right-bumper root field."); CrookSecondaryEnsnareSeconds = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Crook secondary ensnare seconds", 3.5f, "How long hostile creatures caught by the root field are held motionless."); CrookSecondaryPoisonMultiplier = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Crook secondary poison multiplier", 1f, "Multiplier applied to the Crook's normal poison value in its area attack. No blunt damage is copied."); KvasturScrollPrice = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Kvastur scroll price", 350, "Coins charged by the Bog Witch for the Rootbound Kvastur scroll."); GaldrCharterPrice = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Galdr Charter price", 750, "Coins charged by the Bog Witch for the Rootbound Galdr Charter after Kvastur recognition."); CharterAbominationSummonEitr = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charter Abomination summon eitr", 85f, "Eitr paid when the Galdr Charter calls its strengthened Abomination. Recall is free."); CharterAbominationBaseHealth = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charter Abomination base health", 1600f, "Base health before the companion's configured creature level multiplier. 1600 at level three yields 4800 maximum health."); CharterAbominationLevel = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charter Abomination level", 3, "Creature level of the summoned Abomination. Three is the vanilla two-star combat tier."); CharterAbominationRegenPerSecond = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charter Abomination regeneration per second", 20f, "Health restored each second to the owner-authoritative summoned Abomination."); CharterAbominationFollowDistance = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charter Abomination follow distance", 15f, "Minimum distance in metres the Abomination keeps while following its owner outside combat."); CharmElementalMagic = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charm elemental magic", 40f, "Elemental Magic skill levels supplied while the Rootbound charm is equipped."); CharmBloodMagic = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charm blood magic", 40f, "Blood Magic skill levels supplied while the Rootbound charm is equipped."); CharmStaticEitr = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charm static eitr", 40f, "Maximum eitr supplied while the Rootbound charm is equipped."); CharmPowerCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Charm Forsaken power cooldown", 420f, "Forsaken-power cooldown applied on activation while the charm is equipped. 420 seconds is seven minutes; power duration is unchanged."); RootboundWispCarryWeight = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Rootbound Wisp carry weight", 150f, "Maximum carry weight added while the Rootbound Wisp is equipped."); ModerCompanionSummonEitr = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Rootbound Moder summon eitr", 140f, "Eitr paid when the Galdr Charter's special sigil calls its weaker Moder companion. Recall is free."); ModerCompanionHealth = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Rootbound Moder health", 1800f, "Maximum health of the non-boss Rootbound Moder companion."); ModerCompanionDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Rootbound Moder damage multiplier", 0.45f, "Fraction of live Moder attack damage retained by the companion."); LuminousMushroomRange = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Luminous mushroom light range", 22f, "Metres illuminated by each planted yellow mushroom."); LuminousMushroomIntensity = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Luminous mushroom light intensity", 3.2f, "Point-light intensity of each planted yellow mushroom."); BogWitchGrowthWidth = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Bog Witch growth width", 2.65f, "Target width in metres of the extracted Bog Witch branch crown."); BogWitchGrowthHeight = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Bog Witch growth height", 2.35f, "Target height in metres of the extracted Bog Witch branch crown."); BogWitchGrowthVerticalOffset = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Bog Witch growth vertical offset", 1.35f, "Height in player-local metres of the extracted branch crown's centre."); BogWitchGrowthBackOffset = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Bog Witch growth back offset", -0.24f, "Forward/back player-local offset of the branch crown's centre; negative values move it behind the wearer."); AnimalKillSkillPenalty = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Animal kill skill penalty", 5f, "Running and Jumping levels removed when the full-set wearer personally kills a meat-bearing creature."); SharedStaminaRadius = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Shared stamina radius", 50f, "Radius in metres in which other players receive the Rootbound wearer's stamina gift."); SharedStaminaMultiplier = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Shared stamina multiplier", 2f, "Stamina regeneration multiplier granted to other players inside the aura. The wearer is excluded."); SharedStaminaWearerSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Aura wearer speed multiplier", 0.85f, "Movement-speed multiplier applied to the Rootbound wearer while one or more other players receive the aura. This never stacks per recipient."); PetrifiedToolTier = ((BaseUnityPlugin)this).Config.Bind("03 - Balance", "Petrified tool harvesting tier", 100, "Harvesting clearance of both petrified tools. The deliberately high default remains compatible with later-biome and modded wood or stone while damage still scales normally by quality."); StaffVisualCandidates = ((BaseUnityPlugin)this).Config.Bind("04 - Compatibility", "Staff visual prefabs", "BMP_SurtlingStaff,StaffFireball", "First available prefab supplies the Crook's body. MagicPlugin's Surtling Staff is preferred; vanilla Staff of Embers is the fallback."); MetalIngredientPrefabs = ((BaseUnityPlugin)this).Config.Bind("04 - Compatibility", "Metal ingredient prefabs", "Copper,Tin,Bronze,Iron,Silver,BlackMetal,FlametalNew", "Items whose crafting recipes consume any of these are considered metal equipment."); AnimalFoodTokens = ((BaseUnityPlugin)this).Config.Bind("04 - Compatibility", "Animal food name fragments", "meat,sausage,fish,serpent,wolfjerky,deerstew,loxpie,bloodpudding,misthare,chicken,harepie,seekeraspic", "Case-insensitive prefab-name fragments treated as animal food."); } } internal static class TieredRecipeCosts { private sealed class Cost { internal readonly int ExactQuality; internal readonly int Amount; internal Cost(int exactQuality, int amount) { ExactQuality = exactQuality; Amount = amount; } } private sealed class ReferenceComparer : IEqualityComparer where T : class { internal static readonly ReferenceComparer Instance = new ReferenceComparer(); public bool Equals(T x, T y) { return x == y; } public int GetHashCode(T obj) { return RuntimeHelpers.GetHashCode(obj); } } private static readonly Dictionary Costs = new Dictionary(ReferenceComparer.Instance); internal static void Register(Requirement requirement, int exactQuality, int amount) { Costs[requirement] = new Cost(exactQuality, amount); } internal static bool TryGet(Requirement requirement, int quality, out int amount) { if (Costs.TryGetValue(requirement, out var value)) { amount = ((quality == value.ExactQuality) ? value.Amount : 0); return true; } amount = 0; return false; } } [HarmonyPatch(typeof(Requirement), "GetAmount")] internal static class TieredRequirementGetAmountPatch { private static bool Prefix(Requirement __instance, int qualityLevel, ref int __result) { if (!TieredRecipeCosts.TryGet(__instance, qualityLevel, out var amount)) { return true; } __result = amount; return false; } } }