Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RootboundWitch v1.3.1
plugins/ADARC-RootboundWitch/ADARC.RootboundWitch.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.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("1.3.1.0")] [assembly: AssemblyVersion("1.3.1.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 sealed class GrowthInstance { internal Player Owner; internal GameObject Upper; internal GameObject Lower; internal bool MaterialStateKnown; internal int LastMaterialState; internal bool IsValid { get { if ((Object)(object)Owner != (Object)null && Object.op_Implicit((Object)(object)Upper)) { return Object.op_Implicit((Object)(object)Lower); } return false; } } } 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 readonly Dictionary<Player, GrowthInstance> Instances = new Dictionary<Player, GrowthInstance>(); private static Bounds _combinedBounds; private static Material[] _ordinaryMaterials; private static Material[] _charredMaterials; private static Material[] _permafrostMaterials; private static float _nextResolveAt; private static bool _loggedFailure; 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<CombineInstance> list = new List<CombineInstance>(); List<Material> list2 = new List<Material>(); List<string> list3 = new List<string>(); List<string> list4 = new List<string>(); Matrix4x4 worldToLocalMatrix = val.transform.worldToLocalMatrix; Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(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 : "<no material>")); } } } 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); PullCentralSpineBranchesForward(mesh); LiftDetachedCentralLowerBranch(mesh2); _ordinaryMaterials = list2.ToArray(); _charredMaterials = RootboundAshlandsVisuals.BuildExternalCharredMaterials(_ordinaryMaterials); _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) { ClearInstances(); 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; } } HashSet<Player> currentPlayers = new HashSet<Player>(); foreach (Player item in from candidate in Player.GetAllPlayers() where (Object)(object)candidate != (Object)null select candidate) { currentPlayers.Add(item); int num = ((!((Object)(object)item == (Object)(object)player)) ? RootboundNetworkState.GetVisualState(item) : (active ? RootboundState.GrowthCrownVisualState(item) : 0)); if (num <= 0) { RemoveInstance(item); continue; } if (!Instances.TryGetValue(item, out var value) || !value.IsValid) { RemoveInstance(item); value = new GrowthInstance { Owner = item, Upper = CreateInstance(_upperTemplate, "Rootbound_BogWitchBranchCrownUpper", item), Lower = CreateInstance(_lowerTemplate, "Rootbound_BogWitchBranchCrownLower", item) }; AttachToAnimatedTorso(value.Upper, item, lower: false); AttachToAnimatedTorso(value.Lower, item, lower: true); value.Upper.SetActive(true); value.Lower.SetActive(true); Instances[item] = value; } if (!value.MaterialStateKnown || value.LastMaterialState != num) { Material[] materials = ((num >= 3) ? _permafrostMaterials : ((num == 2) ? _charredMaterials : _ordinaryMaterials)); ApplyMaterials(value.Upper, materials); ApplyMaterials(value.Lower, materials); value.LastMaterialState = num; value.MaterialStateKnown = true; } } Player[] array = Instances.Keys.Where((Player existing) => (Object)(object)existing == (Object)null || !currentPlayers.Contains(existing)).ToArray(); for (int num2 = 0; num2 < array.Length; num2++) { RemoveInstance(array[num2]); } } internal static void Clear() { ClearInstances(); 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; _charredMaterials = null; _permafrostMaterials = null; } private static void ClearInstances() { GrowthInstance[] array = Instances.Values.ToArray(); for (int i = 0; i < array.Length; i++) { DestroyInstance(array[i]); } Instances.Clear(); } private static void RemoveInstance(Player player) { if (player != null && Instances.TryGetValue(player, out var value)) { DestroyInstance(value); Instances.Remove(player); } } private static void DestroyInstance(GrowthInstance instance) { if (instance != null) { if (Object.op_Implicit((Object)(object)instance.Upper)) { Object.Destroy((Object)(object)instance.Upper); } if (Object.op_Implicit((Object)(object)instance.Lower)) { Object.Destroy((Object)(object)instance.Lower); } } } private static GameObject CreateInstance(GameObject template, string name, Player player) { GameObject obj = Object.Instantiate<GameObject>(template, ((Component)player).transform, false); ((Object)obj).name = name; ((Object)obj).hideFlags = (HideFlags)52; PositionOnBack(obj, CurrentStatureFactor(player)); return obj; } private static void PositionOnBack(GameObject crown, float statureFactor) { //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_00c8: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0104: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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) 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; statureFactor = Mathf.Clamp(statureFactor, 0.55f, 1f); crown.transform.localScale = Vector3.one * num3 * statureFactor; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(0f, RootboundWitchPlugin.BogWitchGrowthVerticalOffset.Value, RootboundWitchPlugin.BogWitchGrowthBackOffset.Value); crown.transform.localPosition = (val2 - ((Bounds)(ref val)).center * num3) * statureFactor; } private static void AttachToAnimatedTorso(GameObject crown, Player player, bool lower) { //IL_0076: 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_0092: 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_0042: 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_005e: 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) 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; } if (lower) { Transform transform = crown.transform; transform.position += ((Component)player).transform.forward * (0.11f * CurrentStatureFactor(player)); } else { Transform transform2 = crown.transform; transform2.position += ((Component)player).transform.forward * (0.065f * CurrentStatureFactor(player)); } 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 float CurrentStatureFactor(Player player) { if ((Object)(object)player == (Object)null) { return 1f; } if (!(((Object)(object)player == (Object)(object)Player.m_localPlayer) ? RootboundState.IsFullSet(player) : (RootboundNetworkState.GetSupportTier(player) > 0))) { return 1f; } return Mathf.Clamp(RootboundWitchPlugin.FullSetVisualScale.Value, 0.55f, 1f); } 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<Animator>)((Component)player).GetComponentsInChildren<Animator>(true)).FirstOrDefault((Func<Animator, bool>)((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<Transform>(true); string[] array2 = new string[5] { "pelvis", "hips", "hip", "spine1", "spine" }; foreach (string token in array2) { Transform val3 = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((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<MeshFilter>(); MeshRenderer obj = val.AddComponent<MeshRenderer>(); 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<MeshRenderer>(); 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<int> list = new List<int>(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 void LiftDetachedCentralLowerBranch(Mesh mesh) { //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0158: 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_01a6: 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_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)mesh) || mesh.vertexCount == 0) { return; } Vector3[] vertices = mesh.vertices; int[] array = Enumerable.Repeat(-1, vertices.Length).ToArray(); for (int i = 0; i < mesh.subMeshCount; i++) { int[] triangles = mesh.GetTriangles(i); for (int j = 0; j + 2 < triangles.Length; j += 3) { int num = triangles[j]; int num2 = triangles[j + 1]; int num3 = triangles[j + 2]; Activate(array, num); Activate(array, num2); Activate(array, num3); Union(array, num, num2); Union(array, num2, num3); } } Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>(); for (int k = 0; k < array.Length; k++) { if (array[k] >= 0) { int key = Find(array, k); if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List<int>()); } value.Add(k); } } if (dictionary.Count < 2) { RootboundWitchPlugin.Log.LogWarning((object)"Bog Witch lower crown had no separable central branch; leaving its mesh unchanged."); return; } Bounds val = BoundsFor(vertices, dictionary.Values.SelectMany((List<int> result) => result)); float num4 = Mathf.Max(0.01f, ((Bounds)(ref val)).size.x); float num5 = Mathf.Max(0.01f, ((Bounds)(ref val)).size.y); List<int> list2 = null; Bounds val2 = default(Bounds); float num6 = float.MaxValue; foreach (List<int> value2 in dictionary.Values) { if (value2.Count < 6) { continue; } Bounds val3 = BoundsFor(vertices, value2); float num7 = Mathf.Abs(((Bounds)(ref val3)).center.x - ((Bounds)(ref val)).center.x) / num4; float num8 = (((Bounds)(ref val3)).center.y - ((Bounds)(ref val)).min.y) / num5; float num9 = ((Bounds)(ref val3)).size.y / num5; if (!(num7 > 0.24f) && !(num8 > 0.64f) && !(num9 < 0.12f)) { float num10 = num7 * 2f + num8 - num9 * 0.15f; if (num10 < num6) { num6 = num10; list2 = value2; val2 = val3; } } } if (list2 == null) { RootboundWitchPlugin.Log.LogWarning((object)"Bog Witch lower crown found no safe central dangling component to lift."); return; } float num11 = CrownBaseScale(); float num12 = 0.18f / Mathf.Max(0.01f, num11); foreach (int item in list2) { vertices[item].y += num12; } mesh.vertices = vertices; mesh.RecalculateBounds(); RootboundWitchPlugin.Log.LogInfo((object)("Bog Witch central lower branch lifted by 0.18m at full stature (component center " + ((object)((Bounds)(ref val2)).center/*cast due to .constrained prefix*/).ToString() + ", vertices " + list2.Count + ").")); } private static void PullCentralSpineBranchesForward(Mesh mesh) { //IL_0149: 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_015f: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)mesh) || mesh.vertexCount == 0) { return; } Vector3[] vertices = mesh.vertices; int[] array = Enumerable.Repeat(-1, vertices.Length).ToArray(); for (int i = 0; i < mesh.subMeshCount; i++) { int[] triangles = mesh.GetTriangles(i); for (int j = 0; j + 2 < triangles.Length; j += 3) { int num = triangles[j]; int num2 = triangles[j + 1]; int num3 = triangles[j + 2]; Activate(array, num); Activate(array, num2); Activate(array, num3); Union(array, num, num2); Union(array, num2, num3); } } Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>(); for (int k = 0; k < array.Length; k++) { if (array[k] >= 0) { int key = Find(array, k); if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List<int>()); } value.Add(k); } } if (dictionary.Count < 3) { RootboundWitchPlugin.Log.LogWarning((object)"Bog Witch upper crown exposed fewer than three separable spine branches; retaining its accepted fit."); return; } Bounds usedBounds = BoundsFor(vertices, dictionary.Values.SelectMany((List<int> result) => result)); float width = Mathf.Max(0.01f, ((Bounds)(ref usedBounds)).size.x); float height = Mathf.Max(0.01f, ((Bounds)(ref usedBounds)).size.y); List<List<int>> list2 = (from component in (from component in dictionary.Values where component.Count >= 6 select new { Vertices = component, Bounds = BoundsFor(vertices, component) }).Where(component => { //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_0019: 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_003d: 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_0050: 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_0072: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = component.Bounds; if (Mathf.Abs(((Bounds)(ref bounds)).center.x - ((Bounds)(ref usedBounds)).center.x) / width <= 0.22f) { bounds = component.Bounds; if ((((Bounds)(ref bounds)).min.y - ((Bounds)(ref usedBounds)).min.y) / height <= 0.28f) { bounds = component.Bounds; return ((Bounds)(ref bounds)).size.y / height >= 0.14f; } } return false; }).OrderBy(component => { //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_0019: 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_003f: 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) Bounds bounds = component.Bounds; float num6 = Mathf.Abs(((Bounds)(ref bounds)).center.x - ((Bounds)(ref usedBounds)).center.x) / width * 2f; bounds = component.Bounds; return num6 + (((Bounds)(ref bounds)).min.y - ((Bounds)(ref usedBounds)).min.y) / height; }).Take(3) select component.Vertices).ToList(); if (list2.Count != 3) { RootboundWitchPlugin.Log.LogWarning((object)"Bog Witch upper crown could not safely identify exactly three spine branches; moved none."); return; } float num4 = 0.085f / Mathf.Max(0.01f, CrownBaseScale()); HashSet<int> hashSet = new HashSet<int>(); foreach (List<int> item in list2) { foreach (int item2 in item) { if (hashSet.Add(item2)) { vertices[item2].z += num4; } } } float num5 = 0.13f / Mathf.Max(0.01f, CrownBaseScale()); foreach (List<int> item3 in list2.OrderBy(delegate(List<int> component) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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) Bounds val = BoundsFor(vertices, component); return ((Bounds)(ref val)).center.y; }).Take(2)) { foreach (int item4 in item3) { vertices[item4].z += num5; } } mesh.vertices = vertices; mesh.RecalculateBounds(); RootboundWitchPlugin.Log.LogInfo((object)"Bog Witch upper crown seated three central spine branches 0.085m forward; the two kidney-height roots received a further 0.13m lumbar seat."); } private static float CrownBaseScale() { //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_002a: 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_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_002f: 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_0076: 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)); return Mathf.Clamp(Mathf.Min(Mathf.Max(0.5f, RootboundWitchPlugin.BogWitchGrowthWidth.Value) / Mathf.Max(0.05f, ((Bounds)(ref val)).size.x), Mathf.Max(0.5f, RootboundWitchPlugin.BogWitchGrowthHeight.Value) / Mathf.Max(0.05f, ((Bounds)(ref val)).size.y)), 0.05f, 12f); } private static Bounds BoundsFor(Vector3[] vertices, IEnumerable<int> indices) { //IL_0004: 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_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_0029: 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_0055: Unknown result type (might be due to invalid IL or missing references) bool flag = false; Bounds result = default(Bounds); foreach (int index in indices) { if (!flag) { result = new Bounds(vertices[index], Vector3.zero); flag = true; } else { ((Bounds)(ref result)).Encapsulate(vertices[index]); } } return result; } private static void Activate(int[] parent, int vertex) { if (vertex >= 0 && vertex < parent.Length && parent[vertex] < 0) { parent[vertex] = vertex; } } private static int Find(int[] parent, int vertex) { while (parent[vertex] != vertex) { parent[vertex] = parent[parent[vertex]]; vertex = parent[vertex]; } return vertex; } private static void Union(int[] parent, int left, int right) { int num = Find(parent, left); int num2 = Find(parent, right); if (num != num2) { parent[num2] = num; } } 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<Transform>(true); string[] array = obj; foreach (string target in array) { Transform val = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform transform) => string.Equals(Normalize(((Object)transform).name), target, StringComparison.OrdinalIgnoreCase))); if (Object.op_Implicit((Object)(object)val)) { return val; } } Animator val2 = ((IEnumerable<Animator>)((Component)player).GetComponentsInChildren<Animator>(true)).FirstOrDefault((Func<Animator, bool>)((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<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform transform) => Normalize(((Object)transform).name).Contains("spine2"))) ?? ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((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<string> list = new List<string>(); 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<MeshFilter>(); 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<string> list = new List<string>(); 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 CrookboundRootStaff { private const string ProjectilePrefab = "CrookboundRoot_ElderProjectile"; private const string FieldRootPrefab = "CrookboundRoot_FieldRoot"; private static readonly FieldRef<Attack, Humanoid> AttackCharacter = AccessTools.FieldRefAccess<Attack, Humanoid>("m_character"); private static readonly FieldRef<Attack, ItemData> AttackWeapon = AccessTools.FieldRefAccess<Attack, ItemData>("m_weapon"); private static readonly FieldRef<Humanoid, bool> IsSecondary = AccessTools.FieldRefAccess<Humanoid, bool>("m_currentAttackIsSecondary"); private static GameObject _projectile; private static GameObject _fieldRoot; private static readonly Dictionary<long, float> NextRetaliation = new Dictionary<long, float>(); internal static GameObject Projectile => _projectile; internal static void RegisterArmourRetaliation() { if (!Object.op_Implicit((Object)(object)_fieldRoot)) { _fieldRoot = RegisterFieldRoot(); } } internal static Attack BuildMergedSecondary(SharedData rootSpell) { if (rootSpell == null || rootSpell.m_attack == null) { throw new InvalidOperationException("Rootbound Crook's Elder secondary requires the live StaffGreenRoots attack."); } if (!Object.op_Implicit((Object)(object)_projectile)) { _projectile = RegisterProjectile(); } return BuildPrimary(Require(Object.op_Implicit((Object)(object)RootboundContent.FindPrefab("BMP_SurtlingStaff")) ? "BMP_SurtlingStaff" : "StaffFireball").GetComponent<ItemDrop>().m_itemData.m_shared.m_attack ?? throw new InvalidOperationException("Rootbound Crook's Elder secondary has no player projectile-cast architecture."), rootSpell.m_attack); } internal static void Register() { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //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_0102: 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_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) GameObject obj = Require(Object.op_Implicit((Object)(object)RootboundContent.FindPrefab("BMP_SurtlingStaff")) ? "BMP_SurtlingStaff" : "StaffFireball"); GameObject val = Require("StaffGreenRoots"); SharedData shared = obj.GetComponent<ItemDrop>().m_itemData.m_shared; SharedData shared2 = val.GetComponent<ItemDrop>().m_itemData.m_shared; if (shared.m_attack == null || shared2.m_attack == null) { throw new InvalidOperationException("Crookbound Root requires live player-cast and StaffGreenRoots attack architectures."); } if (!Object.op_Implicit((Object)(object)_projectile)) { _projectile = RegisterProjectile(); } RegisterArmourRetaliation(); ReclaimedStaffVisual.SourceVisualSnapshot sourceVisualSnapshot = ReclaimedStaffVisual.CaptureSource(obj); CustomItem val2 = new CustomItem(ReclaimedStaffVisual.CreateIsolatedItemPrefab(obj, "CrookboundRoot"), true); SharedData shared3 = val2.ItemDrop.m_itemData.m_shared; shared3.m_name = "$item_crookbound_root"; shared3.m_description = "$item_crookbound_root_desc"; shared3.m_maxQuality = shared2.m_maxQuality; shared3.m_skillType = shared2.m_skillType; shared3.m_attack = BuildPrimary(shared.m_attack, shared2.m_attack); shared3.m_secondaryAttack = BuildSecondary(shared2); shared3.m_damages = shared2.m_damages; shared3.m_damagesPerLevel = shared2.m_damagesPerLevel; shared3.m_attackForce = shared2.m_attackForce; shared3.m_backstabBonus = shared2.m_backstabBonus; shared3.m_attackStatusEffect = shared2.m_attackStatusEffect; shared3.m_attackStatusEffectChance = shared2.m_attackStatusEffectChance; shared3.m_hitEffect = shared2.m_hitEffect; shared3.m_hitTerrainEffect = shared2.m_hitTerrainEffect; ApplyBareCrookVisual(val2.ItemPrefab); sourceVisualSnapshot.Restore("Crookbound Root"); ItemManager.Instance.AddItem(val2); AddRecipe(val2.ItemDrop); RootboundWitchPlugin.Log.LogInfo((object)"Crookbound Root registered: bare reclaimed branch, Elder 25-shot vine volley, 25 metre allied root field, and lifesteal on both attack modes."); } internal static bool IsOurSecondary(Attack attack) { if (attack == null) { return false; } Humanoid val = AttackCharacter.Invoke(attack); if ((Object)(object)val != (Object)null && IsSecondary.Invoke(val)) { return RootboundState.HasPrefab(AttackWeapon.Invoke(attack), "CrookboundRoot"); } return false; } internal static void CastField(Attack attack) { Humanoid obj = AttackCharacter.Invoke(attack); Player player = (Player)(object)((obj is Player) ? obj : null); ItemData val = AttackWeapon.Invoke(attack); if (RootboundSummonRecall.HasLocalAttackAuthority(player) && val != null && Object.op_Implicit((Object)(object)_fieldRoot)) { SpawnField(player, val); } } internal static bool TryArmourRetaliation(Player player) { if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead() || !RootboundState.IsFullSet(player) || !((Character)player).IsEncumbered() || !Object.op_Implicit((Object)(object)_fieldRoot)) { return false; } long playerID = player.GetPlayerID(); if (NextRetaliation.TryGetValue(playerID, out var value) && Time.time < value) { return false; } GameObject val = RootboundContent.FindPrefab("RootboundCrook"); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 == (Object)null) { RootboundWitchPlugin.Log.LogWarning((object)"Overencumbered retaliation could not resolve the Rootbound Crook damage ladder."); return false; } ItemData val3 = val2.m_itemData.Clone(); val3.m_quality = Mathf.Clamp(RootboundState.MinimumQuality(player), 1, 4); NextRetaliation[playerID] = Time.time + Mathf.Max(1f, RootboundWitchPlugin.CrookboundFieldRetaliationCooldown.Value); SpawnField(player, val3); return true; } private static void SpawnField(Player player, ItemData weapon) { //IL_0077: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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) //IL_00b1: 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) int num = Mathf.Clamp(RootboundWitchPlugin.CrookboundFieldRootCount.Value, 1, 64); float num2 = Mathf.Max(3f, RootboundWitchPlugin.CrookboundFieldRadius.Value); float num3 = Random.Range(0f, 360f); int num4 = 0; for (int i = 0; i < num; i++) { float num5 = ((float)i + 0.5f) / (float)num; float num6 = Mathf.Lerp(2.5f, num2, Mathf.Sqrt(num5)); float num7 = num3 + (float)i * 137.50777f; if (TryFindGround(((Component)player).transform.position + Quaternion.Euler(0f, num7, 0f) * Vector3.forward * num6, out var ground)) { GameObject obj = Object.Instantiate<GameObject>(_fieldRoot, ground, Quaternion.Euler(0f, num7 + 180f, 0f)); obj.SetActive(true); CrookboundFieldRoot component = obj.GetComponent<CrookboundFieldRoot>(); if ((Object)(object)component != (Object)null) { component.Assign(player, weapon); } num4++; } } RootboundWitchPlugin.Log.LogInfo((object)$"Rootbound overencumbered retaliation for {player.GetPlayerName()}: {num4}/{num} roots across {num2:0.#} m."); } private static Attack BuildPrimary(Attack playerCast, Attack rootAttack) { Attack obj = playerCast.Clone(); obj.m_attackProjectile = _projectile; obj.m_projectiles = 1; obj.m_projectileBursts = 1; obj.m_burstInterval = 0f; obj.m_perBurstResourceUsage = false; obj.m_projectileAccuracy = 10f; obj.m_projectileAccuracyMin = 20f; obj.m_randomVelocity = false; obj.m_useCharacterFacing = false; obj.m_useCharacterFacingYAim = false; obj.m_damageMultiplier = 1f; obj.m_forceMultiplier = rootAttack.m_forceMultiplier; obj.m_attackEitr = rootAttack.m_attackEitr; obj.m_attackEitrAdd = rootAttack.m_attackEitrAdd; obj.m_attackHealth = 0f; obj.m_attackHealthPercentage = 0f; obj.m_attackHealthLowBlockUse = false; obj.m_attackHealthReturnHit = Mathf.Max(0f, RootboundWitchPlugin.CrookboundProjectileLifeReturn.Value); return obj; } private static Attack BuildSecondary(SharedData rootSpell) { Attack val = RootboundCrookSecondary.BuildAttack(rootSpell); val.m_attackEitr = ((rootSpell.m_attack != null) ? rootSpell.m_attack.m_attackEitr : val.m_attackEitr); val.m_attackEitrAdd = ((rootSpell.m_attack != null) ? rootSpell.m_attack.m_attackEitrAdd : 0f); val.m_attackHealth = 0f; val.m_attackHealthPercentage = 0f; val.m_attackHealthLowBlockUse = false; val.m_attackHealthReturnHit = 0f; val.m_spawnOnTrigger = null; val.m_spawnOnHit = null; val.m_spawnOnHitChance = 0f; val.m_damageMultiplier = 0f; val.m_forceMultiplier = 0f; return val; } private static GameObject RegisterProjectile() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown GameObject val = Require("gdking_root_projectile"); if ((Object)(object)val.GetComponent<Projectile>() == (Object)null) { throw new InvalidOperationException("gdking_root_projectile is not a live Projectile prefab."); } GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("CrookboundRoot_ElderProjectile", val); val2.transform.localScale = Vector3.Scale(val2.transform.localScale, new Vector3(0.075f, 0.075f, 1f)); val2.AddComponent<CrookboundVolleySeed>(); PrefabManager.Instance.AddPrefab(new CustomPrefab(val2, true)); return val2; } private static GameObject RegisterFieldRoot() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown GameObject val = RootboundContent.FindPrefab("TentaRoot") ?? RootboundContent.FindPrefab("TentaRoot_wild"); if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val.GetComponent<Character>() == (Object)null || (Object)(object)val.GetComponent<MonsterAI>() == (Object)null || (Object)(object)val.GetComponent<ZNetView>() == (Object)null) { throw new InvalidOperationException("Neither live Elder TentaRoot prefab can host the Crookbound field."); } GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("CrookboundRoot_FieldRoot", val); Character component = val2.GetComponent<Character>(); MonsterAI component2 = val2.GetComponent<MonsterAI>(); component.m_name = "$enemy_crookbound_field_root"; component.m_faction = (Faction)11; component.m_health = Mathf.Max(1f, component.m_health * 2f); component2.m_fleeIfLowHealth = 0f; component2.m_fleeIfHurtWhenTargetCantBeReached = false; CharacterDrop component3 = val2.GetComponent<CharacterDrop>(); if ((Object)(object)component3 != (Object)null) { component3.m_drops.Clear(); } SpawnArea component4 = val2.GetComponent<SpawnArea>(); if ((Object)(object)component4 != (Object)null) { Object.DestroyImmediate((Object)(object)component4); } Tameable obj = val2.GetComponent<Tameable>() ?? val2.AddComponent<Tameable>(); obj.m_startsTamed = true; obj.m_commandable = false; obj.m_unsummonOnOwnerLogoutSeconds = 10f; val2.AddComponent<CrookboundFieldRoot>(); PrefabManager.Instance.AddPrefab(new CustomPrefab(val2, true)); return val2; } private static void ApplyBareCrookVisual(GameObject staff) { //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) ReclaimedStaffVisual.Apply(staff); ReclaimedStaffVisual.RemoveGeneratedOvergrowth(staff); FrostedStaffVisual.RemoveDeadCoreOnly(staff, "Crookbound Root"); Light[] componentsInChildren = staff.GetComponentsInChildren<Light>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } ParticleSystem[] componentsInChildren2 = staff.GetComponentsInChildren<ParticleSystem>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { EmissionModule emission = componentsInChildren2[i].emission; ((EmissionModule)(ref emission)).enabled = false; } } private static bool TryFindGround(Vector3 candidate, out Vector3 ground) { //IL_0034: 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_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) //IL_0049: 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_0083: 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_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) int mask = LayerMask.GetMask(new string[5] { "terrain", "Default", "static_solid", "piece", "piece_nonsolid" }); RaycastHit val = default(RaycastHit); if (Physics.Raycast(candidate + Vector3.up * 35f, Vector3.down, ref val, 80f, mask, (QueryTriggerInteraction)1)) { ground = ((RaycastHit)(ref val)).point + Vector3.up * 0.05f; return true; } ground = candidate; return false; } private static void AddRecipe(ItemDrop result) { //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown Recipe val = ScriptableObject.CreateInstance<Recipe>(); ((Object)val).name = "Recipe_CrookboundRoot"; val.m_item = result; val.m_amount = 1; val.m_enabled = true; GameObject val2 = Require("piece_workbench"); val.m_craftingStation = val2.GetComponent<CraftingStation>(); val.m_repairStation = val.m_craftingStation; val.m_minStationLevel = 1; List<Requirement> list = new List<Requirement>(); AddTier(list, 1, "MycelialCrook", 1); AddTier(list, 1, "CryptKey", 1); AddTier(list, 1, "Wishbone", 1); AddTier(list, 1, "Eitr", 30); AddTier(list, 2, "Eitr", 15); AddTier(list, 2, "YggdrasilWood", 10); AddTier(list, 2, "Mandible", 5); AddTier(list, 3, "AskHide", 6); AddTier(list, 3, "CelestialFeather", 4); AddTier(list, 3, "CharredBone", 8); AddTier(list, 4, FirstExisting("FrostCore", "Frostcore"), 3); AddTier(list, 4, FirstExisting("Frostwood", "FrostWood", "Timberwood"), 12); AddTier(list, 4, FirstExisting("MooseHide", "Moosehide"), 4); val.m_resources = list.ToArray(); if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val, false, false))) { throw new InvalidOperationException("Jotunn rejected " + ((Object)val).name); } } private static void AddTier(List<Requirement> requirements, int quality, string prefabName, int amount) { //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_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_0043: 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_0052: Expected O, but got Unknown ItemDrop component = Require(prefabName).GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Crookbound Root recipe item has no ItemDrop: " + prefabName); } Requirement val = new Requirement { m_resItem = component, m_amount = ((quality == 1) ? 1 : 0), m_amountPerLevel = 0, m_recover = true, m_upgraderResource = false }; requirements.Add(val); TieredRecipeCosts.Register(val, quality, amount); } private static string FirstExisting(params string[] candidates) { return candidates.FirstOrDefault((string candidate) => Object.op_Implicit((Object)(object)RootboundContent.FindPrefab(candidate))) ?? throw new InvalidOperationException("Crookbound Root upgrade material is missing: " + string.Join("|", candidates)); } private static GameObject Require(string name) { GameObject obj = RootboundContent.FindPrefab(name); if (!Object.op_Implicit((Object)(object)obj)) { throw new InvalidOperationException("Crookbound Root requires live prefab: " + name); } return obj; } } internal sealed class CrookboundVolleySeed : MonoBehaviour { private static readonly FieldRef<Projectile, Vector3> Velocity = AccessTools.FieldRefAccess<Projectile, Vector3>("m_vel"); private bool _continuation; internal void MarkContinuation() { _continuation = true; } private void Start() { //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_0084: 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_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_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) if (_continuation || !Object.op_Implicit((Object)(object)RootboundWitchPlugin.Instance)) { return; } Projectile component = ((Component)this).GetComponent<Projectile>(); Character val = (Object.op_Implicit((Object)(object)component) ? FrostedRootProjectileState.Owner(component) : null); Player val2 = (Player)(object)((val is Player) ? val : null); if (!Object.op_Implicit((Object)(object)component) || ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)Player.m_localPlayer)) { return; } if (Object.op_Implicit((Object)(object)val)) { Vector3 val3 = val.GetLookDir(); if (((Vector3)(ref val3)).sqrMagnitude < 0.01f) { val3 = ((Component)val).transform.forward; } ((Component)component).transform.position = val.GetEyePoint() + ((Vector3)(ref val3)).normalized * 0.45f; } ((MonoBehaviour)RootboundWitchPlugin.Instance).StartCoroutine(ContinueVolley(component)); } private static IEnumerator ContinueVolley(Projectile seed) { Character owner = FrostedRootProjectileState.Owner(seed); HitData hit = FrostedRootProjectileState.HitData(seed); ItemData weapon = FrostedRootProjectileState.Weapon(seed); ItemData ammo = FrostedRootProjectileState.Ammo(seed); Vector3 localMuzzle = (Object.op_Implicit((Object)(object)owner) ? ((Component)owner).transform.InverseTransformPoint(((Component)seed).transform.position) : Vector3.zero); Vector3 val = Velocity.Invoke(seed); float speed = Mathf.Max(8f, ((Vector3)(ref val)).magnitude); Vector3 val2; Vector3 lookDir; if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f)) { if (!Object.op_Implicit((Object)(object)owner)) { val2 = Vector3.forward; } else { lookDir = owner.GetLookDir(); val2 = ((Vector3)(ref lookDir)).normalized; } } else { val2 = ((Vector3)(ref val)).normalized; } Vector3 fallbackForward = val2; float hitNoise = seed.m_hitNoise; int index = 1; while (index < 25) { yield return (object)new WaitForSeconds(0.1f); GameObject projectile = CrookboundRootStaff.Projectile; if (!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)projectile)) { break; } Vector3 val3 = ((Component)owner).transform.TransformPoint(localMuzzle); lookDir = owner.GetLookDir(); Vector3 val4 = ((Vector3)(ref lookDir)).normalized; if (((Vector3)(ref val4)).sqrMagnitude < 0.01f) { val4 = fallbackForward; } Vector2 val5 = Random.insideUnitCircle * 5f; Vector3 val6 = Quaternion.Euler(0f - val5.y, val5.x, 0f) * val4; GameObject obj = Object.Instantiate<GameObject>(projectile, val3, Quaternion.LookRotation(val6)); CrookboundVolleySeed component = obj.GetComponent<CrookboundVolleySeed>(); if ((Object)(object)component != (Object)null) { component.MarkContinuation(); } obj.GetComponent<Projectile>().Setup(owner, val6 * speed, hitNoise, (HitData)((hit != null) ? ((object)hit.Clone()) : ((object)new HitData())), weapon, ammo); int num = index + 1; index = num; } } } internal sealed class CrookboundFieldRoot : MonoBehaviour { private const string OwnerKey = "ADARC_CrookboundRootOwner"; private const string ExpiresKey = "ADARC_CrookboundRootExpires"; private const string QualityKey = "ADARC_CrookboundRootQuality"; private const string DamageKey = "ADARC_CrookboundRootDamage_"; private ZNetView _view; private MonsterAI _ai; private Character _character; private long _ownerId; private float _expiresAt; private DamageTypes _damage; private void Awake() { _view = ((Component)this).GetComponent<ZNetView>(); _ai = ((Component)this).GetComponent<MonsterAI>(); _character = ((Component)this).GetComponent<Character>(); if ((Object)(object)_ai != (Object)null) { _ai.MakeTame(); _ai.SetDespawnInDay(false); } ReadState(); } private void Update() { ReadState(); if (!(_expiresAt <= 0f) && !(Time.time < _expiresAt) && !((Object)(object)_character == (Object)null) && !_character.IsDead() && ((Object)(object)_view == (Object)null || _view.GetZDO() == null || _view.IsOwner())) { RootboundSummonRecall.Kill(_character, _view); } } internal void Assign(Player owner, ItemData weapon) { //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_0092: Unknown result type (might be due to invalid IL or missing references) _ownerId = owner.GetPlayerID(); _expiresAt = Time.time + Mathf.Max(5f, RootboundWitchPlugin.CrookboundFieldDuration.Value); _damage = weapon.GetDamage(); if ((Object)(object)_view != (Object)null && _view.GetZDO() != null) { ZDO zDO = _view.GetZDO(); zDO.Set("ADARC_CrookboundRootOwner", _ownerId); zDO.Set("ADARC_CrookboundRootExpires", _expiresAt); zDO.Set("ADARC_CrookboundRootQuality", weapon.m_quality); WriteDamage(zDO, _damage); } if ((Object)(object)_ai != (Object)null) { _ai.MakeTame(); } } internal bool TryPrepareHit(Character target, ref HitData hit) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) ReadState(); if ((Object)(object)_view != (Object)null && _view.GetZDO() != null && !_view.IsOwner()) { return false; } Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player player) => (Object)(object)player != (Object)null && player.GetPlayerID() == _ownerId)); if ((Object)(object)val == (Object)null || (Object)(object)target == (Object)null || target.IsDead() || !BaseAI.IsEnemy((Character)(object)val, target)) { return false; } hit.m_damage = _damage; hit.m_skill = (SkillType)9; if ((Object)(object)_view != (Object)null && _view.GetZDO() != null) { hit.m_itemLevel = (short)Mathf.Max(1, _view.GetZDO().GetInt("ADARC_CrookboundRootQuality", 1)); } float num = Mathf.Max(0f, hit.GetTotalDamage()) * Mathf.Clamp01(RootboundWitchPlugin.CrookboundFieldLifeStealFraction.Value); if (num > 0.001f) { ((Character)val).Heal(num, true); } return true; } private void ReadState() { //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_0063: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_view == (Object)null) && _view.GetZDO() != null) { ZDO zDO = _view.GetZDO(); _ownerId = zDO.GetLong("ADARC_CrookboundRootOwner", _ownerId); _expiresAt = zDO.GetFloat("ADARC_CrookboundRootExpires", _expiresAt); _damage = ReadDamage(zDO, _damage); } } private static void WriteDamage(ZDO zdo, DamageTypes damage) { //IL_0006: 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_0028: 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_004a: 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_006c: 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_008e: 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_00b0: Unknown result type (might be due to invalid IL or missing references) zdo.Set("ADARC_CrookboundRootDamage_raw", damage.m_damage); zdo.Set("ADARC_CrookboundRootDamage_blunt", damage.m_blunt); zdo.Set("ADARC_CrookboundRootDamage_slash", damage.m_slash); zdo.Set("ADARC_CrookboundRootDamage_pierce", damage.m_pierce); zdo.Set("ADARC_CrookboundRootDamage_fire", damage.m_fire); zdo.Set("ADARC_CrookboundRootDamage_frost", damage.m_frost); zdo.Set("ADARC_CrookboundRootDamage_lightning", damage.m_lightning); zdo.Set("ADARC_CrookboundRootDamage_poison", damage.m_poison); zdo.Set("ADARC_CrookboundRootDamage_spirit", damage.m_spirit); zdo.Set("ADARC_CrookboundRootDamage_chop", damage.m_chop); zdo.Set("ADARC_CrookboundRootDamage_pickaxe", damage.m_pickaxe); } private static DamageTypes ReadDamage(ZDO zdo, DamageTypes fallback) { //IL_0002: 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_0028: 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_0058: 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_0088: 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_00b8: 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_00e8: 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_0110: Unknown result type (might be due to invalid IL or missing references) return new DamageTypes { m_damage = zdo.GetFloat("ADARC_CrookboundRootDamage_raw", fallback.m_damage), m_blunt = zdo.GetFloat("ADARC_CrookboundRootDamage_blunt", fallback.m_blunt), m_slash = zdo.GetFloat("ADARC_CrookboundRootDamage_slash", fallback.m_slash), m_pierce = zdo.GetFloat("ADARC_CrookboundRootDamage_pierce", fallback.m_pierce), m_fire = zdo.GetFloat("ADARC_CrookboundRootDamage_fire", fallback.m_fire), m_frost = zdo.GetFloat("ADARC_CrookboundRootDamage_frost", fallback.m_frost), m_lightning = zdo.GetFloat("ADARC_CrookboundRootDamage_lightning", fallback.m_lightning), m_poison = zdo.GetFloat("ADARC_CrookboundRootDamage_poison", fallback.m_poison), m_spirit = zdo.GetFloat("ADARC_CrookboundRootDamage_spirit", fallback.m_spirit), m_chop = zdo.GetFloat("ADARC_CrookboundRootDamage_chop", fallback.m_chop), m_pickaxe = zdo.GetFloat("ADARC_CrookboundRootDamage_pickaxe", fallback.m_pickaxe) }; } } [HarmonyPatch(typeof(Character), "Damage")] internal static class CrookboundFieldLifestealPatch { private static bool Prefix(Character __instance, ref HitData hit) { Character val = ((hit != null) ? hit.GetAttacker() : null); CrookboundFieldRoot crookboundFieldRoot = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<CrookboundFieldRoot>() : null); if ((Object)(object)crookboundFieldRoot == (Object)null) { return true; } return crookboundFieldRoot.TryPrepareHit(__instance, ref hit); } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class RootboundOverencumberedRetaliationPatch { private static void Postfix(Character __instance, HitData __1) { Player val = (Player)(object)((__instance is Player) ? __instance : null); Character val2 = ((__1 != null) ? __1.GetAttacker() : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val) && !(__1.GetTotalDamage() <= 0.001f) && BaseAI.IsEnemy((Character)(object)val, val2)) { CrookboundRootStaff.TryArmourRetaliation(val); } } } internal static class DraconicCrook { private const string FissureAoeName = "Fader_Fissure_AOE"; private const string FissureAoePath = "Assets/Characters/Fader/attacks/Fader_Fissure_AOE.prefab"; private const string MeteorName = "projectile_meteor_fader"; private const string MeteorPath = "Assets/Characters/Fader/attacks/projectile_meteor_fader.prefab"; private const string MeteorAftermathPrefab = "DraconicCrook_MeteorAftermath"; private const float DamagePerGrowth = 10f; private static readonly FieldRef<Attack, Humanoid> AttackCharacter = AccessTools.FieldRefAccess<Attack, Humanoid>("m_character"); private static readonly FieldRef<Attack, ItemData> AttackWeapon = AccessTools.FieldRefAccess<Attack, ItemData>("m_weapon"); private static readonly FieldRef<Humanoid, bool> IsSecondary = AccessTools.FieldRefAccess<Humanoid, bool>("m_currentAttackIsSecondary"); private static SoftReference<GameObject> _fissureReference; private static SoftReference<GameObject> _meteorReference; private static GameObject _fissureAoe; private static GameObject _meteor; private static GameObject _meteorAftermath; internal static void Register() { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_0117: 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_015a: Unknown result type (might be due to invalid IL or missing references) GameObject obj = Require("StaffIceShards"); ItemDrop component = obj.GetComponent<ItemDrop>(); Attack val = (((Object)(object)component != (Object)null) ? component.m_itemData.m_shared.m_attack : null); if (val == null) { throw new InvalidOperationException("Draconic Crook requires the live StaffIceShards item and its player-cast attack architecture."); } _fissureAoe = ResolveCombatPrefab("Fader_Fissure_AOE", "Assets/Characters/Fader/attacks/Fader_Fissure_AOE.prefab", ref _fissureReference); _meteor = ResolveCombatPrefab("projectile_meteor_fader", "Assets/Characters/Fader/attacks/projectile_meteor_fader.prefab", ref _meteorReference); if (!Object.op_Implicit((Object)(object)_fissureAoe) || (Object)(object)_fissureAoe.GetComponent<Aoe>() == (Object)null) { throw new InvalidOperationException("Fader_Fissure_AOE did not resolve to the live grausten-spike AOE."); } if (!Object.op_Implicit((Object)(object)_meteor) || (Object)(object)_meteor.GetComponent<Projectile>() == (Object)null) { throw new InvalidOperationException("projectile_meteor_fader did not resolve to the live Fader meteor projectile."); } _meteorAftermath = RegisterMeteorAftermath(_meteor); ReclaimedStaffVisual.SourceVisualSnapshot sourceVisualSnapshot = ReclaimedStaffVisual.CaptureSource(obj); CustomItem val2 = new CustomItem(ReclaimedStaffVisual.CreateIsolatedItemPrefab(obj, "DraconicCrook"), true); SharedData shared = val2.ItemDrop.m_itemData.m_shared; shared.m_name = "$item_draconic_crook"; shared.m_description = "$item_draconic_crook_desc"; shared.m_maxQuality = 4; shared.m_skillType = (SkillType)9; shared.m_attack = BuildAttack(val, RootboundWitchPlugin.DraconicFissureEitr.Value); shared.m_secondaryAttack = BuildAttack(val, RootboundWitchPlugin.DraconicMeteorEitr.Value); shared.m_damages = default(DamageTypes); shared.m_damagesPerLevel = default(DamageTypes); shared.m_attackForce = 0f; shared.m_attackStatusEffect = null; shared.m_attackStatusEffectChance = 0f; DraconicCrookVisual.Apply(val2.ItemPrefab); RootboundStaffIcons.Apply(shared, RootboundStaffIcon.DraconicCrook); sourceVisualSnapshot.Restore("Draconic Crook"); ItemManager.Instance.AddItem(val2); AddRecipe(val2.ItemDrop); RootboundWitchPlugin.Log.LogInfo((object)"Draconic Crook registered from an isolated StaffIceShards body. Primary deploys Fader's exact 12-15 grausten fissures; secondary deploys the exact ten-projectile Fader meteor shower. Four growths add ten damage to every authored damage channel per upgrade. Vanilla StaffIceShards visuals were source-audited and retained."); } internal static bool IsOurAttack(Attack attack) { if (attack != null) { return RootboundState.HasPrefab(AttackWeapon.Invoke(attack), "DraconicCrook"); } return false; } internal static bool HandleAttack(Attack attack) { Humanoid obj = AttackCharacter.Invoke(attack); Player val = (Player)(object)((obj is Player) ? obj : null); ItemData val2 = AttackWeapon.Invoke(attack); if (!RootboundSummonRecall.HasLocalAttackAuthority(val) || val2 == null) { return false; } if (!RootboundAttackTransaction.TryBegin(attack)) { return false; } IEnumerator enumerator = (IsSecondary.Invoke((Humanoid)(object)val) ? CastMeteorShower(val, val2) : CastFissureField(val, val2)); if (Object.op_Implicit((Object)(object)RootboundWitchPlugin.Instance)) { ((MonoBehaviour)RootboundWitchPlugin.Instance).StartCoroutine(enumerator); } return false; } private static Attack BuildAttack(Attack source, float eitr) { Attack obj = source.Clone(); 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_useCharacterFacing = false; obj.m_useCharacterFacingYAim = false; obj.m_attackEitr = Mathf.Max(0f, eitr); obj.m_attackEitrAdd = 0f; obj.m_attackStamina = 0f; obj.m_attackHealth = 0f; obj.m_attackHealthPercentage = 0f; obj.m_attackHealthLowBlockUse = false; obj.m_attackHealthReturnHit = 0f; obj.m_damageMultiplier = 0f; obj.m_forceMultiplier = 0f; return obj; } private static IEnumerator CastFissureField(Player player, ItemData weapon) { int count = Random.Range(12, 16); int index = 0; while (index < count && Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && Object.op_Implicit((Object)(object)_fissureAoe)) { Vector3 val = FindTargetPoint(player); GameObject obj = Object.Instantiate<GameObject>(_fissureAoe, val + Vector3.up * 0.2f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)); Aoe component = obj.GetComponent<Aoe>(); component.m_damagePerLevel = GrowthPacket(component.m_damage); component.Setup((Character)(object)player, Vector3.zero, -1f, (HitData)null, weapon, (ItemData)null); obj.SetActive(true); yield return (object)new WaitForSeconds(0.45f); int num = index + 1; index = num; } } private static IEnumerator CastMeteorShower(Player player, ItemData weapon) { int index = 0; while (index < 10 && Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && Object.op_Implicit((Object)(object)_meteor)) { Vector3 val = FindTargetPoint(player); Vector2 val2 = Random.insideUnitCircle * 15f; Vector3 val3 = val + new Vector3(val2.x, 90f, val2.y); Vector3 val4 = val - val3; Vector3 val5 = ((Vector3)(ref val4)).normalized * 30f; GameObject obj = Object.Instantiate<GameObject>(_meteor, val3, Quaternion.LookRotation(val5)); Projectile component = obj.GetComponent<Projectile>(); if (Object.op_Implicit((Object)(object)_meteorAftermath)) { component.m_spawnOnHit = _meteorAftermath; } component.Setup((Character)(object)player, val5, -1f, (HitData)null, weapon, (ItemData)null); component.m_damage = DamageAtQuality(component.m_damage, weapon.m_quality); obj.SetActive(true); yield return (object)new WaitForSeconds(0.5f); int num = index + 1; index = num; } } private static GameObject RegisterMeteorAftermath(GameObject meteor) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown Projectile component = meteor.GetComponent<Projectile>(); GameObject val = (((Object)(object)component != (Object)null) ? component.m_spawnOnHit : null); Aoe[] array = (Aoe[])(Object.op_Implicit((Object)(object)val) ? ((Array)val.GetComponentsInChildren<Aoe>(true)) : ((Array)new Aoe[0])); if (!Object.op_Implicit((Object)(object)val) || array.Length == 0) { throw new InvalidOperationException("Fader meteor has no live AOE aftermath to make quality-aware."); } GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("DraconicCrook_MeteorAftermath", val); Aoe[] componentsInChildren = val2.GetComponentsInChildren<Aoe>(true); foreach (Aoe obj in componentsInChildren) { obj.m_damagePerLevel = GrowthPacket(obj.m_damage); } PrefabManager.Instance.AddPrefab(new CustomPrefab(val2, true)); return val2; } private static DamageTypes GrowthPacket(DamageTypes authored) { //IL_0002: 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_002a: 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_006a: 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_00aa: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_0148: Unknown result type (might be due to invalid IL or missing references) return new DamageTypes { m_blunt = ((authored.m_blunt > 0f) ? 10f : 0f), m_slash = ((authored.m_slash > 0f) ? 10f : 0f), m_pierce = ((authored.m_pierce > 0f) ? 10f : 0f), m_chop = ((authored.m_chop > 0f) ? 10f : 0f), m_pickaxe = ((authored.m_pickaxe > 0f) ? 10f : 0f), m_fire = ((authored.m_fire > 0f) ? 10f : 0f), m_frost = ((authored.m_frost > 0f) ? 10f : 0f), m_lightning = ((authored.m_lightning > 0f) ? 10f : 0f), m_poison = ((authored.m_poison > 0f) ? 10f : 0f), m_spirit = ((authored.m_spirit > 0f) ? 10f : 0f) }; } private static DamageTypes DamageAtQuality(DamageTypes authored, int quality) { //IL_0011: 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_0017: 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_000f: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(quality, 1, 4) - 1; if (num <= 0) { return authored; } DamageTypes val = GrowthPacket(authored); ((DamageTypes)(ref authored)).Add(val, num); return authored; } private static Vector3 FindTargetPoint(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_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_0079: 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_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_00c0: 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_00ab: 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_00ba: 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 val2 = default(RaycastHit); Vector3 val = (Physics.Raycast(eyePoint, normalized, ref val2, 4096f, -1, (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val2)).point : (eyePoint + normalized * 80f)); int mask = LayerMask.GetMask(new string[5] { "terrain", "Default", "static_solid", "piece", "piece_nonsolid" }); RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val + Vector3.up * 60f, Vector3.down, ref val3, 180f, mask, (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val3)).point + Vector3.up * 0.05f; } return val; } private static GameObject ResolveCombatPrefab(string shortName, string fullPath, ref SoftReference<GameObject> heldReference) { //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_0047: Unknown result type (might be due to invalid IL or missing references) GameObject val = RootboundContent.FindPrefab(shortName); if (Object.op_Implicit((Object)(object)val)) { return val; } string[] array = new string[2] { shortName, fullPath }; foreach (string text in array) { try { heldReference = AssetManager.Instance.GetSoftReference<GameObject>(text); if (heldReference.IsValid) { heldReference.Load(); heldReference.WaitForLoadToComplete(); val = heldReference.Asset; if (Object.op_Implicit((Object)(object)val)) { heldReference.HoldReference(); RootboundWitchPlugin.Log.LogInfo((object)("Draconic Crook resolved live Fader asset '" + text + "'.")); return val; } } } catch (Exception ex) { RootboundWitchPlugin.Log.LogWarning((object)("Draconic Crook Fader asset candidate '" + text + "' failed: " + ex.Message)); } } return null; } private static void AddRecipe(ItemDrop result) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown Recipe val = ScriptableObject.CreateInstance<Recipe>(); ((Object)val).name = "Recipe_DraconicCrook"; val.m_item = result; val.m_amount = 1; val.m_enabled = true; val.m_craftingStation = Require("piece_magetable").GetComponent<CraftingStation>(); val.m_repairStation = val.m_craftingStation; val.m_minStationLevel = 4; List<Requirement> list = new List<Requirement>(); AddTier(list, 1, "StaffIceShards", 1); AddTier(list, 1, "TrophyFader", 2); AddTier(list, 1, "FaderEmber", 15); AddTier(list, 1, "GemstoneGreen", 3); AddTier(list, 1, "Eitr", 65); AddTier(list, 2, "TrophyFader", 1); AddTier(list, 2, "FaderEmber", 10); AddTier(list, 2, "Eitr", 20); AddTier(list, 3, "TrophyFader", 1); AddTier(list, 3, "FaderEmber", 15); AddTier(list, 3, "GemstoneGreen", 1); AddTier(list, 3, "Eitr", 30); AddTier(list, 4, "TrophyFader", 1); AddTier(list, 4, "FaderEmber", 20); AddTier(list, 4, "GemstoneGreen", 2); AddTier(list, 4, "Eitr", 40); val.m_resources = list.ToArray(); if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val, false, false))) { throw new InvalidOperationException("Jotunn rejected " + ((Object)val).name); } } private static void AddTier(List<Requirement> requirements, int quality, string prefabName, int amount) { Requirement val = Requirement(prefabName, (quality == 1) ? 1 : 0); val.m_amountPerLevel = 0; val.m_upgraderResource = false; requirements.Add(val); TieredRecipeCosts.Register(val, quality, amount); } private static Requirement Requirement(string prefabName, int amount) { //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_0032: 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_0040: 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_004f: Expected O, but got Unknown ItemDrop component = Require(prefabName).GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Draconic Crook recipe item is missing: " + prefabName); } return new Requirement { m_resItem = component, m_amount = amount, m_amountPerLevel = 0, m_upgraderResource = false, m_recover = true }; } private static GameObject Require(string prefabName) { GameObject obj = RootboundContent.FindPrefab(prefabName); if (!Object.op_Implicit((Object)(object)obj)) { throw new InvalidOperationException("Draconic Crook requires live prefab: " + prefabName); } return obj; } } internal static class DraconicCrookVisual { private static readonly Color RotDark = new Color(0.006f, 0.022f, 0.01f, 0.07f); private static readonly Color RotLight = new Color(0.035f, 0.12f, 0.04f, 0.17f); private static readonly Color SolidRot = new Color(0.035f, 0.18f, 0.055f, 1f); private static readonly string[] ColourProperties = new string[3] { "_Color", "_BaseColor", "_TintColor" }; internal static void Apply(GameObject staff) { //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: 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_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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_00bc: 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) if (!Object.op_Implicit((Object)(object)staff)) { return; } ReclaimedStaffVisual.DisableUpgradeGlow(staff); Renderer[] componentsInChildren = staff.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { bool flag = val is ParticleSystemRenderer || val is TrailRenderer || val is LineRenderer; Material[] sharedMaterials = val.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])) { continue; } Material val2 = new Material(sharedMaterials[j]) { name = ((Object)sharedMaterials[j]).name + "_DraconicCrookIsolated" }; string[] colourProperties = ColourProperties; foreach (string text in colourProperties) { if (val2.HasProperty(text)) { val2.SetColor(text, flag ? RotLight : SolidRot); } } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", Color.black); } val2.DisableKeyword("_EMISSION"); if (flag) { MakeTransparent(val2); } array[j] = val2; } val.sharedMaterials = array; TrailRenderer val3 = (TrailRenderer)(object)((val is TrailRenderer) ? val : null); if (Object.op_Implicit((Object)(object)val3)) { val3.startColor = RotLight; val3.endColor = RotDark; } LineRenderer val4 = (LineRenderer)(object)((val is LineRenderer) ? val : null); if (Object.op_Implicit((Object)(object)val4)) { val4.startColor = RotLight; val4.endColor = RotDark; } } ParticleSystem[] componentsInChildren2 = staff.GetComponentsInChildren<ParticleSystem>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { MainModule main = componentsInChildren2[i].main; ((MainModule)(ref main)).startColor = new MinMaxGradient(RotDark, RotLight); } Light[] componentsInChildren3 = staff.GetComponentsInChildren<Light>(true); foreach (Light obj in componentsInChildren3) { obj.color = SolidRot; obj.intensity = Mathf.Min(obj.intensity, 0.12f); obj.range = Mathf.Min(obj.range, 3f); } } private static void MakeTransparent(Material material) { 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 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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<RootboundTriangleProjectile>(); 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, bool keepSolidGeometryOpaque = false) { //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<ParticleSystem>(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<Light>(true); foreach (Light obj in componentsInChildren2) { ((Behaviour)obj).enabled = false; obj.intensity = 0f; } Renderer[] componentsInChildren3 = visual.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren3) { Material[] array = ((IEnumerable<Material>)val.sharedMaterials).Select((Func<Material, Material>)((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, keepSolidGeometryOpaque); } val.sharedMaterials = array; } } private static void Tint(Material material, bool airborne, bool keepSolidGeometryOpaque) { //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_00bc: 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_006d: 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 : (keepSolidGeometryOpaque ? 1f : 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; } else if (keepSolidGeometryOpaque) { 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; } } } internal sealed class RootboundTriangleProjectile : MonoBehaviour { private static readonly FieldRef<Projectile, Character> Owner = AccessTools.FieldRefAccess<Projectile, Character>("m_owner"); private static readonly FieldRef<Projectile, Vector3> Velocity = AccessTools.FieldRefAccess<Projectile, Vector3>("m_vel"); private static readonly FieldRef<Projectile, Vector3> StartPoint = AccessTools.FieldRefAccess<Projectile, Vector3>("m_startPoint"); private static int _sequence; private Projectile _projectile; private bool _placed; private void Awake() { _projectile = ((Component)this).GetComponent<Projectile>(); } 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) //