Decompiled source of LuckOnKill v1.0.2

Luck On Kill.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;
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("Luck On Kill")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Luck On Kill")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2edd8a2b-56c3-4ee0-871e-fa11d76998ec")]
[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 LuckOnKill;

[BepInPlugin("kumo.sulfur.luck_on_kill", "Luck On Kill", "1.0.2")]
public sealed class Plugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> EnableMod;

	internal static ConfigEntry<float> RewardMultiplier;

	internal static ConfigEntry<float> RewardFlatBonus;

	internal static ConfigEntry<float> RewardOverride;

	internal static ConfigEntry<bool> ApplyThroughModifyStatus;

	internal static ConfigEntry<bool> RequireHostileToPlayer;

	internal static ConfigEntry<bool> RewardOnlyExperienceUnits;

	internal static ConfigEntry<bool> RewardCivilians;

	internal static ConfigEntry<bool> RewardBreakables;

	internal static ConfigEntry<bool> PreventDuplicateRewards;

	internal static ConfigEntry<bool> LogRewards;

	private Harmony harmony;

	private const string UnitTypeName = "PerfectRandom.Sulfur.Core.Units.Unit";

	private const string GameManagerTypeName = "PerfectRandom.Sulfur.Core.World.GameManager";

	private const string EntityAttributesTypeName = "PerfectRandom.Sulfur.Core.Stats.EntityAttributes";

	private const int StatLuckGain = 58;

	private const int StatusLuck = 94;

	private static readonly HashSet<int> rewardedUnitIds = new HashSet<int>();

	private void Awake()
	{
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable Luck On Kill.");
		RewardMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Reward", "RewardMultiplier", 1f, "Multiplier for the Luck gained on enemy death. Base reward is current Stat_LuckGain, which equals one minute of vanilla Luck recovery.");
		RewardFlatBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Reward", "RewardFlatBonus", 0f, "Flat bonus added to the kill Luck reward after multiplier.");
		RewardOverride = ((BaseUnityPlugin)this).Config.Bind<float>("Reward", "RewardOverride", -1f, "If >= 0, replaces the kill Luck reward with this fixed value. -1 = disabled.");
		ApplyThroughModifyStatus = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "ApplyThroughModifyStatus", true, "If true, applies Luck through ModifyStatus. This allows Better Luck Control to affect kill rewards too.");
		RequireHostileToPlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "RequireHostileToPlayer", true, "If true, only units hostile to the player grant Luck.");
		RewardOnlyExperienceUnits = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "RewardOnlyExperienceUnits", false, "If true, only units with ExperienceOnKill > 0 grant Luck. Default false allows all hostile enemies, including special 0 XP enemies.");
		RewardCivilians = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "RewardCivilians", false, "If true, civilian units can grant Luck.");
		RewardBreakables = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "RewardBreakables", false, "If true, Breakable units can grant Luck. Recommended false.");
		PreventDuplicateRewards = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "PreventDuplicateRewards", true, "Prevents the same unit death from granting Luck more than once. Object-pool reuse is handled by clearing this state on Unit.Spawn().");
		LogRewards = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogRewards", true, "Log Luck rewards from enemy deaths.");
		harmony = new Harmony("kumo.sulfur.luck_on_kill");
		harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Luck On Kill loaded. Patched Unit.Die().");
	}

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

	internal static void ResetRewardState(object unit)
	{
		if (unit != null)
		{
			int objectId = GetObjectId(unit);
			rewardedUnitIds.Remove(objectId);
		}
	}

	internal static bool ShouldRewardBeforeDeath(object unit)
	{
		if (!EnableMod.Value)
		{
			return false;
		}
		if (unit == null)
		{
			return false;
		}
		if (IsDead(unit))
		{
			return false;
		}
		if (IsPlayerUnit(unit))
		{
			return false;
		}
		if (!RewardBreakables.Value && IsBreakableUnit(unit))
		{
			return false;
		}
		if (!RewardCivilians.Value && IsCivilianUnit(unit))
		{
			return false;
		}
		if (RequireHostileToPlayer.Value)
		{
			bool? flag = IsHostileToPlayer(unit);
			if (flag.HasValue)
			{
				if (!flag.Value)
				{
					return false;
				}
			}
			else
			{
				int intMember = GetIntMember(unit, "ExperienceOnKill", 0);
				if (intMember <= 0)
				{
					return false;
				}
			}
		}
		if (RewardOnlyExperienceUnits.Value)
		{
			int intMember2 = GetIntMember(unit, "ExperienceOnKill", 0);
			if (intMember2 <= 0)
			{
				return false;
			}
		}
		return true;
	}

	internal static void GrantLuckForDeath(object unit)
	{
		if (unit == null)
		{
			return;
		}
		int objectId = GetObjectId(unit);
		if (PreventDuplicateRewards.Value)
		{
			if (rewardedUnitIds.Contains(objectId))
			{
				return;
			}
			rewardedUnitIds.Add(objectId);
			if (rewardedUnitIds.Count > 10000)
			{
				rewardedUnitIds.Clear();
			}
		}
		object playerStats = GetPlayerStats(unit);
		if (playerStats == null)
		{
			if (LogRewards.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[LuckOnKill] Could not find current player stats. Unit=" + GetUnitName(unit)));
				}
			}
			return;
		}
		float attribute = GetAttribute(playerStats, 58);
		if (float.IsNaN(attribute))
		{
			if (LogRewards.Value)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"[LuckOnKill] Could not read Stat_LuckGain.");
				}
			}
			return;
		}
		float num = CalculateReward(attribute);
		if (num <= 0f)
		{
			return;
		}
		float status = GetStatus(playerStats, 94);
		if (ApplyThroughModifyStatus.Value)
		{
			ModifyStatus(playerStats, 94, num);
		}
		else
		{
			SetStatus(playerStats, 94, status + num);
		}
		float status2 = GetStatus(playerStats, 94);
		if (LogRewards.Value)
		{
			ManualLogSource log3 = Log;
			if (log3 != null)
			{
				log3.LogInfo((object)("[LuckOnKill] Unit died: " + GetUnitName(unit) + " | LuckGain=" + attribute.ToString("0.###") + " | Reward=" + num.ToString("0.###") + " | Status_Luck " + status.ToString("0.###") + " -> " + status2.ToString("0.###")));
			}
		}
	}

	private static object GetPlayerStats(object contextUnit)
	{
		object obj = TryGetPlayerStatsFromContextUnit(contextUnit);
		if (obj != null)
		{
			return obj;
		}
		object obj2 = TryGetPlayerStatsFromGameManager();
		if (obj2 != null)
		{
			return obj2;
		}
		object obj3 = TryFindPlayerStatsByScanningUnits();
		if (obj3 != null)
		{
			return obj3;
		}
		return null;
	}

	private static object TryGetPlayerStatsFromContextUnit(object contextUnit)
	{
		if (contextUnit == null)
		{
			return null;
		}
		object member = GetMember(contextUnit, "PlayerUnit");
		if (member == null)
		{
			return null;
		}
		return GetMember(member, "Stats");
	}

	private static object TryGetPlayerStatsFromGameManager()
	{
		object obj = TryGetPlayerUnitFromGameManager();
		if (obj == null)
		{
			return null;
		}
		return GetMember(obj, "Stats");
	}

	private static object TryGetPlayerUnitFromGameManager()
	{
		Type type = FindTypeByFullName("PerfectRandom.Sulfur.Core.World.GameManager");
		if (type == null)
		{
			return null;
		}
		object staticMember = GetStaticMember(type, "Instance");
		if (staticMember == null)
		{
			return null;
		}
		return GetMember(staticMember, "PlayerUnit");
	}

	private static object TryFindPlayerStatsByScanningUnits()
	{
		Type type = FindTypeByFullName("PerfectRandom.Sulfur.Core.Units.Unit");
		if (type == null)
		{
			return null;
		}
		Object[] array;
		try
		{
			array = Object.FindObjectsOfType(type);
		}
		catch
		{
			return null;
		}
		if (array == null)
		{
			return null;
		}
		Object[] array2 = array;
		foreach (Object val in array2)
		{
			if (!(val == (Object)null) && IsPlayerUnit(val))
			{
				object member = GetMember(val, "Stats");
				if (member != null)
				{
					return member;
				}
			}
		}
		return null;
	}

	private static float CalculateReward(float luckGain)
	{
		float value = RewardOverride.Value;
		if (value >= 0f)
		{
			return value;
		}
		float num = luckGain * RewardMultiplier.Value + RewardFlatBonus.Value;
		if (float.IsNaN(num) || float.IsInfinity(num))
		{
			num = 0f;
		}
		return Math.Max(0f, num);
	}

	private static bool? IsHostileToPlayer(object unit)
	{
		if (unit == null)
		{
			return null;
		}
		object playerUnit = TryGetPlayerUnitFromGameManager();
		if (playerUnit == null)
		{
			playerUnit = TryFindPlayerUnitByScanningUnits();
		}
		if (playerUnit == null)
		{
			return null;
		}
		MethodInfo methodInfo = FindInstanceMethod(unit.GetType(), "IsHostileTo", (ParameterInfo[] parameters) => parameters.Length == 1 && parameters[0].ParameterType.IsAssignableFrom(playerUnit.GetType()));
		if (methodInfo == null)
		{
			return null;
		}
		try
		{
			object obj = methodInfo.Invoke(unit, new object[1] { playerUnit });
			if (obj is bool)
			{
				bool value = (bool)obj;
				if (true)
				{
					return value;
				}
			}
		}
		catch
		{
			return null;
		}
		return null;
	}

	private static object TryFindPlayerUnitByScanningUnits()
	{
		Type type = FindTypeByFullName("PerfectRandom.Sulfur.Core.Units.Unit");
		if (type == null)
		{
			return null;
		}
		Object[] array;
		try
		{
			array = Object.FindObjectsOfType(type);
		}
		catch
		{
			return null;
		}
		if (array == null)
		{
			return null;
		}
		Object[] array2 = array;
		foreach (Object val in array2)
		{
			if (!(val == (Object)null) && IsPlayerUnit(val))
			{
				return val;
			}
		}
		return null;
	}

	private static bool IsDead(object unit)
	{
		object member = GetMember(unit, "UnitState");
		if (member == null)
		{
			member = GetMember(unit, "unitState");
		}
		if (member == null)
		{
			return false;
		}
		string text = member.ToString();
		if (text == "Dead")
		{
			return true;
		}
		try
		{
			return Convert.ToInt32(member) == 0;
		}
		catch
		{
			return false;
		}
	}

	private static bool IsPlayerUnit(object unit)
	{
		if (GetBoolMember(unit, "isPlayer", fallback: false))
		{
			return true;
		}
		object member = GetMember(unit, "IsPlayer");
		bool flag = default(bool);
		int num;
		if (member is bool)
		{
			flag = (bool)member;
			num = 1;
		}
		else
		{
			num = 0;
		}
		if (((uint)num & (flag ? 1u : 0u)) != 0)
		{
			return true;
		}
		string unitName = GetUnitName(unit);
		return unitName.Contains("Unit_Player");
	}

	private static bool IsCivilianUnit(object unit)
	{
		if (GetMember(unit, "IsCivilian") is bool result)
		{
			return result;
		}
		return false;
	}

	private static bool IsBreakableUnit(object unit)
	{
		if (unit == null)
		{
			return false;
		}
		Type type = unit.GetType();
		while (type != null)
		{
			if (type.Name == "Breakable" || (type.FullName != null && type.FullName.Contains(".Breakable")))
			{
				return true;
			}
			type = type.BaseType;
		}
		string unitName = GetUnitName(unit);
		return unitName.Contains("Breakable");
	}

	private static string GetUnitName(object unit)
	{
		if (unit == null)
		{
			return "Unknown";
		}
		Object val = (Object)((unit is Object) ? unit : null);
		if (val != (Object)null)
		{
			return val.name;
		}
		return unit.ToString();
	}

	private static int GetObjectId(object obj)
	{
		Object val = (Object)((obj is Object) ? obj : null);
		if (val != (Object)null)
		{
			return val.GetInstanceID();
		}
		return RuntimeHelpers.GetHashCode(obj);
	}

	private static float GetStatus(object stats, int attributeId)
	{
		return InvokeStatsGetter(stats, "GetStatus", attributeId);
	}

	private static float GetAttribute(object stats, int attributeId)
	{
		return InvokeStatsGetter(stats, "GetAttribute", attributeId);
	}

	private static float InvokeStatsGetter(object stats, string methodName, int attributeId)
	{
		if (stats == null)
		{
			return float.NaN;
		}
		Type enumType = FindTypeByFullName("PerfectRandom.Sulfur.Core.Stats.EntityAttributes");
		if (enumType == null)
		{
			return float.NaN;
		}
		object obj = Enum.ToObject(enumType, attributeId);
		MethodInfo methodInfo = FindInstanceMethod(stats.GetType(), methodName, (ParameterInfo[] parameters) => parameters.Length == 1 && parameters[0].ParameterType == enumType);
		if (methodInfo == null)
		{
			return float.NaN;
		}
		try
		{
			object value = methodInfo.Invoke(stats, new object[1] { obj });
			return Convert.ToSingle(value);
		}
		catch
		{
			return float.NaN;
		}
	}

	private static void ModifyStatus(object stats, int statusId, float amount)
	{
		InvokeStatsSetter(stats, "ModifyStatus", statusId, amount);
	}

	private static void SetStatus(object stats, int statusId, float value)
	{
		InvokeStatsSetter(stats, "SetStatus", statusId, value);
	}

	private static void InvokeStatsSetter(object stats, string methodName, int statusId, float value)
	{
		if (stats == null)
		{
			return;
		}
		Type enumType = FindTypeByFullName("PerfectRandom.Sulfur.Core.Stats.EntityAttributes");
		if (enumType == null)
		{
			return;
		}
		object obj = Enum.ToObject(enumType, statusId);
		MethodInfo methodInfo = FindInstanceMethod(stats.GetType(), methodName, (ParameterInfo[] parameters) => parameters.Length >= 2 && parameters[0].ParameterType == enumType && parameters[1].ParameterType == typeof(float));
		if (methodInfo == null)
		{
			if (LogRewards.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[LuckOnKill] Could not find " + methodName + "."));
				}
			}
			return;
		}
		ParameterInfo[] parameters2 = methodInfo.GetParameters();
		object[] array = new object[parameters2.Length];
		array[0] = obj;
		array[1] = value;
		for (int i = 2; i < array.Length; i++)
		{
			Type parameterType = parameters2[i].ParameterType;
			if (parameterType == typeof(bool))
			{
				array[i] = false;
			}
			else if (parameters2[i].HasDefaultValue)
			{
				array[i] = parameters2[i].DefaultValue;
			}
			else
			{
				array[i] = GetDefaultValue(parameterType);
			}
		}
		try
		{
			methodInfo.Invoke(stats, array);
		}
		catch (Exception ex)
		{
			if (LogRewards.Value)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[LuckOnKill] Failed to invoke " + methodName + ": " + ex.GetType().Name + ": " + ex.Message));
				}
			}
		}
	}

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

	private static object GetStaticMember(Type type, string name)
	{
		if (type == null)
		{
			return null;
		}
		Type type2 = type;
		while (type2 != null)
		{
			PropertyInfo property = type2.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
			if (property != null)
			{
				try
				{
					return property.GetValue(null, null);
				}
				catch
				{
					return null;
				}
			}
			FieldInfo field = type2.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
			if (field != null)
			{
				try
				{
					return field.GetValue(null);
				}
				catch
				{
					return null;
				}
			}
			type2 = type2.BaseType;
		}
		return null;
	}

	private static bool GetBoolMember(object obj, string name, bool fallback)
	{
		if (GetMember(obj, name) is bool result)
		{
			return result;
		}
		return fallback;
	}

	private static int GetIntMember(object obj, string name, int fallback)
	{
		object member = GetMember(obj, name);
		if (member == null)
		{
			return fallback;
		}
		try
		{
			return Convert.ToInt32(member);
		}
		catch
		{
			return fallback;
		}
	}

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

	private static MethodInfo FindInstanceMethod(Type type, string methodName, Func<ParameterInfo[], bool> parameterPredicate)
	{
		if (type == null)
		{
			return null;
		}
		Type type2 = type;
		while (type2 != null)
		{
			MethodInfo[] methods = type2.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo[] array = methods;
			foreach (MethodInfo methodInfo in array)
			{
				if (!(methodInfo.Name != methodName))
				{
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameterPredicate(parameters))
					{
						return methodInfo;
					}
				}
			}
			type2 = type2.BaseType;
		}
		return null;
	}

	private static object GetDefaultValue(Type type)
	{
		if (type == null)
		{
			return null;
		}
		if (type.IsValueType)
		{
			return Activator.CreateInstance(type);
		}
		return null;
	}
}
[HarmonyPatch]
internal static class Unit_Spawn_ResetRewardState_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 <unitType>5__1;

		private Assembly[] <>s__2;

		private int <>s__3;

		private Assembly <assembly>5__4;

		private Type[] <types>5__5;

		private Type[] <>s__6;

		private int <>s__7;

		private Type <type>5__8;

		private MethodInfo <method>5__9;

		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()
		{
			<unitType>5__1 = null;
			<>s__2 = null;
			<assembly>5__4 = null;
			<types>5__5 = null;
			<>s__6 = null;
			<type>5__8 = null;
			<method>5__9 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			int num = <>1__state;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				goto IL_015e;
			}
			<>1__state = -1;
			<unitType>5__1 = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Units.Unit");
			if (<unitType>5__1 == null)
			{
				return false;
			}
			<>s__2 = AppDomain.CurrentDomain.GetAssemblies();
			<>s__3 = 0;
			goto IL_01b2;
			IL_017b:
			if (<>s__7 < <>s__6.Length)
			{
				<type>5__8 = <>s__6[<>s__7];
				if (!(<type>5__8 == null) && <unitType>5__1.IsAssignableFrom(<type>5__8))
				{
					<method>5__9 = <type>5__8.GetMethod("Spawn", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(<method>5__9 == null) && !<method>5__9.IsAbstract)
					{
						if (<method>5__9.GetParameters().Length == 0)
						{
							<>2__current = <method>5__9;
							<>1__state = 1;
							return true;
						}
						goto IL_015e;
					}
				}
				goto IL_016d;
			}
			<>s__6 = null;
			<types>5__5 = null;
			<assembly>5__4 = null;
			goto IL_01a4;
			IL_016d:
			<>s__7++;
			goto IL_017b;
			IL_01a4:
			<>s__3++;
			goto IL_01b2;
			IL_01b2:
			if (<>s__3 < <>s__2.Length)
			{
				<assembly>5__4 = <>s__2[<>s__3];
				try
				{
					<types>5__5 = <assembly>5__4.GetTypes();
				}
				catch
				{
					goto IL_01a4;
				}
				<>s__6 = <types>5__5;
				<>s__7 = 0;
				goto IL_017b;
			}
			<>s__2 = null;
			return false;
			IL_015e:
			<method>5__9 = null;
			<type>5__8 = null;
			goto IL_016d;
		}

		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 Postfix(object __instance)
	{
		Plugin.ResetRewardState(__instance);
	}
}
[HarmonyPatch]
internal static class Unit_Die_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 <unitType>5__1;

		private Assembly[] <>s__2;

		private int <>s__3;

		private Assembly <assembly>5__4;

		private Type[] <types>5__5;

		private Type[] <>s__6;

		private int <>s__7;

		private Type <type>5__8;

		private MethodInfo <method>5__9;

		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()
		{
			<unitType>5__1 = null;
			<>s__2 = null;
			<assembly>5__4 = null;
			<types>5__5 = null;
			<>s__6 = null;
			<type>5__8 = null;
			<method>5__9 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			int num = <>1__state;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				goto IL_015e;
			}
			<>1__state = -1;
			<unitType>5__1 = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Units.Unit");
			if (<unitType>5__1 == null)
			{
				return false;
			}
			<>s__2 = AppDomain.CurrentDomain.GetAssemblies();
			<>s__3 = 0;
			goto IL_01b2;
			IL_017b:
			if (<>s__7 < <>s__6.Length)
			{
				<type>5__8 = <>s__6[<>s__7];
				if (!(<type>5__8 == null) && <unitType>5__1.IsAssignableFrom(<type>5__8))
				{
					<method>5__9 = <type>5__8.GetMethod("Die", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(<method>5__9 == null) && !<method>5__9.IsAbstract)
					{
						if (<method>5__9.GetParameters().Length == 0)
						{
							<>2__current = <method>5__9;
							<>1__state = 1;
							return true;
						}
						goto IL_015e;
					}
				}
				goto IL_016d;
			}
			<>s__6 = null;
			<types>5__5 = null;
			<assembly>5__4 = null;
			goto IL_01a4;
			IL_016d:
			<>s__7++;
			goto IL_017b;
			IL_01a4:
			<>s__3++;
			goto IL_01b2;
			IL_01b2:
			if (<>s__3 < <>s__2.Length)
			{
				<assembly>5__4 = <>s__2[<>s__3];
				try
				{
					<types>5__5 = <assembly>5__4.GetTypes();
				}
				catch
				{
					goto IL_01a4;
				}
				<>s__6 = <types>5__5;
				<>s__7 = 0;
				goto IL_017b;
			}
			<>s__2 = null;
			return false;
			IL_015e:
			<method>5__9 = null;
			<type>5__8 = null;
			goto IL_016d;
		}

		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 __instance, out bool __state)
	{
		__state = Plugin.ShouldRewardBeforeDeath(__instance);
	}

	private static void Postfix(object __instance, bool __state)
	{
		if (__state)
		{
			Plugin.GrantLuckForDeath(__instance);
		}
	}
}