Decompiled source of BetterLuckControl v1.0.1

Better Luck Control.dll

Decompiled 2 days 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LuckMonitorPlugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LuckMonitorPlugin")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c6baf2e8-69f6-4b7d-b513-705a60ab6f3d")]
[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 RyukaLabs.Sulfur.LuckTweaks;

[BepInPlugin("ryukalabs.sulfur.lucktweaks", "Luck Tweaks", "1.0.1")]
public class LuckTweaksPlugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	internal static ConfigEntry<float> RecoveryMultiplier;

	internal static ConfigEntry<float> RecoveryFlatBonus;

	internal static ConfigEntry<float> RecoveryOverridePerMinute;

	internal static ConfigEntry<float> ConsumptionMultiplier;

	internal static ConfigEntry<bool> VerboseLogging;

	internal const int StatLuckGain = 58;

	internal const int StatusLuck = 94;

	internal static bool IsTweakingLuckStatus;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		RecoveryMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Luck Recovery", "RecoveryMultiplier", 1f, "Multiplier for positive Status_Luck changes. 1 = vanilla. 2 = double luck recovery.");
		RecoveryFlatBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Luck Recovery", "RecoveryFlatBonus", 0f, "Flat bonus added to every positive Status_Luck recovery tick after multiplier.");
		RecoveryOverridePerMinute = ((BaseUnityPlugin)this).Config.Bind<float>("Luck Recovery", "RecoveryOverridePerMinute", -1f, "If >= 0, replaces each positive Status_Luck recovery tick with this value. -1 = disabled.");
		ConsumptionMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Luck Consumption", "ConsumptionMultiplier", 1f, "Multiplier for negative Status_Luck changes. 1 = vanilla. 0.5 = half cost. 0 = no luck consumption.");
		VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", true, "Print Status_Luck changes to BepInEx log.");
		_harmony = new Harmony("ryukalabs.sulfur.lucktweaks");
		_harmony.PatchAll();
		Log.LogInfo((object)"Luck Tweaks loaded.");
		Log.LogInfo((object)"Watching Status_Luck = 94. Stat_LuckGain = 58.");
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	internal static bool IsStatusLuckArg(object arg)
	{
		int? num = TryExtractAttributeId(arg);
		return num.HasValue && num.Value == 94;
	}

	private static int? TryExtractAttributeId(object arg)
	{
		if (arg == null)
		{
			return null;
		}
		Type type = arg.GetType();
		if (type.IsEnum)
		{
			try
			{
				return Convert.ToInt32(arg);
			}
			catch
			{
				return null;
			}
		}
		if (arg is int value)
		{
			return value;
		}
		if (arg is long num)
		{
			return (int)num;
		}
		string text = arg.ToString();
		if (text == "Status_Luck")
		{
			return 94;
		}
		if (text == "Stat_LuckGain")
		{
			return 58;
		}
		object member = GetMember(arg, "id");
		if (member != null && member != arg)
		{
			int? num2 = TryExtractAttributeId(member);
			if (num2.HasValue)
			{
				return num2.Value;
			}
		}
		object member2 = GetMember(arg, "value");
		if (member2 != null && member2 != arg)
		{
			int? num3 = TryExtractAttributeId(member2);
			if (num3.HasValue)
			{
				return num3.Value;
			}
		}
		try
		{
			return Convert.ToInt32(arg);
		}
		catch
		{
			return null;
		}
	}

	internal static object GetMember(object obj, string name)
	{
		if (obj == null)
		{
			return null;
		}
		Type type = obj.GetType();
		while (type != null)
		{
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				try
				{
					return property.GetValue(obj, null);
				}
				catch
				{
					return null;
				}
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				try
				{
					return field.GetValue(obj);
				}
				catch
				{
					return null;
				}
			}
			type = type.BaseType;
		}
		return null;
	}

	internal static Type FindTypeByFullName(string fullName)
	{
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly assembly in assemblies)
		{
			Type type = assembly.GetType(fullName, throwOnError: false);
			if (type != null)
			{
				return type;
			}
		}
		return null;
	}
}
[HarmonyPatch]
internal static class EntityStats_ModifyStatus_Patch
{
	[CompilerGenerated]
	private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private MethodBase <>2__current;

