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;
}
}
}