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 cfgEnable; private static ConfigEntry cfgShowDebugLog; private static ConfigEntry cfgDisableRerollBreak; private static ConfigEntry cfgInfiniteReroll; private static ConfigEntry cfgOverrideMaxRerollCount; private static ConfigEntry cfgMaxRerollCount; private static ConfigEntry cfgEnableCostCap; private static ConfigEntry cfgBaseCost; private static ConfigEntry cfgCostIncrease; private static ConfigEntry cfgMaxCost; private static ConfigEntry cfgDisableCostIncrease; private static ConfigEntry cfgFirstRerollFree; private static ConfigEntry 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 standStates = new Dictionary(); 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("General", "Enable", true, "Enable this mod.このMODを有効化します"); cfgShowDebugLog = ((BaseUnityPlugin)this).Config.Bind("General", "ShowDebugLog", false, "Show detailed debug logs.詳細デバッグログを表示します"); cfgDisableRerollBreak = ((BaseUnityPlugin)this).Config.Bind("Break", "DisableRerollBreak", true, "Prevent the Upgrade Reroller from breaking.Upgrade Rerollerの破損を防止します"); cfgInfiniteReroll = ((BaseUnityPlugin)this).Config.Bind("Break", "InfiniteReroll", true, "Disable the reroll limit by forcing the internal maximum count to 0.内部最大回数を0にしてリロール上限を無効化します"); cfgOverrideMaxRerollCount = ((BaseUnityPlugin)this).Config.Bind("Break", "OverrideMaxRerollCount", true, "Override the vanilla random maximum reroll count.バニラのランダム最大リロール回数を上書きします"); cfgMaxRerollCount = ((BaseUnityPlugin)this).Config.Bind("Break", "MaxRerollCount", 999, new ConfigDescription("Maximum reroll count used when InfiniteReroll is disabled.InfiniteReroll無効時に使用する最大リロール回数です", (AcceptableValueBase)(object)new AcceptableValueRange(1, 9999), Array.Empty())); cfgEnableCostCap = ((BaseUnityPlugin)this).Config.Bind("Cost", "EnableCostCap", true, "Cap the reroll cost at MaxCost.リロール費用をMaxCostで上限固定します"); cfgBaseCost = ((BaseUnityPlugin)this).Config.Bind("Cost", "BaseCost", 5, new ConfigDescription("Base reroll cost in K dollars.基本リロール費用です(Kドル単位)", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); cfgCostIncrease = ((BaseUnityPlugin)this).Config.Bind("Cost", "CostIncrease", 5, new ConfigDescription("Cost increase per successful reroll in K dollars.成功リロール1回ごとの費用上昇量です(Kドル単位)", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); cfgMaxCost = ((BaseUnityPlugin)this).Config.Bind("Cost", "MaxCost", 30, new ConfigDescription("Maximum reroll cost in K dollars.最大リロール費用です(Kドル単位)", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); cfgDisableCostIncrease = ((BaseUnityPlugin)this).Config.Bind("Cost", "DisableCostIncrease", false, "Keep the reroll cost fixed at BaseCost.リロール費用をBaseCostで固定します"); cfgFirstRerollFree = ((BaseUnityPlugin)this).Config.Bind("Cost", "FirstRerollFree", false, "Make the first successful reroll on each stand free.各リロール台の初回成功リロールを無料化します"); cfgShowInfiniteRerollText = ((BaseUnityPlugin)this).Config.Bind("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 = "∞"; } else { int @int = GetInt(rerollCountField, stand); int int2 = GetInt(maxRerollCountField, stand); text = @int + "/" + int2; } string text2 = ((num <= 0) ? "FREE" : ("-$" + FormatDollars(num) + "K")); 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); } } } }