Decompiled source of LuckyTouch v1.2.1

plugins/LuckyTouch.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using AdvancedREPO.Config;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LuckyTouch")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LuckyTouch")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1450d209-6bd5-4127-ab3d-8d0632c3f5f5")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace LuckyTouch
{
	[BepInPlugin("dyxc666.LuckyTouch", "LuckyTouch", "1.2.1")]
	[BepInProcess("REPO.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class LuckyTouchMod : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <DelayedRefresh>d__38 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public PhysGrabber grabber;

			public LuckyTouchMod <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedRefresh>d__38(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					colorStatesMethod?.Invoke(grabber, null);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private readonly Harmony harmony = new Harmony("dyxc666.LuckyTouch");

		public static ConfigField<bool> EnableLuckSystem;

		public static ConfigField<float> LuckAccumulationRate;

		public static ConfigField<float> LuckDecayRate;

		public static ConfigField<float> LuckMaxDelta;

		public static ConfigField<float> LuckMin;

		public static ConfigField<float> LuckMax;

		public static ConfigField<string> HighLuckColorHex;

		public static ConfigField<string> LowLuckColorHex;

		public static ConfigField<bool> EnableVerboseLogging;

		public static float CurrentLuck = 1f;

		public static float LastMultiplier = 1f;

		internal static Color highLuckColor = Color.green;

		internal static Color lowLuckColor = Color.red;

		private static FieldInfo dollarValueCurrentField;

		private static FieldInfo dollarValueOriginalField;

		private static MethodInfo colorStatesMethod;

		public static ManualLogSource StaticLogger { get; private set; }

		public static LuckyTouchMod Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			StaticLogger = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"=========================================");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"LuckyTouch 模组 v1.2.1 已加载");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"作者: dyxc666");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"=========================================");
			CreateConfigEntries();
			ParseColorConfigs();
			HighLuckColorHex.ValueChanged += delegate
			{
				ParseColorConfigs();
			};
			LowLuckColorHex.ValueChanged += delegate
			{
				ParseColorConfigs();
			};
			try
			{
				InitializeReflection();
				CacheRefreshMethod();
				ApplyHarmonyPatches();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"✅ 模组初始化成功");
				if (EnableVerboseLogging.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"⚙\ufe0f 当前配置:积累={LuckAccumulationRate.Value},衰减={LuckDecayRate.Value},上限={LuckMaxDelta.Value}");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("❌ 模组初始化失败: " + ex.Message));
			}
		}

		private void InitializeReflection()
		{
			dollarValueCurrentField = typeof(ValuableObject).GetField("dollarValueCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			dollarValueOriginalField = typeof(ValuableObject).GetField("dollarValueOriginal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}

		private void CacheRefreshMethod()
		{
			colorStatesMethod = AccessTools.Method(typeof(PhysGrabber), "ColorStates", Type.EmptyTypes, (Type[])null);
			if (colorStatesMethod == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"未能找到 ColorStates 方法,颜色刷新可能不即时");
			}
		}

		private void ParseColorConfigs()
		{
			//IL_001c: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!ColorUtility.TryParseHtmlString(HighLuckColorHex.Value, ref highLuckColor))
			{
				highLuckColor = Color.green;
			}
			if (!ColorUtility.TryParseHtmlString(LowLuckColorHex.Value, ref lowLuckColor))
			{
				lowLuckColor = Color.red;
			}
		}

		private ConfigField<bool> CreateBoolConfig(string section, string key, bool defaultValue, string description, bool sync = true)
		{
			return new ConfigBuilder<bool>("LuckyTouch").File("LuckyTouch.cfg").Section(section).Key(key)
				.Default(defaultValue)
				.Description(description)
				.Range(false, true)
				.Sync(sync)
				.Build();
		}

		private ConfigField<float> CreateFloatConfig(string section, string key, float defaultValue, string description, float min, float max, bool sync = true)
		{
			return new ConfigBuilder<float>("LuckyTouch").File("LuckyTouch.cfg").Section(section).Key(key)
				.Default(defaultValue)
				.Description(description)
				.Range(min, max)
				.Sync(sync)
				.Build();
		}

		private ConfigField<string> CreateStringConfig(string section, string key, string defaultValue, string description, bool sync = true)
		{
			return new ConfigBuilder<string>("LuckyTouch").File("LuckyTouch.cfg").Section(section).Key(key)
				.Default(defaultValue)
				.Description(description)
				.Sync(sync)
				.Build();
		}

		private void CreateConfigEntries()
		{
			EnableLuckSystem = CreateBoolConfig("基础设置", "启用运气系统", defaultValue: true, "总开关");
			LuckAccumulationRate = CreateFloatConfig("平衡参数", "价格_积累比例", 0.03f, "价格变化绝对值计入运气的比例", 0f, 0.5f);
			LuckDecayRate = CreateFloatConfig("平衡参数", "自然衰减比例", 0.15f, "每次抓取后运气值向1.0衰减的比例", 0f, 0.5f);
			LuckMaxDelta = CreateFloatConfig("平衡参数", "单次变化上限", 0.15f, "每次运气值变化的最大绝对值", 0f, 1f);
			LuckMin = CreateFloatConfig("平衡参数", "运气最小值", 0.2f, "允许的最低运气值", 0.1f, 1f);
			LuckMax = CreateFloatConfig("平衡参数", "运气最大值", 2.2f, "允许的最高运气值", 1f, 5f);
			HighLuckColorHex = CreateStringConfig("视觉效果", "高运气颜色", "#00FF00", "涨价时抓取光束颜色 (十六进制)");
			LowLuckColorHex = CreateStringConfig("视觉效果", "低运气颜色", "#FF0000", "跌价时抓取光束颜色 (十六进制)");
			EnableVerboseLogging = CreateBoolConfig("调试", "详细日志输出", defaultValue: false, "输出核心运气变化数据", sync: false);
		}

		private void ApplyHarmonyPatches()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(PhysGrabObject), "GrabStarted", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(GrabPatch).GetMethod("Postfix_GrabStarted")), (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PhysGrabObject), "GrabLink", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(GrabPatch).GetMethod("Postfix_GrabLink")), (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo3 = AccessTools.Method(typeof(PhysGrabber), "ColorStateSetColor", (Type[])null, (Type[])null);
			if (methodInfo3 == null)
			{
				methodInfo3 = AccessTools.Method(typeof(PhysGrabber), "SetBeamColor", (Type[])null, (Type[])null);
			}
			if (methodInfo3 != null)
			{
				harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(BeamColorPatch).GetMethod("Prefix")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"无法找到光束颜色方法!颜色反馈将不可用。");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"✅ 成功应用 Harmony 补丁");
		}

		public static float GetItemPrice(ValuableObject vo)
		{
			return (dollarValueCurrentField != null) ? ((float)dollarValueCurrentField.GetValue(vo)) : 0f;
		}

		public static void SetItemPrice(ValuableObject vo, float newPrice)
		{
			dollarValueCurrentField?.SetValue(vo, newPrice);
			dollarValueOriginalField?.SetValue(vo, newPrice);
		}

		public static PlayerAvatar GetGrabbingPlayer(PhysGrabObject pgo)
		{
			PropertyInfo property = ((object)pgo).GetType().GetProperty("playerAvatar");
			if (property != null)
			{
				object? value = property.GetValue(pgo);
				return (PlayerAvatar)((value is PlayerAvatar) ? value : null);
			}
			FieldInfo field = ((object)pgo).GetType().GetField("playerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				object? value2 = field.GetValue(pgo);
				return (PlayerAvatar)((value2 is PlayerAvatar) ? value2 : null);
			}
			field = ((object)pgo).GetType().GetField("playerGrabbing", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				object? value3 = field.GetValue(pgo);
				return (PlayerAvatar)((value3 is PlayerAvatar) ? value3 : null);
			}
			return null;
		}

		public static void RefreshBeamColor(PhysGrabObject pgo)
		{
			PlayerAvatar grabbingPlayer = GetGrabbingPlayer(pgo);
			if ((Object)(object)grabbingPlayer != (Object)null && (Object)(object)grabbingPlayer.physGrabber != (Object)null && colorStatesMethod != null)
			{
				colorStatesMethod.Invoke(grabbingPlayer.physGrabber, null);
			}
		}

		[IteratorStateMachine(typeof(<DelayedRefresh>d__38))]
		private IEnumerator DelayedRefresh(PhysGrabber grabber)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedRefresh>d__38(0)
			{
				<>4__this = this,
				grabber = grabber
			};
		}

		public void DelayedRefreshBeamColor(PhysGrabber grabber)
		{
			((MonoBehaviour)this).StartCoroutine(DelayedRefresh(grabber));
		}
	}
	[HarmonyPatch]
	public static class GrabPatch
	{
		private static HashSet<int> processedItems = new HashSet<int>();

		public static void Postfix_GrabStarted(PhysGrabObject __instance)
		{
			ProcessGrab(__instance);
		}

		public static void Postfix_GrabLink(PhysGrabObject __instance)
		{
			ProcessGrab(__instance);
		}

		private static void ProcessGrab(PhysGrabObject pgo)
		{
			if (!LuckyTouchMod.EnableLuckSystem.Value)
			{
				return;
			}
			ValuableObject component = ((Component)pgo).GetComponent<ValuableObject>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)((Component)pgo).gameObject).GetInstanceID();
			if (processedItems.Contains(instanceID))
			{
				return;
			}
			float itemPrice = LuckyTouchMod.GetItemPrice(component);
			if (!(itemPrice <= 0f))
			{
				float num = Random.Range(0.5f, 2f);
				float num2 = num * LuckyTouchMod.CurrentLuck;
				float num3 = itemPrice * num2;
				num3 = Mathf.Clamp(num3, 1f, 1000000f);
				LuckyTouchMod.SetItemPrice(component, num3);
				float num4 = Mathf.Abs(num3 - itemPrice);
				float num5 = num4 * LuckyTouchMod.LuckAccumulationRate.Value;
				num5 = Mathf.Clamp(num5, 0f - LuckyTouchMod.LuckMaxDelta.Value, LuckyTouchMod.LuckMaxDelta.Value);
				if (num3 > itemPrice)
				{
					LuckyTouchMod.CurrentLuck += num5;
				}
				else
				{
					LuckyTouchMod.CurrentLuck -= num5;
				}
				float value = LuckyTouchMod.LuckDecayRate.Value;
				LuckyTouchMod.CurrentLuck = Mathf.Lerp(LuckyTouchMod.CurrentLuck, 1f, value);
				LuckyTouchMod.CurrentLuck = Mathf.Clamp(LuckyTouchMod.CurrentLuck, LuckyTouchMod.LuckMin.Value, LuckyTouchMod.LuckMax.Value);
				LuckyTouchMod.LastMultiplier = num2;
				processedItems.Add(instanceID);
				if (LuckyTouchMod.EnableVerboseLogging.Value)
				{
					LuckyTouchMod.StaticLogger.LogInfo((object)$"[运气] 物品: {((Object)pgo).name} | 基础倍率={num:F2} | 最终乘数={num2:F2} | 运气变化={num5:F2} | 当前运气={LuckyTouchMod.CurrentLuck:F2}");
				}
				LuckyTouchMod.RefreshBeamColor(pgo);
				PlayerAvatar grabbingPlayer = LuckyTouchMod.GetGrabbingPlayer(pgo);
				if ((Object)(object)grabbingPlayer != (Object)null && (Object)(object)grabbingPlayer.physGrabber != (Object)null)
				{
					LuckyTouchMod.Instance.DelayedRefreshBeamColor(grabbingPlayer.physGrabber);
				}
			}
		}
	}
	[HarmonyPatch]
	public static class BeamColorPatch
	{
		public static void Prefix(PhysGrabber __instance, ref Color mainColor, ref Color emissionColor)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (LuckyTouchMod.EnableLuckSystem.Value)
			{
				float lastMultiplier = LuckyTouchMod.LastMultiplier;
				if (lastMultiplier > 1f)
				{
					mainColor = LuckyTouchMod.highLuckColor;
					emissionColor = LuckyTouchMod.highLuckColor;
				}
				else if (lastMultiplier < 1f)
				{
					mainColor = LuckyTouchMod.lowLuckColor;
					emissionColor = LuckyTouchMod.lowLuckColor;
				}
			}
		}
	}
}