using System; 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.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes.Arrays; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("LuckyBreak")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LuckyBreak")] [assembly: AssemblyTitle("LuckyBreak")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace LuckyBreak { internal class LuckHUD : MonoBehaviour { private static GUIStyle _boxStyle; private static GUIStyle _labelStyle; private static GUIStyle _valueStyle; private static bool _stylesInit; public LuckHUD(IntPtr ptr) : base(ptr) { } private static void InitStyles() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown _boxStyle = new GUIStyle(); _boxStyle.normal.background = MakeTex(1, 1, new Color(0f, 0f, 0f, 0.65f)); _boxStyle.padding = new RectOffset(10, 10, 6, 6); _labelStyle = new GUIStyle(); _labelStyle.fontStyle = (FontStyle)1; _labelStyle.normal.textColor = Color.white; _labelStyle.fontSize = 13; _valueStyle = new GUIStyle(); _valueStyle.fontSize = 22; _valueStyle.fontStyle = (FontStyle)1; _valueStyle.alignment = (TextAnchor)4; _stylesInit = true; } private static Texture2D MakeTex(int width, int height, Color col) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(width, height); Il2CppStructArray pixels = val.GetPixels(); for (int i = 0; i < ((Il2CppArrayBase)(object)pixels).Count; i++) { ((Il2CppArrayBase)(object)pixels)[i] = col; } val.SetPixels(pixels); val.Apply(); return val; } private void OnGUI() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) if (LuckManager.IsRunActive && (int)Event.current.type == 8) { if (Input.GetKeyDown((KeyCode)112)) { LuckManager.HudHidden = !LuckManager.HudHidden; LuckyBreakPlugin.ModLog.LogInfo((object)("[LuckyBreak] HUD " + (LuckManager.HudHidden ? "hidden" : "shown") + " (P key)")); } else { ConfigEntry cfgCheatsEnabled = LuckyBreakPlugin.CfgCheatsEnabled; if (cfgCheatsEnabled != null && cfgCheatsEnabled.Value) { if (Input.GetKeyDown((KeyCode)93)) { LuckManager.AddLuck(0.5f); LuckyBreakPlugin.ModLog.LogInfo((object)("[CHEAT] ] → +" + 0.5f + " luck, now " + LuckManager.CurrentLuck)); } else if (Input.GetKeyDown((KeyCode)91)) { LuckManager.AddLuck(-0.5f); LuckyBreakPlugin.ModLog.LogInfo((object)("[CHEAT] [ → -" + 0.5f + " luck, now " + LuckManager.CurrentLuck)); } } } } if (LuckManager.IsRunActive && !LuckManager.HudHidden && LuckManager.HasGoldLuckRelic) { if (!_stylesInit) { InitStyles(); } float num = LuckManager.CurrentLuck + LuckManager.GoldLuckBonus; Color textColor = default(Color); if (num > 5f) { ((Color)(ref textColor))..ctor(0.2f, 1f, 0.4f); } else if (num < -5f) { ((Color)(ref textColor))..ctor(1f, 0.3f, 0.3f); } else { ((Color)(ref textColor))..ctor(0.9f, 0.9f, 0.9f); } _valueStyle.normal.textColor = textColor; string value = ((num >= 0f) ? "+" : ""); string obj = $"{value}{num:0.#}"; string text = ""; if (LuckManager.WinStreak >= 2) { text = $" W{LuckManager.WinStreak}"; } else if (LuckManager.LossStreak >= 2) { text = $" L{LuckManager.LossStreak}"; } float num2 = 130f; float num3 = 60f; float num4 = ((float?)LuckyBreakPlugin.CfgHudX?.Value) ?? 8f; float num5 = (float)Screen.width - 246f - num4 - num2; float num6 = ((float?)LuckyBreakPlugin.CfgHudY?.Value) ?? 8f; GUI.Box(new Rect(num5, num6, num2, num3), GUIContent.none, _boxStyle); GUILayout.BeginArea(new Rect(num5 + 6f, num6 + 4f, num2 - 12f, num3 - 8f)); GUILayout.Label(" LUCK" + text, _labelStyle, Array.Empty()); GUILayout.Label(obj, _valueStyle, Array.Empty()); GUILayout.EndArea(); } } } internal static class LuckManager { internal static float CurrentLuck; internal static bool IsInCamp; internal static bool IsRunActive; internal static PlayerItemController CachedController; internal static int WinStreak; internal static int LossStreak; internal static bool HasGoldLuckRelic; internal static bool HudHidden; internal const float MaxLuck = 100f; internal const float MinLuck = -100f; internal const float LuckPerWinStreak = 5f; internal const float MercyLuckPerLoss = 2f; internal const float GoldToLuckRate = 0.05f; internal static float GoldLuckRate => LuckyBreakPlugin.CfgGoldLuckRate?.Value ?? 0.1f; internal static float GoldLuckBonus { get { if (!HasGoldLuckRelic) { return 0f; } try { PlayerMgr inst = PlayerMgr.Inst; if ((Object)(object)inst == (Object)null) { return 0f; } return (float)inst.CoinCount * GoldLuckRate; } catch { return 0f; } } } internal static void AddLuck(float amount) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown CurrentLuck = Math.Clamp(CurrentLuck + amount, -100f, 100f); ManualLogSource modLog = LuckyBreakPlugin.ModLog; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Luck changed by "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(amount, "+0.##;-0.##"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Now: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CurrentLuck, "0.##"); } modLog.LogInfo(val); } internal static void OnRunStart() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown IsRunActive = true; bool flag = default(bool); if (WinStreak > 0) { float num = (float)WinStreak * 5f; AddLuck(num); ManualLogSource modLog = LuckyBreakPlugin.ModLog; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(34, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Win streak "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(WinStreak); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" → +"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" luck at run start."); } modLog.LogInfo(val); } else if (LossStreak > 0) { float num2 = (float)LossStreak * 2f; AddLuck(num2); ManualLogSource modLog2 = LuckyBreakPlugin.ModLog; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(28, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loss streak "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(LossStreak); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" → +"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num2); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" mercy luck."); } modLog2.LogInfo(val); } } internal static void OnReturnToCamp() { IsRunActive = false; IsInCamp = true; CurrentLuck = 0f; HasGoldLuckRelic = false; LuckyBreakPlugin.ModLog.LogInfo((object)"Returned to camp — luck and relic state reset."); } internal static void OnRunFailed() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown WinStreak = 0; LossStreak++; ManualLogSource modLog = LuckyBreakPlugin.ModLog; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Run failed. Loss streak: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(LossStreak); } modLog.LogInfo(val); } internal static void OnRunWon() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown LossStreak = 0; WinStreak++; ManualLogSource modLog = LuckyBreakPlugin.ModLog; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Run won. Win streak: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(WinStreak); } modLog.LogInfo(val); } internal static void OnMainMenu() { CurrentLuck = 0f; IsInCamp = false; IsRunActive = false; CachedController = null; HasGoldLuckRelic = false; HudHidden = false; WinStreak = 0; LossStreak = 0; } internal static void ConvertGoldToLuck() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown bool flag = default(bool); try { PlayerMgr inst = PlayerMgr.Inst; if ((Object)(object)inst == (Object)null) { return; } int coinCount = inst.CoinCount; if (coinCount > 0) { float num = (float)coinCount * 0.05f; inst.ChangeCoin(-coinCount); AddLuck(num); ManualLogSource modLog = LuckyBreakPlugin.ModLog; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(30, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Gold→Luck: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(coinCount); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("g → +"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num, "0.#"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" luck. Total: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CurrentLuck, "0.#"); } modLog.LogInfo(val); } } catch (Exception ex) { ManualLogSource modLog2 = LuckyBreakPlugin.ModLog; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(26, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("ConvertGoldToLuck failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } modLog2.LogWarning(val2); } } } [BepInPlugin("com.effcoding.LuckyBreak", "LuckyBreak", "1.0.0")] public class LuckyBreakPlugin : BasePlugin { internal static ManualLogSource ModLog; private static readonly Harmony Harmony = new Harmony("com.effcoding.LuckyBreak"); internal static ConfigEntry CfgGoldLuckRate; internal static ConfigEntry CfgHudX; internal static ConfigEntry CfgHudY; internal static ConfigEntry CfgCheatsEnabled; public override void Load() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown ModLog = ((BasePlugin)this).Log; CfgGoldLuckRate = ((BasePlugin)this).Config.Bind("Pickaxe Relic — Gold Luck", "LuckPerCoin", 0.1f, "How much luck each coin you hold contributes while the Prospector's Pickaxe relic is active.\nYour gold balance adds to luck passively. Luck is capped at +100 (or -100).\n\nPower reference — total luck bonus at common gold amounts:\n LuckPerCoin | 50g | 100g | 200g | 500g | gold to hit cap\n 0.05 | +2.5 | +5 | +10 | +25 | ~2000g (very subtle)\n 0.08 | +4 | +8 | +16 | +40 | ~1250g (noticeable)\n 0.10 | +5 | +10 | +20 | +50 | ~1000g (default)\n 0.15 | +7.5 | +15 | +30 | +75 | ~666g (strong)\n 0.20 | +10 | +20 | +40 | cap | ~500g (dominant)\n\nAt +100 luck: shop prices are 30% cheaper and spell drops are upgraded.\nRecommended range: 0.05 (subtle) to 0.20 (dominant). Default: 0.10"); CfgHudX = ((BasePlugin)this).Config.Bind("HUD", "HUDOffsetFromRight", 8, "Shifts the HUD left from the right edge of the screen (default 8).\nRaise to move it further left. Lower to push it closer to the right edge.\nTip: press P during a run to instantly hide or show the stat overlay."); CfgHudY = ((BasePlugin)this).Config.Bind("HUD", "PositionY", 8, "Distance from the top of the screen in pixels (default 8).\nIncrease to move the HUD down."); CfgCheatsEnabled = ((BasePlugin)this).Config.Bind("Cheats", "Enabled", false, "Set to true to unlock luck adjustment keys during runs:\n ] — add +0.5 luck\n [ — subtract 0.5 luck\nP key always works to hide or show the HUD regardless of this setting.\nDefault: false (balanced play)."); ClassInjector.RegisterTypeInIl2Cpp(); ClassInjector.RegisterTypeInIl2Cpp(); GameObject val = new GameObject("LuckyBreak_HUD"); val.AddComponent(); Object.DontDestroyOnLoad((Object)val); GameObject val2 = new GameObject("LuckyBreak_StreakTracker"); val2.AddComponent(); Object.DontDestroyOnLoad((Object)val2); Harmony.PatchAll(); ManualLogSource modLog = ModLog; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(54, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("LuckyBreak 1.0.0 loaded. GoldLuckRate="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(CfgGoldLuckRate.Value); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" Cheats="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(CfgCheatsEnabled.Value); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" HUD=("); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(CfgHudX.Value); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(","); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(CfgHudY.Value); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(")"); } modLog.LogInfo(val3); } } internal class StreakTracker : MonoBehaviour { public StreakTracker(IntPtr ptr) : base(ptr) { } } } namespace LuckyBreak.Patches { [HarmonyPatch(typeof(BattleData), "GetSpellFromPool")] internal class Patch_BattleData_GetSpellFromPool { private static void Prefix(ref int level) { float num = LuckManager.CurrentLuck + LuckManager.GoldLuckBonus; if (num >= 75f) { level = 3; } else if (num >= 35f) { level = Math.Min(3, level + 1); } else if (num <= -50f) { level = Math.Max(1, level - 1); } } } [HarmonyPatch(typeof(BattleMgr), "Start_Normal")] internal class Patch_BattleMgr_StartNormal { private static void Postfix() { LuckyBreakPlugin.ModLog.LogInfo((object)"[LuckyBreak] Run started."); LuckManager.OnRunStart(); } } [HarmonyPatch(typeof(CampMgr), "Start")] internal class Patch_CampMgr_Start { private static void Postfix() { LuckyBreakPlugin.ModLog.LogInfo((object)"CampMgr.Start - entered camp, resetting run luck."); LuckManager.OnReturnToCamp(); } } [HarmonyPatch(typeof(CampMgr), "OnDestroy")] internal class Patch_CampMgr_OnDestroy { private static void Postfix() { LuckyBreakPlugin.ModLog.LogInfo((object)"CampMgr.OnDestroy - leaving camp."); LuckManager.IsInCamp = false; LuckManager.CachedController = null; } } [HarmonyPatch(typeof(MainMenuMgr), "Start")] internal class Patch_MainMenuMgr_Start { private static void Postfix() { LuckyBreakPlugin.ModLog.LogInfo((object)"MainMenuMgr.Start - main menu loaded, clearing run state."); LuckManager.OnMainMenu(); } } [HarmonyPatch(typeof(PlayerItemController), "Awake")] internal class Patch_PlayerItemController_Awake { private static void Postfix(PlayerItemController __instance) { LuckManager.CachedController = __instance; } } [HarmonyPatch(typeof(RollRewardFly), "SetRelic")] internal class Patch_RollRewardFly_SetRelic { private const int MONEY_IS_POWER_ID = 43; private static void Postfix(RollRewardFly __instance) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown try { if (__instance.id == 43 && !LuckManager.HasGoldLuckRelic) { LuckManager.HasGoldLuckRelic = true; LuckyBreakPlugin.ModLog.LogInfo((object)("[LuckyBreak] Money is Power (id=43) obtained → gold-luck passive activated. " + $"GoldBonus will now track CoinCount × {LuckManager.GoldLuckRate}.")); } } catch (Exception ex) { ManualLogSource modLog = LuckyBreakPlugin.ModLog; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(32, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[LuckyBreak] RelicPickup error: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } modLog.LogWarning(val); } } } [HarmonyPatch(typeof(Item), "GetPrice", new Type[] { typeof(bool) })] internal class Patch_Item_GetPrice { private static void Postfix(ref int __result, bool considerDiscount) { float num = LuckManager.CurrentLuck + LuckManager.GoldLuckBonus; if (num != 0f) { float num2 = ((num > 0f) ? (1f - num / 100f * 0.3f) : (1f + (0f - num) / 100f * 0.2f)); __result = (int)((float)__result * num2); } } } }