		private int <>l__initialThreadId;

		private Type <type>5__1;

		private MethodInfo[] <>s__2;

		private int <>s__3;

		private MethodInfo <method>5__4;

		private ParameterInfo[] <parameters>5__5;

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

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

		[DebuggerHidden]
		public <TargetMethods>d__0(int <>1__state)
		{
			this.<>1__state = <>1__state;
			<>l__initialThreadId = Environment.CurrentManagedThreadId;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<type>5__1 = null;
			<>s__2 = null;
			<method>5__4 = null;
			<parameters>5__5 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			int num = <>1__state;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				goto IL_00ef;
			}
			<>1__state = -1;
			<type>5__1 = LuckTweaksPlugin.FindTypeByFullName("PerfectRandom.Sulfur.Core.Stats.EntityStats");
			if (<type>5__1 == null)
			{
				return false;
			}
			<>s__2 = <type>5__1.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			<>s__3 = 0;
			goto IL_010c;
			IL_00fe:
			<>s__3++;
			goto IL_010c;
			IL_00ef:
			<parameters>5__5 = null;
			<method>5__4 = null;
			goto IL_00fe;
			IL_010c:
			if (<>s__3 < <>s__2.Length)
			{
				<method>5__4 = <>s__2[<>s__3];
				if (<method>5__4.Name != "ModifyStatus")
				{
					goto IL_00fe;
				}
				<parameters>5__5 = <method>5__4.GetParameters();
				if (<parameters>5__5.Length >= 2 && <parameters>5__5[1].ParameterType == typeof(float))
				{
					<>2__current = <method>5__4;
					<>1__state = 1;
					return true;
				}
				goto IL_00ef;
			}
			<>s__2 = 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();
		}

		[DebuggerHidden]
		IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
		{
			if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
			{
				<>1__state = 0;
				return this;
			}
			return new <TargetMethods>d__0(0);
		}

		[DebuggerHidden]
		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<MethodBase>)this).GetEnumerator();
		}
	}

	[IteratorStateMachine(typeof(<TargetMethods>d__0))]
	private static IEnumerable<MethodBase> TargetMethods()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <TargetMethods>d__0(-2);
	}

	private static void Prefix(object __0, ref float __1, out bool __state)
	{
		__state = false;
		if (!LuckTweaksPlugin.IsStatusLuckArg(__0) || LuckTweaksPlugin.IsTweakingLuckStatus)
		{
			return;
		}
		LuckTweaksPlugin.IsTweakingLuckStatus = true;
		__state = true;
		float num = __1;
		float num2 = num;
		if (num > 0f)
		{
			float value = LuckTweaksPlugin.RecoveryOverridePerMinute.Value;
			num2 = ((!(value >= 0f)) ? (num * LuckTweaksPlugin.RecoveryMultiplier.Value + LuckTweaksPlugin.RecoveryFlatBonus.Value) : value);
			if (num2 < 0f)
			{
				num2 = 0f;
			}
		}
		else if (num < 0f)
		{
			float num3 = LuckTweaksPlugin.ConsumptionMultiplier.Value;
			if (num3 < 0f)
			{
				num3 = 0f;
			}
			num2 = num * num3;
		}
		__1 = num2;
		if (LuckTweaksPlugin.VerboseLogging.Value)
		{
			LuckTweaksPlugin.Log.LogInfo((object)$"[LuckTweaks] Status_Luck delta changed: {num:0.###} -> {num2:0.###}");
		}
	}

	private static void Postfix(bool __state)
	{
		if (__state)
		{
			LuckTweaksPlugin.IsTweakingLuckStatus = false;
		}
	}
}