using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyTitle("Piss Ropes")] [assembly: AssemblyDescription("PEAK BepInEx plugin that restores the yellow unplaced rope-spool preview.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Piss Ropes")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f98cebc2-1ce9-4cf7-9ff7-b53f425d9d45")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace Piss_Ropes { [BepInPlugin("tony4twentys.Piss_Ropes", "Piss Ropes", "1.0.0")] [BepInProcess("PEAK.exe")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "tony4twentys.Piss_Ropes"; public const string PluginName = "Piss Ropes"; public const string PluginVersion = "1.0.0"; internal static ConfigEntry EnabledConfig; internal static ConfigEntry PreviewColorConfig; internal static ConfigEntry ApplyToAntiRopeConfig; private Harmony _harmony; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0058: 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 Instance = this; Log = ((BaseUnityPlugin)this).Logger; EnabledConfig = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "When enabled, unplaced rope-spool previews use the yellow color instead of the vanilla blue."); PreviewColorConfig = ((BaseUnityPlugin)this).Config.Bind("General", "PreviewColor", new Color(0.95f, 0.82f, 0.12f, 1f), "Yellow used for the hanging rope while it is still attached to a spool."); ApplyToAntiRopeConfig = ((BaseUnityPlugin)this).Config.Bind("General", "ApplyToAntiRope", true, "Also recolor anti-grav spool previews."); _harmony = new Harmony("tony4twentys.Piss_Ropes"); _harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} loaded.", "Piss Ropes", "1.0.0")); } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } Log = null; } } internal static class GhostRopeColor { private static readonly string[] FallbackTintProperties = new string[11] { "_Color", "_BaseColor", "_Tint", "_Color0", "_Color1", "_Color2", "_Color21", "_Color3", "_Color4", "_TopColor", "_EmissionColor" }; private static bool _loggedOnce; private static bool _loggedError; public static void Apply(RopeBoneVisualizer visualizer) { //IL_008a: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) if (Plugin.EnabledConfig == null || !Plugin.EnabledConfig.Value || (Object)(object)visualizer == (Object)null || (Object)(object)visualizer.ghostMaterial == (Object)null || (!Plugin.ApplyToAntiRopeConfig.Value && IsAntiRope(visualizer))) { return; } Color val = (Color)((Plugin.PreviewColorConfig != null) ? Plugin.PreviewColorConfig.Value : new Color(0.95f, 0.82f, 0.12f, 1f)); Recolor(visualizer.ghostMaterial, val); if (!_loggedOnce) { _loggedOnce = true; Material ghostMaterial = visualizer.ghostMaterial; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)string.Format("Recolored spool preview '{0}' shader '{1}' to {2}.", ((Object)ghostMaterial).name, ((Object)(object)ghostMaterial.shader != (Object)null) ? ((Object)ghostMaterial.shader).name : "null", val)); } } } public static void LogOnce(string message) { if (!_loggedError) { _loggedError = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)message); } } } private static bool IsAntiRope(RopeBoneVisualizer visualizer) { Rope rope = visualizer.rope; if ((Object)(object)rope != (Object)null) { if (rope.antigrav) { return true; } if ((Object)(object)rope.spool != (Object)null) { return rope.spool.isAntiRope; } } return false; } private static void Recolor(Material material, Color yellow) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0087: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty("_VertexGhost")) { material.SetFloat("_VertexGhost", 0f); } Shader shader = material.shader; bool flag = false; if ((Object)(object)shader != (Object)null) { int propertyCount = shader.GetPropertyCount(); for (int i = 0; i < propertyCount; i++) { if ((int)shader.GetPropertyType(i) <= 0) { string propertyName = shader.GetPropertyName(i); if (IsTintProperty(propertyName)) { Color color = material.GetColor(propertyName); material.SetColor(propertyName, MixYellow(yellow, color)); flag = true; } } } } if (flag) { return; } for (int j = 0; j < FallbackTintProperties.Length; j++) { string text = FallbackTintProperties[j]; if (material.HasProperty(text)) { Color color2 = material.GetColor(text); material.SetColor(text, MixYellow(yellow, color2)); } } } private static bool IsTintProperty(string name) { if (string.IsNullOrEmpty(name)) { return false; } if (name.IndexOf("Remap", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Direction", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Offset", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Smoothstep", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Tightness", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("HueShift", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } return name.IndexOf("Color", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Tint", StringComparison.OrdinalIgnoreCase) >= 0; } private static Color MixYellow(Color yellow, Color current) { //IL_0001: 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_000d: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_00af: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(current.r, Mathf.Max(current.g, current.b)); Color result = yellow; result.a = current.a; if (num > 1f) { result.r *= num; result.g *= num; result.b *= num; } else if (num > 0.01f && num < 0.35f) { float num2 = num / 0.35f; result.r *= num2; result.g *= num2; result.b *= num2; } return result; } } [HarmonyPatch(typeof(RopeBoneVisualizer), "Awake")] internal static class RopeBoneVisualizer_Awake_Piss_Patch { private static void Postfix(RopeBoneVisualizer __instance) { try { GhostRopeColor.Apply(__instance); } catch (Exception ex) { GhostRopeColor.LogOnce("Preview recolor skipped: " + ex.Message); } } } }