Decompiled source of RerollNoBreak v4.0.0

RerollNoBreak.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJP.RerollNoBreak
{
	[BepInPlugin("REPOJP.RerollNoBreak", "RerollNoBreak", "1.0.3")]
	public sealed class RerollNoBreakPlugin : BaseUnityPlugin
	{
		private sealed class StandState
		{
			public int ActualRerollCount;
		}

		[HarmonyPatch]
		private static class RerollCostPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.PropertyGetter(upgradeStandType, "RerollCost");
			}

			[HarmonyPostfix]
			private static void Postfix(object __instance, ref int __result)
			{
				try
				{
					if (IsEnabled())
					{
						__result = CalculateCost(__instance);
					}
				}
				catch (Exception ex)
				{
					LogWarning("Failure: RerollCostPostfix\n" + ex);
				}
			}
		}

		[HarmonyPatch]
		private static class StartPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "Start", (Type[])null, (Type[])null);
			}

			[HarmonyPostfix]
			private static void Postfix(object __instance)
			{
				try
				{
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
				}
				catch (Exception ex)
				{
					LogWarning("Failure: StartPostfix\n" + ex);
				}
			}
		}

		[HarmonyPatch]
		private static class OnClickPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "OnClick", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static void Prefix(object __instance)
			{
				try
				{
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
					ForceIdleIfBroken(__instance);
				}
				catch (Exception ex)
				{
					LogWarning("Failure: OnClickPrefix\n" + ex);
				}
			}
		}

		[HarmonyPatch]
		private static class StatePressPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "StatePress", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static void Prefix(object __instance)
			{
				try
				{
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
				}
				catch (Exception ex)
				{
					LogWarning("Failure: StatePressPrefix\n" + ex);
				}
			}
		}

		[HarmonyPatch]
		private static class StatePressSucceedPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "StatePressSucceed", (Type[])null, (Type[])null);
			}

			[HarmonyPrefix]
			private static void Prefix(object __instance, ref bool __state)
			{
				try
				{
					__state = GetBool(stateStartField, __instance);
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
				}
				catch (Exception ex)
				{
					__state = false;
					LogWarning("Failure: StatePressSucceedPrefix\n" + ex);
				}
			}

			[HarmonyPostfix]
			private static void Postfix(object __instance, bool __state)
			{
				try
				{
					if (IsEnabled())
					{
						if (__state && IsHostOrSingleplayer())
						{
							StandState standState = GetStandState(__instance);
							standState.ActualRerollCount++;
						}
						ApplySafeCounters(__instance, sync: true);
						RepairBrokenVisuals(__instance);
					}
				}
				catch (Exception ex)
				{
					LogWarning("Failure: StatePressSucceedPostfix\n" + ex);
				}
			}
		}

		[HarmonyPatch]
		private static class StateRerollRollEndPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "StateRerollRollEnd", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static void Prefix(object __instance)
			{
				try
				{
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
				}
				catch (Exception ex)
				{
					LogWarning("Failure: StateRerollRollEndPrefix\n" + ex);
				}
			}
		}

		[HarmonyPatch]
		private static class StateRerollOpenHatchPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "StateRerollOpenHatch", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static void Prefix(object __instance)
			{
				try
				{
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
				}
				catch (Exception ex)
				{
					LogWarning("Failure: StateRerollOpenHatchPrefix\n" + ex);
				}
			}
		}

		[HarmonyPatch]
		private static class TriggerButtonBreakPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "TriggerButtonBreak", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static bool Prefix(object __instance)
			{
				try
				{
					if (!IsEnabled() || !cfgDisableRerollBreak.Value)
					{
						return true;
					}
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
					return false;
				}
				catch (Exception ex)
				{
					LogWarning("Failure: TriggerButtonBreakPrefix\n" + ex);
					return true;
				}
			}
		}

		[HarmonyPatch]
		private static class SetBrokenPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "SetBroken", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static bool Prefix(object __instance)
			{
				try
				{
					if (!IsEnabled() || !cfgDisableRerollBreak.Value)
					{
						return true;
					}
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
					ForceIdleIfBroken(__instance);
					return false;
				}
				catch (Exception ex)
				{
					LogWarning("Failure: SetBrokenPrefix\n" + ex);
					return true;
				}
			}
		}

		[HarmonyPatch]
		private static class SetBrokenRpcPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "SetBrokenRPC", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static bool Prefix(object __instance)
			{
				try
				{
					if (!IsEnabled() || !cfgDisableRerollBreak.Value)
					{
						return true;
					}
					ApplySafeCounters(__instance, sync: false);
					RepairBrokenVisuals(__instance);
					ForceIdleIfBroken(__instance);
					return false;
				}
				catch (Exception ex)
				{
					LogWarning("Failure: SetBrokenRPCPrefix\n" + ex);
					return true;
				}
			}
		}

		[HarmonyPatch]
		private static class StateBrokenPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "StateBroken", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static bool Prefix(object __instance)
			{
				try
				{
					if (!IsEnabled() || !cfgDisableRerollBreak.Value)
					{
						return true;
					}
					ApplySafeCounters(__instance, sync: true);
					RepairBrokenVisuals(__instance);
					ForceIdleIfBroken(__instance);
					return false;
				}
				catch (Exception ex)
				{
					LogWarning("Failure: StateBrokenPrefix\n" + ex);
					return true;
				}
			}
		}

		[HarmonyPatch]
		private static class UpdateFirePatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "UpdateFire", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(700)]
			[HarmonyPrefix]
			private static bool Prefix(object __instance)
			{
				try
				{
					if (!IsEnabled() || !cfgDisableRerollBreak.Value)
					{
						return true;
					}
					if (GetBool(fireActiveField, __instance))
					{
						RepairBrokenVisuals(__instance);
						return false;
					}
				}
				catch (Exception ex)
				{
					LogWarning("Failure: UpdateFirePrefix\n" + ex);
				}
				return true;
			}
		}

		[HarmonyPatch]
		private static class StateIdlePatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "StateIdle", (Type[])null, (Type[])null);
			}

			[HarmonyPostfix]
			private static void Postfix(object __instance)
			{
				try
				{
					ApplySafeCounters(__instance, sync: false);
					RepairBrokenVisuals(__instance);
				}
				catch (Exception ex)
				{
					LogWarning("Failure: StateIdlePostfix\n" + ex);
				}
			}
		}

		[HarmonyPatch]
		private static class HandleCostDisplayPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(upgradeStandType, "HandleCostDisplay", (Type[])null, (Type[])null);
			}

			[HarmonyPostfix]
			private static void Postfix(object __instance)
			{
				try
				{
					SetCustomHoverText(__instance);
				}
				catch (Exception ex)
				{
					LogWarning("Failure: HandleCostDisplayPostfix\n" + ex);
				}
			}
		}

		public const string PluginGuid = "REPOJP.RerollNoBreak";

		public const string PluginName = "RerollNoBreak";

		public const string PluginVersion = "1.0.3";

		private static RerollNoBreakPlugin instance;

		private static ManualLogSource log;

		private Harmony harmony;

		private static ConfigEntry<bool> cfgEnable;

		private static ConfigEntry<bool> cfgShowDebugLog;

		private static ConfigEntry<bool> cfgDisableRerollBreak;

		private static ConfigEntry<bool> cfgInfiniteReroll;

		private static ConfigEntry<bool> cfgOverrideMaxRerollCount;

		private static ConfigEntry<int> cfgMaxRerollCount;

		private static ConfigEntry<bool> cfgEnableCostCap;

		private static ConfigEntry<int> cfgBaseCost;

		private static ConfigEntry<int> cfgCostIncrease;

		private static ConfigEntry<int> cfgMaxCost;

		private static ConfigEntry<bool> cfgDisableCostIncrease;

		private static ConfigEntry<bool> cfgFirstRerollFree;

		private static ConfigEntry<bool> cfgShowInfiniteRerollText;

		private static Type upgradeStandType;

		private static Type semiFuncType;

		private static MethodInfo semiFuncIsMasterClientOrSingleplayerMethod;

		private static MethodInfo semiFuncDollarGetStringMethod;

		private static MethodInfo syncRerollCountMethod;

		private static MethodInfo syncMaxRerollCountMethod;

		private static MethodInfo resetBuildUpVisualsMethod;

		private static FieldInfo rerollCountField;

		private static FieldInfo maxRerollCountField;

		private static FieldInfo isBrokenField;

		private static FieldInfo stateStartField;

		private static FieldInfo currentStateField;

		private static FieldInfo breakSequenceTriggeredField;

		private static FieldInfo buildUpActiveField;

		private static FieldInfo skipBrokenIntroFxField;

		private static FieldInfo fireActiveField;

		private static FieldInfo buttonGrabObjectField;

		private static FieldInfo buttonField;

		private static FieldInfo buttonRendererField;

		private static FieldInfo buttonNormalMaterialField;

		private static FieldInfo buttonRubbleField;

		private static FieldInfo fireHurtColliderField;

		private static FieldInfo fireLightField;

		private static FieldInfo particleFireLoopField;

		private static FieldInfo buildUpParticlesField;

		private static FieldInfo buildUpLightField;

		private static FieldInfo soundBuildUpLoopField;

		private static readonly Dictionary<int, StandState> standStates = new Dictionary<int, StandState>();

		private void Awake()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			try
			{
				instance = this;
				log = ((BaseUnityPlugin)this).Logger;
				if ((Object)(object)((Component)this).transform.parent != (Object)null)
				{
					((Component)this).transform.SetParent((Transform)null);
				}
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				BindConfig();
				InitializeReflection();
				harmony = new Harmony("REPOJP.RerollNoBreak");
				PatchAllSafely();
				log.LogInfo((object)"RerollNoBreak v1.0.3 loaded.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Awake\n" + ex));
			}
		}

		private void OnDestroy()
		{
			try
			{
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch (Exception ex)
			{
				if (log != null)
				{
					log.LogError((object)("Failure: OnDestroy\n" + ex));
				}
			}
		}

		private void BindConfig()
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			cfgEnable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable", true, "Enable this mod.このMODを有効化します");
			cfgShowDebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowDebugLog", false, "Show detailed debug logs.詳細デバッグログを表示します");
			cfgDisableRerollBreak = ((BaseUnityPlugin)this).Config.Bind<bool>("Break", "DisableRerollBreak", true, "Prevent the Upgrade Reroller from breaking.Upgrade Rerollerの破損を防止します");
			cfgInfiniteReroll = ((BaseUnityPlugin)this).Config.Bind<bool>("Break", "InfiniteReroll", true, "Disable the reroll limit by forcing the internal maximum count to 0.内部最大回数を0にしてリロール上限を無効化します");
			cfgOverrideMaxRerollCount = ((BaseUnityPlugin)this).Config.Bind<bool>("Break", "OverrideMaxRerollCount", true, "Override the vanilla random maximum reroll count.バニラのランダム最大リロール回数を上書きします");
			cfgMaxRerollCount = ((BaseUnityPlugin)this).Config.Bind<int>("Break", "MaxRerollCount", 999, new ConfigDescription("Maximum reroll count used when InfiniteReroll is disabled.InfiniteReroll無効時に使用する最大リロール回数です", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 9999), Array.Empty<object>()));
			cfgEnableCostCap = ((BaseUnityPlugin)this).Config.Bind<bool>("Cost", "EnableCostCap", true, "Cap the reroll cost at MaxCost.リロール費用をMaxCostで上限固定します");
			cfgBaseCost = ((BaseUnityPlugin)this).Config.Bind<int>("Cost", "BaseCost", 5, new ConfigDescription("Base reroll cost in K dollars.基本リロール費用です(Kドル単位)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999), Array.Empty<object>()));
			cfgCostIncrease = ((BaseUnityPlugin)this).Config.Bind<int>("Cost", "CostIncrease", 5, new ConfigDescription("Cost increase per successful reroll in K dollars.成功リロール1回ごとの費用上昇量です(Kドル単位)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999), Array.Empty<object>()));
			cfgMaxCost = ((BaseUnityPlugin)this).Config.Bind<int>("Cost", "MaxCost", 30, new ConfigDescription("Maximum reroll cost in K dollars.最大リロール費用です(Kドル単位)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999), Array.Empty<object>()));
			cfgDisableCostIncrease = ((BaseUnityPlugin)this).Config.Bind<bool>("Cost", "DisableCostIncrease", false, "Keep the reroll cost fixed at BaseCost.リロール費用をBaseCostで固定します");
			cfgFirstRerollFree = ((BaseUnityPlugin)this).Config.Bind<bool>("Cost", "FirstRerollFree", false, "Make the first successful reroll on each stand free.各リロール台の初回成功リロールを無料化します");
			cfgShowInfiniteRerollText = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowInfiniteRerollText", true, "Show custom reroll count and cost text on the button hover text.ボタンホバーテキストに独自の回数と費用を表示します");
		}

		private void InitializeReflection()
		{
			upgradeStandType = AccessTools.TypeByName("UpgradeStand");
			semiFuncType = AccessTools.TypeByName("SemiFunc");
			if (semiFuncType != null)
			{
				semiFuncIsMasterClientOrSingleplayerMethod = AccessTools.Method(semiFuncType, "IsMasterClientOrSingleplayer", (Type[])null, (Type[])null);
				semiFuncDollarGetStringMethod = AccessTools.Method(semiFuncType, "DollarGetString", new Type[1] { typeof(int) }, (Type[])null);
			}
			if (upgradeStandType == null)
			{
				LogWarning("UpgradeStand type was not found. RerollNoBreak patches were not applied.");
				return;
			}
			rerollCountField = AccessTools.Field(upgradeStandType, "rerollCount");
			maxRerollCountField = AccessTools.Field(upgradeStandType, "maxRerollCount");
			isBrokenField = AccessTools.Field(upgradeStandType, "isBroken");
			stateStartField = AccessTools.Field(upgradeStandType, "stateStart");
			currentStateField = AccessTools.Field(upgradeStandType, "currentState");
			breakSequenceTriggeredField = AccessTools.Field(upgradeStandType, "breakSequenceTriggered");
			buildUpActiveField = AccessTools.Field(upgradeStandType, "buildUpActive");
			skipBrokenIntroFxField = AccessTools.Field(upgradeStandType, "skipBrokenIntroFX");
			fireActiveField = AccessTools.Field(upgradeStandType, "fireActive");
			buttonGrabObjectField = AccessTools.Field(upgradeStandType, "buttonGrabObject");
			buttonField = AccessTools.Field(upgradeStandType, "button");
			buttonRendererField = AccessTools.Field(upgradeStandType, "buttonRenderer");
			buttonNormalMaterialField = AccessTools.Field(upgradeStandType, "buttonNormalMaterial");
			buttonRubbleField = AccessTools.Field(upgradeStandType, "buttonRubble");
			fireHurtColliderField = AccessTools.Field(upgradeStandType, "fireHurtCollider");
			fireLightField = AccessTools.Field(upgradeStandType, "fireLight");
			particleFireLoopField = AccessTools.Field(upgradeStandType, "particleFireLoop");
			buildUpParticlesField = AccessTools.Field(upgradeStandType, "buildUpParticles");
			buildUpLightField = AccessTools.Field(upgradeStandType, "buildUpLight");
			soundBuildUpLoopField = AccessTools.Field(upgradeStandType, "soundBuildUpLoop");
			syncRerollCountMethod = AccessTools.Method(upgradeStandType, "SyncRerollCount", (Type[])null, (Type[])null);
			syncMaxRerollCountMethod = AccessTools.Method(upgradeStandType, "SyncMaxRerollCount", (Type[])null, (Type[])null);
			resetBuildUpVisualsMethod = AccessTools.Method(upgradeStandType, "ResetBuildUpVisuals", (Type[])null, (Type[])null);
		}

		private void PatchAllSafely()
		{
			if (!(upgradeStandType == null))
			{
				TryPatchClass(typeof(RerollCostPatch));
				TryPatchClass(typeof(StartPatch));
				TryPatchClass(typeof(OnClickPatch));
				TryPatchClass(typeof(StatePressPatch));
				TryPatchClass(typeof(StatePressSucceedPatch));
				TryPatchClass(typeof(StateRerollRollEndPatch));
				TryPatchClass(typeof(StateRerollOpenHatchPatch));
				TryPatchClass(typeof(TriggerButtonBreakPatch));
				TryPatchClass(typeof(SetBrokenPatch));
				TryPatchClass(typeof(SetBrokenRpcPatch));
				TryPatchClass(typeof(StateBrokenPatch));
				TryPatchClass(typeof(UpdateFirePatch));
				TryPatchClass(typeof(StateIdlePatch));
				TryPatchClass(typeof(HandleCostDisplayPatch));
			}
		}

		private void TryPatchClass(Type patchType)
		{
			try
			{
				MethodInfo methodInfo = AccessTools.Method(patchType, "TargetMethod", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					LogWarning("Patch target resolver was not found: " + patchType.Name);
					return;
				}
				MethodBase methodBase = methodInfo.Invoke(null, null) as MethodBase;
				if (methodBase == null)
				{
					LogWarning("Patch target was not found: " + patchType.Name);
					return;
				}
				harmony.CreateClassProcessor(patchType).Patch();
				LogDebug("Patched: " + patchType.Name + " -> " + methodBase.Name);
			}
			catch (Exception ex)
			{
				LogWarning("Failure: Patch " + patchType.Name + "\n" + ex);
			}
		}

		private static bool IsEnabled()
		{
			if (cfgEnable != null)
			{
				return cfgEnable.Value;
			}
			return false;
		}

		private static bool IsHostOrSingleplayer()
		{
			try
			{
				if (semiFuncIsMasterClientOrSingleplayerMethod == null)
				{
					return true;
				}
				object obj = semiFuncIsMasterClientOrSingleplayerMethod.Invoke(null, null);
				if (obj is bool)
				{
					return (bool)obj;
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failure: IsHostOrSingleplayer\n" + ex);
			}
			return true;
		}

		private static StandState GetStandState(object stand)
		{
			int hashCode = stand.GetHashCode();
			if (!standStates.TryGetValue(hashCode, out var value))
			{
				value = new StandState();
				standStates[hashCode] = value;
			}
			return value;
		}

		private static int CalculateCost(object stand)
		{
			StandState standState = GetStandState(stand);
			if (cfgFirstRerollFree.Value && standState.ActualRerollCount <= 0)
			{
				return 0;
			}
			int num = cfgBaseCost.Value;
			if (!cfgDisableCostIncrease.Value)
			{
				num += standState.ActualRerollCount * cfgCostIncrease.Value;
			}
			if (cfgEnableCostCap.Value)
			{
				num = Mathf.Min(num, cfgMaxCost.Value);
			}
			return Mathf.Max(0, num);
		}

		private static void ApplySafeCounters(object stand, bool sync)
		{
			try
			{
				if (!IsEnabled())
				{
					return;
				}
				if (cfgInfiniteReroll.Value)
				{
					SetInt(maxRerollCountField, stand, 0);
				}
				else if (cfgOverrideMaxRerollCount.Value)
				{
					int num = Mathf.Clamp(cfgMaxRerollCount.Value, 1, 9999);
					SetInt(maxRerollCountField, stand, num);
					int @int = GetInt(rerollCountField, stand);
					if (@int >= num)
					{
						SetInt(rerollCountField, stand, Mathf.Max(0, num - 1));
					}
				}
				if (sync && IsHostOrSingleplayer())
				{
					InvokeMethod(syncMaxRerollCountMethod, stand);
					InvokeMethod(syncRerollCountMethod, stand);
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failure: ApplySafeCounters\n" + ex);
			}
		}

		private static void RepairBrokenVisuals(object stand)
		{
			try
			{
				if (!IsEnabled() || !cfgDisableRerollBreak.Value)
				{
					return;
				}
				SetBool(isBrokenField, stand, value: false);
				SetBool(breakSequenceTriggeredField, stand, value: false);
				SetBool(buildUpActiveField, stand, value: false);
				SetBool(skipBrokenIntroFxField, stand, value: false);
				SetBool(fireActiveField, stand, value: false);
				InvokeMethod(resetBuildUpVisualsMethod, stand);
				StopParticle(buildUpParticlesField, stand);
				StopParticle(particleFireLoopField, stand);
				StopSound(soundBuildUpLoopField, stand);
				SetGameObjectActive(buttonGrabObjectField, stand, active: true);
				SetTransformGameObjectActive(buttonField, stand, active: true);
				SetGameObjectActive(buttonRubbleField, stand, active: false);
				SetGameObjectActive(fireHurtColliderField, stand, active: false);
				SetLightActive(fireLightField, stand, active: false);
				object fieldValue = GetFieldValue(buttonRendererField, stand);
				MeshRenderer val = (MeshRenderer)((fieldValue is MeshRenderer) ? fieldValue : null);
				if ((Object)(object)val != (Object)null)
				{
					((Renderer)val).enabled = true;
					object fieldValue2 = GetFieldValue(buttonNormalMaterialField, stand);
					Material val2 = (Material)((fieldValue2 is Material) ? fieldValue2 : null);
					if ((Object)(object)val2 != (Object)null)
					{
						((Renderer)val).material = val2;
					}
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failure: RepairBrokenVisuals\n" + ex);
			}
		}

		private static void ForceIdleIfBroken(object stand)
		{
			try
			{
				if (IsEnabled() && cfgDisableRerollBreak.Value)
				{
					bool @bool = GetBool(isBrokenField, stand);
					object fieldValue = GetFieldValue(currentStateField, stand);
					int enumInt = GetEnumInt(fieldValue);
					if (@bool || enumInt == 11)
					{
						SetEnumByInt(currentStateField, stand, 0);
						SetBool(stateStartField, stand, value: true);
						RepairBrokenVisuals(stand);
					}
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failure: ForceIdleIfBroken\n" + ex);
			}
		}

		private static void SetCustomHoverText(object stand)
		{
			try
			{
				if (!IsEnabled() || !cfgShowInfiniteRerollText.Value)
				{
					return;
				}
				object fieldValue = GetFieldValue(buttonGrabObjectField, stand);
				if (fieldValue != null)
				{
					int num = CalculateCost(stand);
					string text;
					if (cfgInfiniteReroll.Value)
					{
						text = "<color=#00FFFF>∞</color>";
					}
					else
					{
						int @int = GetInt(rerollCountField, stand);
						int int2 = GetInt(maxRerollCountField, stand);
						text = @int + "/" + int2;
					}
					string text2 = ((num <= 0) ? "<color=#00FF00>FREE</color>" : ("<color=#FF0000>-$" + FormatDollars(num) + "K</color>"));
					string value = "HOLD TO REROLL (" + text + " / " + text2 + ")";
					FieldInfo fieldInfo = AccessTools.Field(fieldValue.GetType(), "hoverText");
					if (fieldInfo != null)
					{
						fieldInfo.SetValue(fieldValue, value);
					}
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failure: SetCustomHoverText\n" + ex);
			}
		}

		private static string FormatDollars(int value)
		{
			try
			{
				if (semiFuncDollarGetStringMethod != null)
				{
					object obj = semiFuncDollarGetStringMethod.Invoke(null, new object[1] { value });
					if (obj != null)
					{
						return obj.ToString();
					}
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failure: FormatDollars\n" + ex);
			}
			return value.ToString();
		}

		private static int GetInt(FieldInfo field, object target)
		{
			object fieldValue = GetFieldValue(field, target);
			if (fieldValue is int)
			{
				return (int)fieldValue;
			}
			return 0;
		}

		private static bool GetBool(FieldInfo field, object target)
		{
			object fieldValue = GetFieldValue(field, target);
			if (fieldValue is bool)
			{
				return (bool)fieldValue;
			}
			return false;
		}

		private static object GetFieldValue(FieldInfo field, object target)
		{
			if (field == null || target == null)
			{
				return null;
			}
			return field.GetValue(target);
		}

		private static void SetInt(FieldInfo field, object target, int value)
		{
			if (field != null && target != null)
			{
				field.SetValue(target, value);
			}
		}

		private static void SetBool(FieldInfo field, object target, bool value)
		{
			if (field != null && target != null)
			{
				field.SetValue(target, value);
			}
		}

		private static void SetEnumByInt(FieldInfo field, object target, int value)
		{
			if (!(field == null) && target != null)
			{
				object value2 = Enum.ToObject(field.FieldType, value);
				field.SetValue(target, value2);
			}
		}

		private static int GetEnumInt(object value)
		{
			if (value == null)
			{
				return -1;
			}
			return Convert.ToInt32(value);
		}

		private static void InvokeMethod(MethodInfo method, object target)
		{
			if (method != null && target != null)
			{
				method.Invoke(target, null);
			}
		}

		private static void SetGameObjectActive(FieldInfo field, object target, bool active)
		{
			object fieldValue = GetFieldValue(field, target);
			if (fieldValue == null)
			{
				return;
			}
			GameObject val = (GameObject)((fieldValue is GameObject) ? fieldValue : null);
			if ((Object)(object)val != (Object)null)
			{
				val.SetActive(active);
				return;
			}
			Component val2 = (Component)((fieldValue is Component) ? fieldValue : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.gameObject != (Object)null)
			{
				val2.gameObject.SetActive(active);
			}
		}

		private static void SetTransformGameObjectActive(FieldInfo field, object target, bool active)
		{
			object fieldValue = GetFieldValue(field, target);
			Transform val = (Transform)((fieldValue is Transform) ? fieldValue : null);
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null)
			{
				((Component)val).gameObject.SetActive(active);
			}
		}

		private static void SetLightActive(FieldInfo field, object target, bool active)
		{
			object fieldValue = GetFieldValue(field, target);
			Light val = (Light)((fieldValue is Light) ? fieldValue : null);
			if ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)((Component)val).gameObject != (Object)null)
				{
					((Component)val).gameObject.SetActive(active);
				}
				((Behaviour)val).enabled = active;
				if (!active)
				{
					val.intensity = 0f;
				}
			}
		}

		private static void StopParticle(FieldInfo field, object target)
		{
			object fieldValue = GetFieldValue(field, target);
			ParticleSystem val = (ParticleSystem)((fieldValue is ParticleSystem) ? fieldValue : null);
			if ((Object)(object)val != (Object)null)
			{
				val.Stop(true);
			}
		}

		private static void StopSound(FieldInfo field, object target)
		{
			object fieldValue = GetFieldValue(field, target);
			if (fieldValue != null)
			{
				MethodInfo methodInfo = AccessTools.Method(fieldValue.GetType(), "Stop", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(fieldValue, null);
				}
			}
		}

		private static void LogDebug(string message)
		{
			if (cfgShowDebugLog != null && cfgShowDebugLog.Value && log != null)
			{
				log.LogInfo((object)message);
			}
		}

		private static void LogWarning(string message)
		{
			if (log != null)
			{
				log.LogWarning((object)message);
			}
		}
	}
}