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<Color> pixels = val.GetPixels();
for (int i = 0; i < ((Il2CppArrayBase<Color>)(object)pixels).Count; i++)
{
((Il2CppArrayBase<Color>)(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<bool> 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<GUILayoutOption>());
GUILayout.Label(obj, _valueStyle, Array.Empty<GUILayoutOption>());
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<float>(amount, "+0.##;-0.##");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Now: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(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<int>(WinStreak);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" → +");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(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<int>(LossStreak);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" → +");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(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<int>(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<int>(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<int>(coinCount);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("g → +");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "0.#");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" luck. Total: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(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<string>(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<float> CfgGoldLuckRate;
internal static ConfigEntry<int> CfgHudX;
internal static ConfigEntry<int> CfgHudY;
internal static ConfigEntry<bool> 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<float>("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<int>("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<int>("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<bool>("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<LuckHUD>();
ClassInjector.RegisterTypeInIl2Cpp<StreakTracker>();
GameObject val = new GameObject("LuckyBreak_HUD");
val.AddComponent<LuckHUD>();
Object.DontDestroyOnLoad((Object)val);
GameObject val2 = new GameObject("LuckyBreak_StreakTracker");
val2.AddComponent<StreakTracker>();
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<float>(CfgGoldLuckRate.Value);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" Cheats=");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>(CfgCheatsEnabled.Value);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" HUD=(");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(CfgHudX.Value);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(",");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(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<string>(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);
}
}
}
}