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 SwampCapes v1.0.0
BepInEx/plugins/SwampCapes/SwampCapes.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SwampCapes")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SwampCapes")] [assembly: AssemblyTitle("SwampCapes")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SwampCapes { internal static class Appearance { internal static void Cape(GameObject prefab, bool guck) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Renderer obj = ((val is SkinnedMeshRenderer) ? val : null); object obj2 = ((obj != null) ? ((SkinnedMeshRenderer)obj).sharedMesh : null); if (obj2 == null) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); obj2 = ((component != null) ? component.sharedMesh : null); } Mesh mesh = (Mesh)obj2; Material[] sharedMaterials = val.sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { if (!Object.op_Implicit((Object)(object)sharedMaterials[j])) { continue; } Material val2 = Object.Instantiate<Material>(sharedMaterials[j]); if (val2.HasProperty("_MainTex") && Object.op_Implicit((Object)(object)val2.GetTexture("_MainTex"))) { Texture2D val3 = ReadTexture(val2.GetTexture("_MainTex")); Color[] pixels = val3.GetPixels(); float[] array = Heights(mesh, j, ((Texture)val3).width, ((Texture)val3).height); Texture2D val4 = new Texture2D(((Texture)val3).width, ((Texture)val3).height, (TextureFormat)4, false); Color[] array2 = (Color[])(object)new Color[pixels.Length]; for (int k = 0; k < pixels.Length; k++) { Color val5 = pixels[k]; float num = ((array != null && array[k] >= 0f) ? array[k] : ((float)(k / ((Texture)val3).width) / (float)(((Texture)val3).height - 1))); float num2 = 1f - Mathf.SmoothStep(0f, 0.48f, num); pixels[k] = Recolor(val5, guck, num2); array2[k] = (guck ? (new Color(0.32f, 0.56f, 0.035f, 1f) * (num2 * val5.a * (0.5f + ((Color)(ref val5)).grayscale * 0.5f))) : (new Color(0.4f, 0.025f, 0.018f, 1f) * ((1f - Mathf.SmoothStep(0.12f, 0.52f, ((Color)(ref val5)).grayscale)) * val5.a))); } val3.SetPixels(pixels); val3.Apply(); val4.SetPixels(array2); val4.Apply(); ((Texture)val3).wrapMode = val2.GetTexture("_MainTex").wrapMode; val2.SetTexture("_MainTex", (Texture)(object)val3); if (val2.HasProperty("_Color")) { val2.SetColor("_Color", Color.white); } if (val2.HasProperty("_EmissionMap")) { val2.SetTexture("_EmissionMap", (Texture)(object)val4); } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", Color.white * (guck ? Plugin.GuckGlowStrength.Value : Plugin.LeechGlowStrength.Value)); } val2.EnableKeyword("_EMISSION"); sharedMaterials[j] = val2; } } val.sharedMaterials = sharedMaterials; } } private static Color Recolor(Color original, bool guck, float hem) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(((Color)(ref original)).grayscale); Color val; if (guck) { val = Color.Lerp(new Color(0.045f, 0.048f, 0.043f), new Color(0.3f, 0.48f, 0.04f), hem); } else { float num2 = 1f - Mathf.SmoothStep(0.12f, 0.52f, num); val = Color.Lerp(new Color(0.19f, 0.23f, 0.15f), new Color(0.6f, 0.075f, 0.06f), num2); } Color result = val * (0.3f + num * 1.1f); result.a = original.a; return result; } private static Texture2D ReadTexture(Texture source) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); RenderTexture active = RenderTexture.active; try { Graphics.Blit(source, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0); val.Apply(); return val; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } private static float[] Heights(Mesh mesh, int slot, int width, int height) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_00f5: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)mesh) || !mesh.isReadable || slot >= mesh.subMeshCount) { return null; } Vector2[] uv = mesh.uv; Vector3[] vertices = mesh.vertices; if (uv.Length != vertices.Length) { return null; } float[] array = new float[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = -1f; } int[] triangles = mesh.GetTriangles(slot); Bounds bounds = mesh.bounds; for (int j = 0; j + 2 < triangles.Length; j += 3) { int num = triangles[j]; int num2 = triangles[j + 1]; int num3 = triangles[j + 2]; Vector2 val = uv[num]; Vector2 val2 = uv[num2]; Vector2 val3 = uv[num3]; float num4 = (val2.y - val3.y) * (val.x - val3.x) + (val3.x - val2.x) * (val.y - val3.y); if (Mathf.Abs(num4) < 1E-06f) { continue; } int num5 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Min(val.x, Mathf.Min(val2.x, val3.x)) * (float)width), 0, width - 1); int num6 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(val.x, Mathf.Max(val2.x, val3.x)) * (float)width), 0, width - 1); int num7 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Min(val.y, Mathf.Min(val2.y, val3.y)) * (float)height), 0, height - 1); int num8 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(val.y, Mathf.Max(val2.y, val3.y)) * (float)height), 0, height - 1); for (int k = num7; k <= num8; k++) { for (int l = num5; l <= num6; l++) { float num9 = ((float)l + 0.5f) / (float)width; float num10 = ((float)k + 0.5f) / (float)height; float num11 = ((val2.y - val3.y) * (num9 - val3.x) + (val3.x - val2.x) * (num10 - val3.y)) / num4; float num12 = ((val3.y - val.y) * (num9 - val3.x) + (val.x - val3.x) * (num10 - val3.y)) / num4; float num13 = 1f - num11 - num12; if (!(num11 < -0.001f) && !(num12 < -0.001f) && !(num13 < -0.001f)) { array[k * width + l] = Mathf.InverseLerp(((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z, vertices[num].z * num11 + vertices[num2].z * num12 + vertices[num3].z * num13); } } } } return array; } internal static Sprite RubberIcon() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) using Stream stream = typeof(Appearance).Assembly.GetManifestResourceStream("SwampCapes.RubberIcon.png"); if (stream == null) { throw new InvalidOperationException("Rubber icon asset is missing."); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, memoryStream.ToArray())) { throw new InvalidOperationException("Cannot decode Rubber icon."); } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } internal static Sprite CapeIcon(Sprite source, bool guck) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) Texture2D val = ReadTexture((Texture)(object)source.texture); Rect textureRect = source.textureRect; Texture2D val2 = new Texture2D((int)((Rect)(ref textureRect)).width, (int)((Rect)(ref textureRect)).height, (TextureFormat)4, false); Color[] pixels = val.GetPixels((int)((Rect)(ref textureRect)).x, (int)((Rect)(ref textureRect)).y, (int)((Rect)(ref textureRect)).width, (int)((Rect)(ref textureRect)).height); for (int i = 0; i < pixels.Length; i++) { pixels[i] = Recolor(pixels[i], guck, 1f - Mathf.SmoothStep(0f, 0.4f, (float)(i / ((Texture)val2).width) / (float)((Texture)val2).height)); } val2.SetPixels(pixels); val2.Apply(); Object.Destroy((Object)(object)val); return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f)); } internal static void RubberRoll(GameObject prefab) { //IL_00bb: 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_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); Material val = null; Renderer[] array = componentsInChildren; for (int i = 0; i < array.Length; i++) { Material[] sharedMaterials = array[i].sharedMaterials; foreach (Material val2 in sharedMaterials) { if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.shader)) { val = val2; break; } } } if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("No loaded material on Rubber's source prefab."); } Material val3 = Object.Instantiate<Material>(val); if (val3.HasProperty("_MainTex")) { val3.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture); } if (val3.HasProperty("_Color")) { val3.SetColor("_Color", new Color(0.045f, 0.045f, 0.05f)); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", Color.black); } if (val3.HasProperty("_EmissionMap")) { val3.SetTexture("_EmissionMap", (Texture)(object)Texture2D.blackTexture); } if (val3.HasProperty("_BumpMap")) { val3.SetTexture("_BumpMap", (Texture)null); } if (val3.HasProperty("_Glossiness")) { val3.SetFloat("_Glossiness", 0.3f); } val3.DisableKeyword("_EMISSION"); Transform val4 = prefab.transform.Find("attach") ?? prefab.transform; GameObject val5 = new GameObject("RubberRoll"); val5.transform.SetParent(val4, false); val5.transform.localRotation = Quaternion.Euler(0f, 0f, 75f); Mesh val6 = new Mesh(); List<Vector3> list = new List<Vector3>(); List<int> list2 = new List<int>(); for (int k = 0; k < 4; k++) { for (int l = 0; l <= 48; l++) { float num = (float)l * MathF.PI * 2f / 48f; float num2 = ((k < 2) ? 0.055f : 0.043f); list.Add(new Vector3(Mathf.Cos(num) * num2, (k % 2 == 0) ? (-0.16f) : 0.16f, Mathf.Sin(num) * num2)); } } for (int m = 0; m < 48; m++) { Quad(list2, m, m + 1, 49 + m + 1, 49 + m); int num3 = 98; Quad(list2, num3 + m, num3 + 48 + 1 + m, num3 + 48 + 1 + m + 1, num3 + m + 1); Quad(list2, m, num3 + m, num3 + m + 1, m + 1); Quad(list2, 49 + m, 49 + m + 1, num3 + 48 + 1 + m + 1, num3 + 48 + 1 + m); } val6.SetVertices(list); val6.SetTriangles(list2, 0); val6.RecalculateNormals(); val6.RecalculateBounds(); val5.AddComponent<MeshFilter>().sharedMesh = val6; ((Renderer)val5.AddComponent<MeshRenderer>()).sharedMaterial = val3; AddRollDetails(val5.transform, val3); array = componentsInChildren; for (int i = 0; i < array.Length; i++) { array[i].enabled = false; } } private static void AddRollDetails(Transform parent, Material rubber) { //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0273: 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) List<Vector3> list = new List<Vector3>(); List<int> list2 = new List<int>(); for (int i = 0; i < 2; i++) { int count = list.Count; for (int j = 0; j <= 240; j++) { float num = (float)j / 240f * MathF.PI * 8f; float num2 = 0.006f + 0.047f * (float)j / 240f; float num3 = ((i == 0) ? (-0.162f) : 0.162f); list.Add(new Vector3(Mathf.Cos(num) * (num2 - 0.0015f), num3, Mathf.Sin(num) * (num2 - 0.0015f))); list.Add(new Vector3(Mathf.Cos(num) * (num2 + 0.0015f), num3, Mathf.Sin(num) * (num2 + 0.0015f))); if (j > 0) { int num4 = count + (j - 1) * 2; int num5 = num4 + 1; int num6 = num4 + 3; int num7 = num4 + 2; Quad(list2, num4, num5, num6, num7); Quad(list2, num7, num6, num5, num4); } } } Material val = Object.Instantiate<Material>(rubber); if (val.HasProperty("_Color")) { val.SetColor("_Color", new Color(0.11f, 0.11f, 0.12f)); } AddMesh(parent, "RolledEdges", list, list2, val); list = new List<Vector3>(); list2 = new List<int>(); for (int k = 0; k <= 48; k++) { for (int l = 0; l <= 8; l++) { float num8 = (float)k * MathF.PI * 2f / 48f; float num9 = (float)l * MathF.PI * 2f / 8f; float num10 = 0.057f + 0.0025f * Mathf.Cos(num9); list.Add(new Vector3(Mathf.Cos(num8) * num10, 0.0025f * Mathf.Sin(num9), Mathf.Sin(num8) * num10)); if (k < 48 && l < 8) { int num11 = k * 9 + l; Quad(list2, num11, num11 + 1, num11 + 8 + 2, num11 + 8 + 1); Quad(list2, num11 + 8 + 1, num11 + 8 + 2, num11 + 1, num11); } } } Material val2 = Object.Instantiate<Material>(rubber); if (val2.HasProperty("_Color")) { val2.SetColor("_Color", new Color(0.23f, 0.23f, 0.24f)); } AddMesh(parent, "BindingCord", list, list2, val2); } private static void AddMesh(Transform parent, string name, List<Vector3> vertices, List<int> triangles, Material material) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); Mesh val2 = new Mesh(); val2.SetVertices(vertices); val2.SetTriangles(triangles, 0); val2.RecalculateNormals(); val2.RecalculateBounds(); val.AddComponent<MeshFilter>().sharedMesh = val2; ((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = material; } private static void Quad(List<int> t, int a, int b, int c, int d) { t.Add(a); t.Add(c); t.Add(b); t.Add(a); t.Add(d); t.Add(c); } } [BepInPlugin("joshu.swampcapes", "SwampCapes", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int), typeof(bool) })] private static class CapeTooltip { private static void Postfix(ItemData item, int qualityLevel, bool crafting, ref string __result) { if (!IsCape(item) || string.IsNullOrEmpty(__result)) { return; } string stats; if (Is(item, "SC_CapeLeech")) { stats = TooltipText.LifestealLine(qualityLevel, (crafting && qualityLevel > item.m_quality) ? item.m_quality : 0, LifestealMultiplier.Value); __result = __result.Replace(TooltipText.LeechDescription(), TooltipText.LeechDescription(LifestealMultiplier.Value)); } else { stats = "Wet Immunity\nPoison Resistance"; string damageModifiersTooltipString = SE_Stats.GetDamageModifiersTooltipString(item.m_shared.m_damageModifiers); if (!string.IsNullOrEmpty(damageModifiersTooltipString)) { __result = __result.Replace(damageModifiersTooltipString, ""); } } __result = TooltipText.InsertAfterWeight(__result, stats, Localization.instance.Localize("$item_weight")); } } [HarmonyPatch(typeof(Requirement), "GetAmount")] private static class UpgradeCost { private static bool Prefix(Requirement __instance, int __0, ref int __result) { if (__instance.m_upgraderResource || __0 <= 1) { return true; } ObjectDB instance = ObjectDB.instance; if (!Object.op_Implicit((Object)(object)instance) || !instance.m_recipes.Any((Recipe r) => Object.op_Implicit((Object)(object)r) && Object.op_Implicit((Object)(object)r.m_item) && IsCape(r.m_item.m_itemData) && r.m_resources.Contains(__instance))) { return true; } __result = ((__instance.m_amountPerLevel != 0) ? Rules.UpgradeCost(__0) : 0); return false; } } [HarmonyPatch(typeof(Character), "CustomFixedUpdate")] private static class CapeUpdate { private static void Postfix(Character __instance) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner()) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { ItemData val2 = EquippedCape((Humanoid)(object)val); float num = (Is(val2, "SC_CapeLeech") ? Rules.LifestealRate(val2.m_quality, LifestealMultiplier.Value) : 0f); if (component.GetZDO().GetFloat("SC_Lifesteal", 0f) != num) { component.GetZDO().Set("SC_Lifesteal", num); } if (Is(val2, "SC_CapeRubberGuck")) { __instance.GetSEMan().RemoveStatusEffect(SEMan.s_statusEffectWet, false); } } } } [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(StatusEffect), typeof(bool), typeof(int), typeof(float), typeof(short) })] private static class BlockWet { private static bool Prefix(SEMan __instance, StatusEffect statusEffect, Character ___m_character, ref StatusEffect __result) { if (!Object.op_Implicit((Object)(object)statusEffect) || ((Object)statusEffect).name != "Wet" || !Is(EquippedCape((Humanoid)(object)((___m_character is Humanoid) ? ___m_character : null)), "SC_CapeRubberGuck")) { return true; } __result = null; return false; } } [HarmonyPatch(typeof(Character), "ApplyDamage")] private static class Lifesteal { private static void Prefix(Character __instance, out float __state) { __state = __instance.GetHealth(); } private static void Postfix(Character __instance, HitData hit, float __state) { float num = Rules.HealthLost(__state, __instance.GetHealth()); if (num <= 0f) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (component == null || !component.IsOwner()) { return; } Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val == (Object)(object)__instance) && !((Character)val).IsDead()) { ZNetView component2 = ((Component)val).GetComponent<ZNetView>(); ItemData val2 = EquippedCape((Humanoid)(object)val); float num2 = ((Object.op_Implicit((Object)(object)component2) && component2.IsValid() && !component2.IsOwner()) ? component2.GetZDO().GetFloat("SC_Lifesteal", 0f) : (Is(val2, "SC_CapeLeech") ? Rules.LifestealRate(val2.m_quality, LifestealMultiplier.Value) : 0f)); if (num2 > 0f) { ((Character)val).Heal(num * num2, true); } } } } public const string Guid = "joshu.swampcapes"; internal const string RubberCape = "SC_CapeRubberGuck"; internal const string LeechCape = "SC_CapeLeech"; internal const string Rubber = "SC_Rubber"; internal const string RateKey = "SC_Lifesteal"; internal static Plugin Instance; internal static ConfigEntry<float> GuckGlowStrength; internal static ConfigEntry<float> LeechGlowStrength; internal static ConfigEntry<float> LifestealMultiplier; private Harmony harmony; private static readonly HashSet<Requirement> CapeRequirements = new HashSet<Requirement>(); private void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown Instance = this; GuckGlowStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "GuckGlowStrength", 1.6f, new ConfigDescription("Green hem glow intensity. Restart the game after changing this value.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); LeechGlowStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "LeechGlowStrength", 0.45f, new ConfigDescription("Subtle red-patch glow intensity for visibility in the swamp. Restart after changing this value; 0 disables glow.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); LifestealMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "LifestealMultiplier", 1f, "Multiplies Leech Cape lifesteal at every level. 1 = default (5% plus 2.5 percentage points per upgrade); 2 doubles it; 0.5 halves it; 0 disables it. Negative values act as 0; non-finite values use 1. Each player configures their own multiplier. Restart after editing the config file."); PrefabManager.OnVanillaPrefabsAvailable += Register; ItemManager.OnItemsRegistered += LinkIdols; harmony = new Harmony("joshu.swampcapes"); harmony.PatchAll(); } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= Register; ItemManager.OnItemsRegistered -= LinkIdols; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private void Register() { PrefabManager.OnVanillaPrefabsAvailable -= Register; CustomItem rubber = Add("SC_Rubber", "Resin", "Rubber", "A waterproof roll of black rubber, cured from guck and coal.", (RequirementConfig[])(object)new RequirementConfig[2] { Req("Guck", 2), Req("Coal", 5) }); rubber.ItemDrop.m_itemData.m_shared.m_maxStackSize = 50; rubber.ItemDrop.m_itemData.m_shared.m_weight = 0.5f; rubber.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { Appearance.RubberIcon() }; CustomItem guck = Add("SC_CapeRubberGuck", "CapeAsh", "Rubber Guck Cape", "You stink like fish... but at least you are dry!", (RequirementConfig[])(object)new RequirementConfig[2] { Req("SC_Rubber", 10, 2), Req("TrophyBlob", 1) }); ConfigureCape(guck); StatusEffect consumeStatusEffect = PrefabManager.Instance.GetPrefab("MeadPoisonResist").GetComponent<ItemDrop>().m_itemData.m_shared.m_consumeStatusEffect; SE_Stats val = (SE_Stats)(object)((consumeStatusEffect is SE_Stats) ? consumeStatusEffect : null); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Cannot resolve poison resistance mead's status effect."); } guck.ItemDrop.m_itemData.m_shared.m_damageModifiers = val.m_mods.Where((DamageModPair m) => (int)m.m_type == 256).ToList(); if (guck.ItemDrop.m_itemData.m_shared.m_damageModifiers.Count == 0) { throw new InvalidOperationException("Poison resistance mead has no poison modifier."); } CustomItem leech = Add("SC_CapeLeech", "CapeAsksvin", "Leech Cape", "Suck the health off your enemies for 5% of damage dealt, increasing with each level", (RequirementConfig[])(object)new RequirementConfig[2] { Req("Bloodbag", 10, 2), Req("TrophyLeech", 1) }); ConfigureCape(leech); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered Rubber, Rubber Guck Cape and Leech Cape."); ApplyAppearance("Rubber Guck Cape icon", delegate { guck.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { Appearance.CapeIcon(guck.ItemDrop.m_itemData.m_shared.m_icons[0], guck: true) }; }); ApplyAppearance("Leech Cape icon", delegate { leech.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { Appearance.CapeIcon(leech.ItemDrop.m_itemData.m_shared.m_icons[0], guck: false) }; }); ApplyAppearance("Rubber", delegate { Appearance.RubberRoll(rubber.ItemPrefab); }); ApplyAppearance("Rubber Guck Cape", delegate { Appearance.Cape(guck.ItemPrefab, guck: true); }); ApplyAppearance("Leech Cape", delegate { Appearance.Cape(leech.ItemPrefab, guck: false); }); } private void ApplyAppearance(string item, Action apply) { try { apply(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Appearance setup failed for " + item + "; its recipe is still registered. " + ex)); } } private static RequirementConfig Req(string item, int amount, int upgrade = 0) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown return new RequirementConfig(item, amount, upgrade, true); } private static CustomItem Add(string id, string source, string name, string description, RequirementConfig[] costs) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0020: 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_0034: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown CustomItem val = new CustomItem(id, source, new ItemConfig { Name = name, Description = description, CraftingStation = "piece_workbench", MinStationLevel = 1, Requirements = costs }); if (!ItemManager.Instance.AddItem(val)) { throw new InvalidOperationException("Could not register " + id); } return val; } private static void ConfigureCape(CustomItem cape) { SharedData shared = cape.ItemDrop.m_itemData.m_shared; shared.m_maxQuality = 5; shared.m_armor = 1f; shared.m_armorPerLevel = 1f; shared.m_equipStatusEffect = null; shared.m_setStatusEffect = null; shared.m_setName = ""; shared.m_damageModifiers = new List<DamageModPair>(); shared.m_movementModifier = 0f; shared.m_eitrRegenModifier = 0f; shared.m_heatResistanceModifier = 0f; shared.m_jumpStaminaModifier = 0f; shared.m_attackStaminaModifier = 0f; shared.m_blockStaminaModifier = 0f; shared.m_dodgeStaminaModifier = 0f; shared.m_swimStaminaModifier = 0f; shared.m_sneakStaminaModifier = 0f; shared.m_runStaminaModifier = 0f; } private void LinkIdols() { ObjectDB instance = ObjectDB.instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } CapeRequirements.Clear(); foreach (Recipe item2 in instance.m_recipes.Where((Recipe r) => Object.op_Implicit((Object)(object)r) && Object.op_Implicit((Object)(object)r.m_item) && IsCape(r.m_item.m_itemData))) { Requirement[] resources = item2.m_resources; foreach (Requirement item in resources) { CapeRequirements.Add(item); } } Requirement[] array = ((IEnumerable<Recipe>)instance.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => Object.op_Implicit((Object)(object)r) && Object.op_Implicit((Object)(object)r.m_item) && ((Object)((Component)r.m_item).gameObject).name == "ArmorIronChest"))?.m_resources.Where((Requirement r) => r.m_upgraderResource).ToArray(); if (array == null || array.Length == 0) { ((BaseUnityPlugin)this).Logger.LogError((object)"Iron armor idol requirement missing; Forge of Potential integration could not be linked."); return; } foreach (Recipe item3 in instance.m_recipes.Where((Recipe r) => Object.op_Implicit((Object)(object)r) && Object.op_Implicit((Object)(object)r.m_item) && IsCape(r.m_item.m_itemData))) { if (!item3.m_resources.Any((Requirement r) => r.m_upgraderResource)) { item3.m_resources = item3.m_resources.Concat(((IEnumerable<Requirement>)array).Select((Func<Requirement, Requirement>)((Requirement r) => new Requirement { m_resItem = r.m_resItem, m_amount = r.m_amount, m_amountPerLevel = r.m_amountPerLevel, m_upgraderResource = true, m_recover = r.m_recover }))).ToArray(); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Linked both capes to the native iron protection idol requirements."); } internal static bool IsCape(ItemData item) { if (!Is(item, "SC_CapeRubberGuck")) { return Is(item, "SC_CapeLeech"); } return true; } internal static bool Is(ItemData item, string id) { if (item != null) { if (!Object.op_Implicit((Object)(object)item.m_dropPrefab) || !(((Object)item.m_dropPrefab).name == id)) { return item.m_shared.m_name == ((id == "SC_CapeRubberGuck") ? "Rubber Guck Cape" : ((id == "SC_CapeLeech") ? "Leech Cape" : "Rubber")); } return true; } return false; } internal static ItemData EquippedCape(Humanoid player) { if (player == null) { return null; } Inventory inventory = player.GetInventory(); if (inventory == null) { return null; } return ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i.m_equipped && IsCape(i))); } } internal static class Rules { internal static int UpgradeCost(int targetLevel) { if (targetLevel < 2 || targetLevel > 5) { return 0; } return 2 << targetLevel - 2; } internal static float ValidMultiplier(float multiplier) { if (!float.IsNaN(multiplier) && !float.IsInfinity(multiplier)) { return Math.Max(0f, multiplier); } return 1f; } internal static float LifestealPercent(int level, float multiplier = 1f) { return (5f + (float)(Math.Max(1, level) - 1) * 2.5f) * ValidMultiplier(multiplier); } internal static float LifestealRate(int level, float multiplier = 1f) { return LifestealPercent(level, multiplier) / 100f; } internal static float HealthLost(float before, float after) { return Math.Max(0f, Math.Min(before, before - after)); } } internal static class TooltipText { internal static string LifestealLine(int level, int previousLevel = 0, float multiplier = 1f) { string text = Rules.LifestealPercent(level, multiplier).ToString("0.##", CultureInfo.InvariantCulture); if (previousLevel > 0 && previousLevel < level) { return "Lifesteal: <color=orange>" + Rules.LifestealPercent(previousLevel, multiplier).ToString("0.##", CultureInfo.InvariantCulture) + "% → " + text + "%</color>"; } return "Lifesteal: <color=orange>" + text + "%</color>"; } internal static string LeechDescription(float multiplier = 1f) { return "Suck the health off your enemies for " + Rules.LifestealPercent(1, multiplier).ToString("0.##", CultureInfo.InvariantCulture) + "% of damage dealt, increasing with each level"; } internal static string InsertAfterWeight(string tooltip, string stats, string translatedWeight) { int num = tooltip.IndexOf("$item_weight", StringComparison.Ordinal); if (num < 0 && !string.IsNullOrEmpty(translatedWeight)) { num = tooltip.IndexOf(translatedWeight + ":", StringComparison.Ordinal); } if (num < 0) { return tooltip + "\n" + stats; } int num2 = tooltip.IndexOf('\n', num); if (num2 >= 0) { return tooltip.Insert(num2, "\n" + stats); } return tooltip + "\n" + stats; } } }