using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BossmanJackMod.State;
using BossmanJackMod.UI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BossmanJack Mod")]
[assembly: AssemblyDescription("A custom mod for CloverPit that adds BossmanJack Audios.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BossmanJack Mod")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("12345678-1234-1234-1234-123456789abc")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace BossmanJackMod
{
[BepInPlugin("com.riggedchips.cloverpit.bossmanjackmod", "BossmanJack Mod", "1.0.0")]
public class BossmanJackModPlugin : BaseUnityPlugin
{
private const string PluginGUID = "com.riggedchips.cloverpit.bossmanjackmod";
private const string PluginName = "BossmanJack Mod";
private const string PluginVersion = "1.0.0";
public static ConfigEntry<bool> EnableBloom = null;
public static ConfigEntry<float> BloomIntensity = null;
public static ConfigEntry<Color> BloomColor = null;
public static ConfigEntry<bool> DisableMotionBlur = null;
public static ConfigEntry<bool> DisableVignette = null;
public static ConfigEntry<bool> EnableVSync = null;
public static ConfigEntry<int> TargetFPS = null;
public static ConfigEntry<float> TimeScale = null;
public static ConfigEntry<bool> EnableCustomSlotImage = null;
public static ConfigEntry<string> CustomSlotImagePath = null;
public static ConfigEntry<bool> EnableCustomNoSpinsImage = null;
public static ConfigEntry<string> CustomNoSpinsImagePath = null;
public static ConfigEntry<bool> EnableNoSpinsFlash = null;
public static ConfigEntry<float> NoSpinsFlashSpeed = null;
public static ConfigEntry<float> NoSpinsFlashMinAlpha = null;
public static ConfigEntry<bool> EnableNoSpinsSound = null;
public static ConfigEntry<string> NoSpinsSoundFolder = null;
public static ConfigEntry<float> NoSpinsSoundVolume = null;
public static ConfigEntry<bool> EnableDeadlineSound = null;
public static ConfigEntry<string> DeadlineSoundFolder = null;
public static ConfigEntry<float> DeadlineSoundVolume = null;
public static ConfigEntry<bool> EnableJackpotSound = null;
public static ConfigEntry<string> JackpotSoundFolder = null;
public static ConfigEntry<float> JackpotSoundVolume = null;
public static ConfigEntry<bool> ForceJackpotTest = null;
public static ConfigEntry<bool> Force666Test = null;
public static ConfigEntry<bool> Enable666Sound = null;
public static ConfigEntry<string> Sound666Folder = null;
public static ConfigEntry<float> Sound666Volume = null;
public static ManualLogSource Log { get; private set; } = null;
internal static Assembly ModAssembly { get; private set; } = null;
internal static string AssetRoot { get; private set; } = string.Empty;
private void Awake()
{
//IL_0541: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
Log.LogInfo((object)"BossmanJack Mod v1.0.0 is loading...");
string text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Paths.PluginPath;
Log.LogDebug((object)("Resolved plugin directory: " + text));
string text3 = (AssetRoot = DetermineAssetRoot(text));
ModAssembly = typeof(BossmanJackModPlugin).Assembly;
Log.LogDebug((object)("Resolved asset root: " + text3));
EnableVSync = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance", "EnableVSync", true, "Enable vertical sync");
TargetFPS = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "TargetFPS", 60, "Target FPS (0 for unlimited)");
TimeScale = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "TimeScale", 1f, "Game time scale");
EnableCustomSlotImage = ((BaseUnityPlugin)this).Config.Bind<bool>("SlotMachine", "EnableCustomTitleImage", true, "Enable custom image on Slot Machine title/intro screen and Devil Horns powerup");
CustomSlotImagePath = ((BaseUnityPlugin)this).Config.Bind<string>("SlotMachine", "CustomTitleImagePath", Path.Combine(text3, "custom_logo.png"), "Full path to custom title screen image (PNG, JPG supported)");
EnableCustomNoSpinsImage = ((BaseUnityPlugin)this).Config.Bind<bool>("SlotMachine", "EnableCustomNoSpinsImage", true, "Enable custom image on 'No Spins Left' screen (replaces devil icon)");
CustomNoSpinsImagePath = ((BaseUnityPlugin)this).Config.Bind<string>("SlotMachine", "CustomNoSpinsImagePath", Path.Combine(text3, "no_spins_devil.png"), "Full path to custom 'No Spins Left' screen image (PNG, JPG supported)");
EnableNoSpinsFlash = ((BaseUnityPlugin)this).Config.Bind<bool>("SlotMachine", "EnableNoSpinsFlash", true, "Enable flashing/fading animation on 'No Spins Left' image");
NoSpinsFlashSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("SlotMachine", "NoSpinsFlashSpeed", 5f, "Speed of the flash animation (higher = faster)");
NoSpinsFlashMinAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("SlotMachine", "NoSpinsFlashMinAlpha", 0.3f, "Minimum transparency during flash (0 = invisible, 1 = fully visible)");
EnableNoSpinsSound = ((BaseUnityPlugin)this).Config.Bind<bool>("NoSpinsSound", "EnableSound", true, "Enable random sound playback when 'No Spins Left' screen appears");
NoSpinsSoundFolder = ((BaseUnityPlugin)this).Config.Bind<string>("NoSpinsSound", "SoundFolder", Path.Combine(text3, "no_spin_sounds"), "Folder containing sound files to play randomly (supports .wav, .ogg, .mp3)");
NoSpinsSoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("NoSpinsSound", "Volume", 0.8f, "Volume of the 'No Spins' sound (0.0 to 1.0)");
EnableDeadlineSound = ((BaseUnityPlugin)this).Config.Bind<bool>("DeadlineSound", "EnableSound", true, "Enable distance-based sound triggers for deadline requirements (closer to deadline = different sounds)");
DeadlineSoundFolder = ((BaseUnityPlugin)this).Config.Bind<string>("DeadlineSound", "SoundFolder", Path.Combine(text3, "deadline_sounds"), "Base folder with subfolders: 'far' (>50% remaining), 'medium' (25-50%), 'close' (10-25%), 'critical' (<10%)");
DeadlineSoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("DeadlineSound", "Volume", 0.7f, "Volume of deadline sounds (0.0 to 1.0)");
EnableJackpotSound = ((BaseUnityPlugin)this).Config.Bind<bool>("JackpotSound", "EnableSound", true, "Enable sound playback on jackpot or coin wins");
JackpotSoundFolder = ((BaseUnityPlugin)this).Config.Bind<string>("JackpotSound", "SoundFolder", Path.Combine(text3, "jackpot_sounds"), "Folder containing jackpot/win sound files (supports .wav, .ogg, .mp3)");
JackpotSoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("JackpotSound", "Volume", 0.9f, "Volume of jackpot/win sounds (0.0 to 1.0)");
ForceJackpotTest = ((BaseUnityPlugin)this).Config.Bind<bool>("DEBUG", "ForceJackpot", false, "TESTING ONLY: Force every spin to be a jackpot (all symbols the same)");
Force666Test = ((BaseUnityPlugin)this).Config.Bind<bool>("DEBUG", "Force666", false, "TESTING ONLY: Force every spin to have three sixes in a horizontal line");
Enable666Sound = ((BaseUnityPlugin)this).Config.Bind<bool>("666Sound", "EnableSound", true, "Enable sound playback when three sixes appear in a horizontal line");
Sound666Folder = ((BaseUnityPlugin)this).Config.Bind<string>("666Sound", "SoundFolder", Path.Combine(text3, "666_sounds"), "Folder containing 666 sound files (supports .wav, .ogg, .mp3)");
Sound666Volume = ((BaseUnityPlugin)this).Config.Bind<float>("666Sound", "Volume", 1f, "Volume of the 666 sound (0.0 to 1.0)");
MigrateAssetPath(CustomSlotImagePath, text3, "custom_logo.png", isFolder: false);
MigrateAssetPath(CustomNoSpinsImagePath, text3, "no_spins_devil.png", isFolder: false);
MigrateAssetPath(NoSpinsSoundFolder, text3, "no_spin_sounds", isFolder: true);
MigrateAssetPath(DeadlineSoundFolder, text3, "deadline_sounds", isFolder: true);
MigrateAssetPath(JackpotSoundFolder, text3, "jackpot_sounds", isFolder: true);
MigrateAssetPath(Sound666Folder, text3, "666_sounds", isFolder: true);
Log.LogDebug((object)("Attempting to provision custom_logo.png to: " + CustomSlotImagePath.Value));
DefaultAssetProvisioner.EnsureAssetFile(CustomSlotImagePath, "custom_logo.png");
Log.LogDebug((object)("Attempting to provision no_spins_devil.png to: " + CustomNoSpinsImagePath.Value));
DefaultAssetProvisioner.EnsureAssetFile(CustomNoSpinsImagePath, "no_spins_devil.png");
if (File.Exists(CustomSlotImagePath.Value))
{
Log.LogInfo((object)("✓ custom_logo.png exists at: " + CustomSlotImagePath.Value));
}
else
{
Log.LogWarning((object)("✗ custom_logo.png NOT FOUND at: " + CustomSlotImagePath.Value));
}
if (File.Exists(CustomNoSpinsImagePath.Value))
{
Log.LogInfo((object)("✓ no_spins_devil.png exists at: " + CustomNoSpinsImagePath.Value));
}
else
{
Log.LogWarning((object)("✗ no_spins_devil.png NOT FOUND at: " + CustomNoSpinsImagePath.Value));
}
ApplyPerformanceSettings();
try
{
new Harmony("com.riggedchips.cloverpit.bossmanjackmod").PatchAll();
Log.LogInfo((object)"BossmanJack Mod patched successfully!");
}
catch (Exception arg)
{
Log.LogError((object)$"Failed to apply patches: {arg}");
}
if (EnableNoSpinsSound.Value)
{
try
{
SoundManager.Instance.LoadSoundsFromFolder(NoSpinsSoundFolder.Value);
Log.LogInfo((object)"SoundManager initialized for No Spins sounds");
}
catch (Exception arg2)
{
Log.LogError((object)$"Failed to initialize SoundManager: {arg2}");
}
}
Log.LogInfo((object)"BossmanJack Mod loaded successfully!");
}
private void ApplyPerformanceSettings()
{
QualitySettings.vSyncCount = (EnableVSync.Value ? 1 : 0);
Application.targetFrameRate = TargetFPS.Value;
Time.timeScale = TimeScale.Value;
Log.LogInfo((object)$"Performance settings applied - VSync: {EnableVSync.Value}, Target FPS: {TargetFPS.Value}, Time Scale: {TimeScale.Value}");
}
private void Update()
{
if (Input.GetKey((KeyCode)306) && Input.GetKey((KeyCode)308) && Input.GetKeyDown((KeyCode)114))
{
Log.LogInfo((object)"Reloading settings...");
ApplyPerformanceSettings();
}
}
private static string DetermineAssetRoot(string pluginDirectory)
{
string text = Path.Combine(pluginDirectory, "BossmanJackMod");
if (!Directory.Exists(text))
{
return pluginDirectory;
}
return text;
}
private static void MigrateAssetPath(ConfigEntry<string> entry, string assetRoot, string relativeName, bool isFolder)
{
try
{
string value = entry.Value;
if (string.IsNullOrWhiteSpace(value))
{
entry.Value = Path.Combine(assetRoot, relativeName);
}
else if (!(isFolder ? Directory.Exists(value) : File.Exists(value)))
{
string text = Path.Combine(assetRoot, relativeName);
if (isFolder ? Directory.Exists(text) : File.Exists(text))
{
entry.Value = text;
Log.LogInfo((object)("Updated config entry '" + ((ConfigEntryBase)entry).Definition.Key + "' to new plugin asset path: " + text));
}
}
}
catch (Exception ex)
{
Log.LogWarning((object)("Failed to migrate config entry '" + ((ConfigEntryBase)entry).Definition.Key + "': " + ex.Message));
}
}
}
internal static class DefaultAssetProvisioner
{
public static void EnsureAssetFile(ConfigEntry<string> configEntry, string embeddedResourceName)
{
string embeddedResourceName2 = embeddedResourceName;
try
{
string value = configEntry.Value;
if (string.IsNullOrWhiteSpace(value) || File.Exists(value))
{
return;
}
string directoryName = Path.GetDirectoryName(value);
if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
Assembly modAssembly = BossmanJackModPlugin.ModAssembly;
string[] manifestResourceNames = modAssembly.GetManifestResourceNames();
BossmanJackModPlugin.Log.LogDebug((object)("Available embedded resources: " + string.Join(", ", manifestResourceNames)));
string text = manifestResourceNames.FirstOrDefault((string n) => n.EndsWith("." + embeddedResourceName2, StringComparison.OrdinalIgnoreCase)) ?? manifestResourceNames.FirstOrDefault((string n) => n.Equals(embeddedResourceName2, StringComparison.OrdinalIgnoreCase)) ?? manifestResourceNames.FirstOrDefault((string n) => n.IndexOf(embeddedResourceName2, StringComparison.OrdinalIgnoreCase) >= 0);
if (text == null)
{
BossmanJackModPlugin.Log.LogWarning((object)("Embedded asset '" + embeddedResourceName2 + "' was not found in resources. Available resources: [" + string.Join(", ", manifestResourceNames) + "]. Cannot provision " + value + "."));
return;
}
BossmanJackModPlugin.Log.LogDebug((object)("Found matching resource: '" + text + "' for '" + embeddedResourceName2 + "'"));
using Stream stream = modAssembly.GetManifestResourceStream(text);
if (stream == null)
{
BossmanJackModPlugin.Log.LogWarning((object)("Embedded asset '" + embeddedResourceName2 + "' was not found in resources. Cannot provision " + value + "."));
return;
}
using FileStream destination = File.Create(value);
stream.CopyTo(destination);
BossmanJackModPlugin.Log.LogInfo((object)("Provisioned default asset '" + embeddedResourceName2 + "' to " + value));
}
catch (Exception ex)
{
BossmanJackModPlugin.Log.LogWarning((object)("Failed to provision default asset '" + embeddedResourceName2 + "' for " + ((ConfigEntryBase)configEntry).Definition.Key + ": " + ex.Message));
}
}
}
public class ImageFlasher : MonoBehaviour
{
private RawImage rawImage;
private Image image;
private CanvasGroup canvasGroup;
private float timer;
public float flashSpeed = 2f;
public float minAlpha = 0.3f;
public float maxAlpha = 1f;
private void Awake()
{
rawImage = ((Component)this).GetComponent<RawImage>();
image = ((Component)this).GetComponent<Image>();
if ((Object)(object)rawImage == (Object)null && (Object)(object)image == (Object)null)
{
canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>();
}
}
private void Update()
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
timer += Time.deltaTime * flashSpeed;
float num = Mathf.Lerp(minAlpha, maxAlpha, (Mathf.Sin(timer) + 1f) / 2f);
if ((Object)(object)rawImage != (Object)null)
{
Color color = ((Graphic)rawImage).color;
color.a = num;
((Graphic)rawImage).color = color;
}
else if ((Object)(object)image != (Object)null)
{
Color color2 = ((Graphic)image).color;
color2.a = num;
((Graphic)image).color = color2;
}
else if ((Object)(object)canvasGroup != (Object)null)
{
canvasGroup.alpha = num;
}
}
}
internal static class DeadlineSoundCoordinator
{
[CompilerGenerated]
private sealed class <PlayAfterSmallDelay>d__11 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
private (int coins, int total, float volume) <request>5__2;
private SoundManager <manager>5__3;
private float <timeout>5__4;
private float <elapsed>5__5;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <PlayAfterSmallDelay>d__11(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<manager>5__3 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Expected O, but got Unknown
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
isProcessing = true;
if (!pendingRequest.HasValue)
{
activeRoutine = null;
isProcessing = false;
return false;
}
<request>5__2 = pendingRequest.Value;
pendingRequest = null;
<>2__current = (object)new WaitForSeconds(0.5f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<manager>5__3 = SoundManager.GetInstance("Deadline");
<manager>5__3.LoadSoundsForRoundCoins(BossmanJackModPlugin.DeadlineSoundFolder.Value, <request>5__2.coins);
Log.LogInfo((object)$"Coin-based sound triggered: earned {<request>5__2.coins} coins this round (total: {<request>5__2.total})");
<timeout>5__4 = 5f;
<elapsed>5__5 = 0f;
break;
case 2:
<>1__state = -1;
<elapsed>5__5 += 0.05f;
break;
}
if (!<manager>5__3.IsInitialized() && <manager>5__3.IsLoading() && <elapsed>5__5 < <timeout>5__4)
{
<>2__current = (object)new WaitForSeconds(0.05f);
<>1__state = 2;
return true;
}
if (<manager>5__3.IsInitialized())
{
<manager>5__3.PlayRandomSound(<request>5__2.volume);
}
else
{
Log.LogWarning((object)$"Deadline sound manager failed to initialize after {<elapsed>5__5}s");
}
activeRoutine = null;
isProcessing = false;
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static bool jackpotActive;
private static (int coins, int total, float volume)? pendingRequest;
private static Coroutine activeRoutine;
private static bool isProcessing;
private static ManualLogSource Log => BossmanJackModPlugin.Log;
static DeadlineSoundCoordinator()
{
SlotMachineUnifiedUpdatePatch.JackpotStarted += OnJackpotStarted;
SlotMachineUnifiedUpdatePatch.JackpotEnded += OnJackpotEnded;
}
private static void OnJackpotStarted()
{
jackpotActive = true;
Log.LogDebug((object)"Jackpot started - deadline sounds will wait");
}
private static void OnJackpotEnded()
{
jackpotActive = false;
Log.LogDebug((object)"Jackpot ended - checking for pending deadline sound");
if (pendingRequest.HasValue)
{
StartOrRestartRoutine((MonoBehaviour)(object)SoundManager.GetInstance("Deadline"));
}
}
public static void Request(int coinsEarned, int totalCoins, float volume)
{
pendingRequest = (coinsEarned, totalCoins, volume);
Log.LogDebug((object)$"Deadline sound requested: {coinsEarned} coins (jackpot active: {jackpotActive}, processing: {isProcessing})");
if (jackpotActive)
{
Log.LogDebug((object)"Jackpot is active - deadline sound will wait");
return;
}
if (isProcessing)
{
Log.LogDebug((object)"Already processing a deadline sound request - will restart");
}
StartOrRestartRoutine((MonoBehaviour)(object)SoundManager.GetInstance("Deadline"));
}
private static void StartOrRestartRoutine(MonoBehaviour runner)
{
if (activeRoutine != null)
{
runner.StopCoroutine(activeRoutine);
activeRoutine = null;
Log.LogDebug((object)"Stopped previous deadline sound routine");
}
activeRoutine = runner.StartCoroutine(PlayAfterSmallDelay());
}
[IteratorStateMachine(typeof(<PlayAfterSmallDelay>d__11))]
private static IEnumerator PlayAfterSmallDelay()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <PlayAfterSmallDelay>d__11(0);
}
}
[HarmonyPatch(typeof(SlotMachineScript), "Set_NoMoreSpins")]
public class SlotMachineNoSpinsUnifiedPatch
{
private static Texture2D customImage;
private static Sprite customSprite;
private static bool attemptedLoad;
private static ManualLogSource Log => BossmanJackModPlugin.Log;
[HarmonyPrefix]
private static void Prefix()
{
}
[HarmonyPostfix]
private static void Postfix(SlotMachineScript __instance)
{
if (BossmanJackModPlugin.EnableDeadlineSound.Value)
{
try
{
int coinsEarned = (int)GameplayData.RoundEarnedCoinsGet();
int totalCoins = (int)GameplayData.CoinsGet();
DeadlineSoundCoordinator.Request(coinsEarned, totalCoins, BossmanJackModPlugin.DeadlineSoundVolume.Value);
}
catch (Exception arg)
{
Log.LogError((object)$"Error playing coin-based sound: {arg}");
}
}
else if (BossmanJackModPlugin.EnableNoSpinsSound.Value)
{
try
{
SoundManager instance = SoundManager.Instance;
if (instance.IsInitialized())
{
instance.PlayRandomSound(BossmanJackModPlugin.NoSpinsSoundVolume.Value);
}
else
{
Log.LogWarning((object)"SoundManager not initialized - cannot play No Spins sound");
}
}
catch (Exception arg2)
{
Log.LogError((object)$"Error playing No Spins sound: {arg2}");
}
}
if (BossmanJackModPlugin.EnableDeadlineSound.Value)
{
try
{
Type type = Type.GetType("Sound, Assembly-CSharp");
if (type != null)
{
MethodInfo method = type.GetMethod("Stop", new Type[1] { typeof(string) });
if (method != null)
{
method.Invoke(null, new object[1] { "SoundSlotNoMoreCoins" });
Log.LogDebug((object)"Stopped original 'SoundSlotNoMoreCoins' (using deadline sound instead)");
}
}
}
catch (Exception ex)
{
Log.LogWarning((object)("Could not stop original no-coins sound: " + ex.Message));
}
}
if (!BossmanJackModPlugin.EnableCustomNoSpinsImage.Value)
{
return;
}
if ((Object)(object)customImage == (Object)null && !attemptedLoad)
{
attemptedLoad = true;
customImage = TextureLoader.LoadTexture(BossmanJackModPlugin.CustomNoSpinsImagePath.Value);
if (!((Object)(object)customImage != (Object)null))
{
Log.LogWarning((object)"Failed to load custom No Spins image. Using original.");
return;
}
customSprite = TextureLoader.CreateSprite(customImage);
Log.LogInfo((object)$"Custom No Spins image loaded successfully! Size: {((Texture)customImage).width}x{((Texture)customImage).height}");
}
if ((Object)(object)customImage != (Object)null && (Object)(object)__instance.noMoreSpinsScreenHolder != (Object)null)
{
RawImage[] componentsInChildren = __instance.noMoreSpinsScreenHolder.GetComponentsInChildren<RawImage>(true);
if (componentsInChildren.Length != 0)
{
Log.LogInfo((object)$"Found {componentsInChildren.Length} RawImage component(s) in noMoreSpinsScreenHolder");
RawImage[] array = componentsInChildren;
foreach (RawImage val in array)
{
val.texture = (Texture)(object)customImage;
Log.LogInfo((object)("Custom image applied to RawImage: " + ((Object)val).name));
if (BossmanJackModPlugin.EnableNoSpinsFlash.Value)
{
AddVisibilityToggle(((Component)val).gameObject);
}
}
return;
}
Image[] componentsInChildren2 = __instance.noMoreSpinsScreenHolder.GetComponentsInChildren<Image>(true);
if (componentsInChildren2.Length != 0)
{
Log.LogInfo((object)$"Found {componentsInChildren2.Length} Image component(s) in noMoreSpinsScreenHolder");
Image[] array2 = componentsInChildren2;
foreach (Image val2 in array2)
{
val2.sprite = customSprite;
Log.LogInfo((object)("Custom image applied to Image: " + ((Object)val2).name));
if (BossmanJackModPlugin.EnableNoSpinsFlash.Value)
{
AddVisibilityToggle(((Component)val2).gameObject);
}
}
}
else
{
Log.LogWarning((object)"Could not find any Image or RawImage components in noMoreSpinsScreenHolder");
}
}
else if ((Object)(object)__instance.noMoreSpinsScreenHolder == (Object)null)
{
Log.LogWarning((object)"noMoreSpinsScreenHolder is null - cannot replace image");
}
}
private static void AddVisibilityToggle(GameObject target)
{
if ((Object)(object)target.GetComponent<VisibilityToggler>() != (Object)null)
{
Log.LogDebug((object)("VisibilityToggler already exists on " + ((Object)target).name));
return;
}
VisibilityToggler visibilityToggler = target.AddComponent<VisibilityToggler>();
visibilityToggler.toggleInterval = 1f / BossmanJackModPlugin.NoSpinsFlashSpeed.Value;
Log.LogInfo((object)$"Added VisibilityToggler to {((Object)target).name} (Speed: {BossmanJackModPlugin.NoSpinsFlashSpeed.Value}, Interval: {visibilityToggler.toggleInterval})");
}
}
[HarmonyPatch(typeof(SlotMachineScript), "Start")]
public class SlotMachineTitleImagePatch
{
private static Texture2D customTitleTexture;
private static bool attemptedLoad;
private static bool loadFailed;
private static ManualLogSource Log => BossmanJackModPlugin.Log;
[HarmonyPostfix]
private static void Postfix(SlotMachineScript __instance)
{
if (!BossmanJackModPlugin.EnableCustomSlotImage.Value || loadFailed)
{
return;
}
if (!attemptedLoad)
{
attemptedLoad = true;
customTitleTexture = TextureLoader.LoadTexture(BossmanJackModPlugin.CustomSlotImagePath.Value);
if (!((Object)(object)customTitleTexture != (Object)null))
{
Log.LogWarning((object)"Failed to load custom title screen texture. Using original.");
loadFailed = true;
return;
}
Log.LogInfo((object)$"Custom title screen texture loaded! Size: {((Texture)customTitleTexture).width}x{((Texture)customTitleTexture).height}");
}
if ((Object)(object)customTitleTexture != (Object)null && (Object)(object)__instance.titleScreenRawImage != (Object)null)
{
__instance.titleScreenRawImage.texture = (Texture)(object)customTitleTexture;
Log.LogInfo((object)"Custom title screen image applied!");
}
else if ((Object)(object)__instance.titleScreenRawImage == (Object)null)
{
Log.LogWarning((object)"titleScreenRawImage is null - cannot replace texture");
}
}
}
[HarmonyPatch(typeof(PowerupScript), "GetPrefab")]
public class PowerupDevilHornPrefabPatch
{
private static Texture2D customHornTexture;
private static Sprite customHornSprite;
private static bool attemptedLoad;
private static bool loadFailed;
private static GameObject cachedModifiedPrefab;
private static ManualLogSource Log => BossmanJackModPlugin.Log;
[HarmonyPostfix]
private static void Postfix(Identifier identifier, ref GameObject __result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
if ((int)identifier != 94 || !BossmanJackModPlugin.EnableCustomSlotImage.Value || (Object)(object)__result == (Object)null || loadFailed)
{
return;
}
if (!attemptedLoad)
{
attemptedLoad = true;
customHornTexture = TextureLoader.LoadTexture(BossmanJackModPlugin.CustomSlotImagePath.Value);
if ((Object)(object)customHornTexture != (Object)null)
{
customHornSprite = TextureLoader.CreateSprite(customHornTexture);
Log.LogInfo((object)"Custom devil horn texture loaded!");
}
else
{
Log.LogWarning((object)"Failed to load custom devil horn texture. Using original.");
loadFailed = true;
}
}
if ((Object)(object)customHornTexture == (Object)null)
{
return;
}
if ((Object)(object)cachedModifiedPrefab == (Object)null)
{
cachedModifiedPrefab = Object.Instantiate<GameObject>(__result);
RawImage[] componentsInChildren = cachedModifiedPrefab.GetComponentsInChildren<RawImage>(true);
foreach (RawImage val in componentsInChildren)
{
val.texture = (Texture)(object)customHornTexture;
Log.LogDebug((object)("Replaced RawImage in devil horn prefab: " + ((Object)val).name));
}
Image[] componentsInChildren2 = cachedModifiedPrefab.GetComponentsInChildren<Image>(true);
foreach (Image val2 in componentsInChildren2)
{
val2.sprite = customHornSprite;
Log.LogDebug((object)("Replaced Image sprite in devil horn prefab: " + ((Object)val2).name));
}
Log.LogInfo((object)"Devil horn prefab modified and cached!");
}
__result = cachedModifiedPrefab;
}
}
[HarmonyPatch(typeof(SlotMachineScript), "Spin")]
public class ForceJackpotTestPatch
{
[CompilerGenerated]
private sealed class <ForceJackpotAfterDelay>d__3 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public SlotMachineScript instance;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ForceJackpotAfterDelay>d__3(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Expected I4, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSeconds(0.1f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
Log.LogWarning((object)"=== FORCE JACKPOT TEST MODE: Forcing symbols ===");
try
{
FieldInfo field = typeof(SlotMachineScript).GetField("lines", BindingFlags.Instance | BindingFlags.NonPublic);
if ((object)field == null)
{
Log.LogError((object)"Could not find 'lines' field!");
return false;
}
if (!(field.GetValue(instance) is Kind[][] array) || array.Length == 0 || array[0].Length == 0)
{
Log.LogError((object)"Lines array is null or empty!");
return false;
}
Kind val = array[0][0];
for (int i = 0; i < array.Length; i++)
{
for (int j = 0; j < array[i].Length; j++)
{
array[i][j] = (Kind)(int)val;
}
}
Log.LogWarning((object)$"FORCED JACKPOT: All symbols set to {val}");
Log.LogWarning((object)$"HasJackpot() = {SlotMachineScript.HasJackpot()}");
}
catch (Exception arg)
{
Log.LogError((object)$"Error forcing jackpot symbols: {arg}");
}
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static ManualLogSource Log => BossmanJackModPlugin.Log;
[HarmonyPostfix]
private static void Postfix(SlotMachineScript __instance)
{
if (BossmanJackModPlugin.ForceJackpotTest.Value)
{
((MonoBehaviour)__instance).StartCoroutine(ForceJackpotAfterDelay(__instance));
}
}
[IteratorStateMachine(typeof(<ForceJackpotAfterDelay>d__3))]
private static IEnumerator ForceJackpotAfterDelay(SlotMachineScript instance)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ForceJackpotAfterDelay>d__3(0)
{
instance = instance
};
}
}
[HarmonyPatch(typeof(SlotMachineScript), "Update")]
public class SlotMachineUnifiedUpdatePatch
{
private static bool wasJackpot;
private static bool jackpotSoundPlayed;
private static float jackpotSoundLoadTimer;
private static bool wasSixPattern;
private static bool sixSoundPlayed;
private static float sixSoundLoadTimer;
private static bool previousSpinning;
private static bool sixPlayedThisSpinSession;
private static ManualLogSource Log => BossmanJackModPlugin.Log;
public static event Action JackpotStarted;
public static event Action JackpotEnded;
public static bool IsJackpotActive()
{
return wasJackpot;
}
[HarmonyPostfix]
private static void Postfix()
{
ProcessJackpotDetection();
}
private static void ProcessJackpotDetection()
{
bool flag = SlotMachineScript.HasJackpot();
bool flag2 = SlotMachineScript.IsSpinning();
CheckSpecialPatterns(out var has, out var _);
if (flag && !wasJackpot)
{
wasJackpot = true;
jackpotSoundPlayed = false;
jackpotSoundLoadTimer = 0f;
SlotMachineUnifiedUpdatePatch.JackpotStarted?.Invoke();
try
{
SoundManager.GetInstance("Jackpot").LoadSoundsFromFolder(BossmanJackModPlugin.JackpotSoundFolder.Value);
Log.LogInfo((object)"Jackpot sounds loading started...");
}
catch (Exception arg)
{
Log.LogError((object)$"Error loading jackpot sounds: {arg}");
}
}
if (!flag && wasJackpot)
{
wasJackpot = false;
SlotMachineUnifiedUpdatePatch.JackpotEnded?.Invoke();
}
if (flag && !jackpotSoundPlayed)
{
jackpotSoundLoadTimer += Time.deltaTime;
if (jackpotSoundLoadTimer >= 1f)
{
try
{
SoundManager instance = SoundManager.GetInstance("Jackpot");
if (instance.IsInitialized() && !instance.IsLoading())
{
jackpotSoundPlayed = true;
instance.PlayRandomSound(BossmanJackModPlugin.JackpotSoundVolume.Value);
Log.LogInfo((object)"Jackpot sound played!");
}
else if (jackpotSoundLoadTimer >= 5f)
{
jackpotSoundPlayed = true;
Log.LogWarning((object)$"Jackpot sound timeout - initialized: {instance.IsInitialized()}, loading: {instance.IsLoading()}");
}
}
catch (Exception arg2)
{
Log.LogError((object)$"Error playing jackpot sound: {arg2}");
jackpotSoundPlayed = true;
}
}
}
if (BossmanJackModPlugin.Enable666Sound.Value && has && !sixPlayedThisSpinSession)
{
if (!wasSixPattern)
{
wasSixPattern = true;
sixSoundPlayed = false;
sixSoundLoadTimer = 0f;
try
{
SoundManager.GetInstance("SixSixSix").LoadSoundsFromFolder(BossmanJackModPlugin.Sound666Folder.Value);
}
catch (Exception arg3)
{
Log.LogError((object)$"Error loading 666 sounds: {arg3}");
sixSoundPlayed = true;
sixPlayedThisSpinSession = true;
}
}
if (!sixSoundPlayed)
{
sixSoundLoadTimer += Time.deltaTime;
if (sixSoundLoadTimer >= 0.5f)
{
try
{
SoundManager instance2 = SoundManager.GetInstance("SixSixSix");
if (instance2.IsInitialized() && !instance2.IsLoading())
{
sixSoundPlayed = true;
sixPlayedThisSpinSession = true;
instance2.PlayRandomSound(BossmanJackModPlugin.Sound666Volume.Value);
}
else if (sixSoundLoadTimer >= 3f)
{
sixSoundPlayed = true;
sixPlayedThisSpinSession = true;
}
}
catch (Exception arg4)
{
Log.LogError((object)$"Error playing 666 sound: {arg4}");
sixSoundPlayed = true;
sixPlayedThisSpinSession = true;
}
}
}
}
else if (!has && wasSixPattern)
{
wasSixPattern = false;
sixSoundPlayed = false;
sixSoundLoadTimer = 0f;
}
if (!flag2 && previousSpinning)
{
sixPlayedThisSpinSession = false;
wasSixPattern = false;
sixSoundPlayed = false;
sixSoundLoadTimer = 0f;
}
previousSpinning = flag2;
}
private static void CheckSpecialPatterns(out bool has666, out bool has999)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Invalid comparison between Unknown and I4
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Invalid comparison between Unknown and I4
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Invalid comparison between Unknown and I4
has666 = false;
has999 = false;
try
{
if ((Object)(object)SlotMachineScript.instance == (Object)null)
{
return;
}
List<PatternInfos> patternsEnabled = SlotMachineScript.instance.GetPatternsEnabled();
if (patternsEnabled == null || patternsEnabled.Count == 0)
{
return;
}
for (int i = 0; i < patternsEnabled.Count; i++)
{
PatternInfos val = patternsEnabled[i];
if ((int)val.patternKind == 2)
{
if ((int)val.symbolKind == 7)
{
has666 = true;
}
else if ((int)val.symbolKind == 8)
{
has999 = true;
}
if (has666 & has999)
{
break;
}
}
}
if (has999 && (BossmanJackModPlugin.Enable666Sound.Value || BossmanJackModPlugin.EnableJackpotSound.Value))
{
Log.LogWarning((object)"!!! 999 PATTERN DETECTED !!!");
}
}
catch (Exception ex)
{
Log.LogError((object)("Error checking 666/999 pattern: " + ex.Message));
}
}
}
public class SoundManager : MonoBehaviour
{
[CompilerGenerated]
private sealed class <LoadAudioFilesCoroutine>d__15 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public List<string> filePaths;
public SoundManager <>4__this;
private int <successCount>5__2;
private List<string>.Enumerator <>7__wrap2;
private string <filePath>5__4;
private UnityWebRequest <www>5__5;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadAudioFilesCoroutine>d__15(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if ((uint)(num - -4) <= 1u || num == 1)
{
try
{
if (num == -4 || num == 1)
{
try
{
}
finally
{
<>m__Finally2();
}
}
}
finally
{
<>m__Finally1();
}
}
<>7__wrap2 = default(List<string>.Enumerator);
<filePath>5__4 = null;
<www>5__5 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Invalid comparison between Unknown and I4
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
try
{
int num = <>1__state;
SoundManager soundManager = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<successCount>5__2 = 0;
Log.LogDebug((object)$"Starting async load of {filePaths.Count} audio file(s).");
<>7__wrap2 = filePaths.GetEnumerator();
<>1__state = -3;
break;
case 1:
<>1__state = -4;
if ((int)<www>5__5.result == 1)
{
AudioClip content = DownloadHandlerAudioClip.GetContent(<www>5__5);
if ((Object)(object)content != (Object)null)
{
((Object)content).name = Path.GetFileName(<filePath>5__4);
soundManager.loadedClips.Add(content);
<successCount>5__2++;
Log.LogInfo((object)("Loaded audio: " + ((Object)content).name));
}
else
{
Log.LogWarning((object)("Download handler returned null clip for " + <filePath>5__4 + " despite success result."));
}
}
else
{
Log.LogError((object)$"Failed to load audio file {<filePath>5__4}. Result={<www>5__5.result}, Error={<www>5__5.error}");
}
<>m__Finally2();
<www>5__5 = null;
<filePath>5__4 = null;
break;
}
while (<>7__wrap2.MoveNext())
{
<filePath>5__4 = <>7__wrap2.Current;
AudioType audioType = soundManager.GetAudioType(<filePath>5__4);
if ((int)audioType == 0)
{
Log.LogWarning((object)("Unsupported audio type for file " + <filePath>5__4 + ". Skipping."));
continue;
}
string text = "file:///" + <filePath>5__4.Replace("\\", "/");
<www>5__5 = UnityWebRequestMultimedia.GetAudioClip(text, audioType);
<>1__state = -4;
<>2__current = <www>5__5.SendWebRequest();
<>1__state = 1;
return true;
}
<>m__Finally1();
<>7__wrap2 = default(List<string>.Enumerator);
Log.LogInfo((object)$"Successfully loaded {<successCount>5__2}/{filePaths.Count} audio files");
lock (soundManager.loadingLock)
{
soundManager.isInitialized = <successCount>5__2 > 0;
soundManager.isLoading = false;
}
Log.LogInfo((object)$"SoundManager initialization state: {soundManager.isInitialized} (clip count={soundManager.loadedClips.Count})");
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
((IDisposable)<>7__wrap2).Dispose();
}
private void <>m__Finally2()
{
<>1__state = -3;
if (<www>5__5 != null)
{
((IDisposable)<www>5__5).Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <WaitAndPlayCoroutine>d__26 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public SoundManager <>4__this;
public float volume;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <WaitAndPlayCoroutine>d__26(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
int num = <>1__state;
SoundManager soundManager = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
break;
case 2:
<>1__state = -1;
break;
}
if (!soundManager.isInitialized)
{
<>2__current = null;
<>1__state = 2;
return true;
}
soundManager.PlayRandomSound(volume);
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static Dictionary<string, SoundManager> _instances = new Dictionary<string, SoundManager>();
private AudioSource audioSource;
private List<AudioClip> loadedClips = new List<AudioClip>();
private bool isInitialized;
private bool isLoading;
private readonly object loadingLock = new object();
public int[] coinTiers = new int[3] { 10, 50, 100 };
private static ManualLogSource Log => BossmanJackModPlugin.Log;
public static SoundManager Instance => GetInstance("Default");
public static SoundManager GetInstance(string name)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
if (!_instances.ContainsKey(name))
{
GameObject val = new GameObject("SoundManager_" + name);
Object.DontDestroyOnLoad((Object)val);
SoundManager value = val.AddComponent<SoundManager>();
_instances[name] = value;
Log.LogInfo((object)("Created SoundManager instance: " + name));
}
return _instances[name];
}
private void Awake()
{
audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
audioSource.playOnAwake = false;
audioSource.spatialBlend = 0f;
}
private void OnDestroy()
{
List<string> list = new List<string>();
foreach (KeyValuePair<string, SoundManager> instance in _instances)
{
if ((Object)(object)instance.Value == (Object)(object)this)
{
list.Add(instance.Key);
}
}
foreach (string item in list)
{
_instances.Remove(item);
}
}
public void LoadSoundsFromFolder(string folderPath)
{
Log.LogInfo((object)("LoadSoundsFromFolder invoked with path: " + folderPath));
lock (loadingLock)
{
if (isLoading)
{
Log.LogWarning((object)("Already loading sounds, ignoring request for: " + folderPath));
return;
}
if (!Directory.Exists(folderPath))
{
Log.LogWarning((object)("Sound folder does not exist: " + folderPath));
return;
}
isLoading = true;
loadedClips.Clear();
isInitialized = false;
Log.LogDebug((object)"Cleared previously loaded audio clips. Awaiting new load.");
string[] obj = new string[3] { "*.wav", "*.ogg", "*.mp3" };
List<string> list = new List<string>();
string[] array = obj;
foreach (string searchPattern in array)
{
list.AddRange(Directory.GetFiles(folderPath, searchPattern, SearchOption.TopDirectoryOnly));
}
if (list.Count == 0)
{
Log.LogWarning((object)("No audio files found in " + folderPath));
isLoading = false;
}
else
{
Log.LogInfo((object)$"Found {list.Count} audio file(s) in {folderPath}");
((MonoBehaviour)this).StartCoroutine(LoadAudioFilesCoroutine(list));
}
}
}
[IteratorStateMachine(typeof(<LoadAudioFilesCoroutine>d__15))]
private IEnumerator LoadAudioFilesCoroutine(List<string> filePaths)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadAudioFilesCoroutine>d__15(0)
{
<>4__this = this,
filePaths = filePaths
};
}
private AudioType GetAudioType(string filePath)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
return (AudioType)(Path.GetExtension(filePath).ToLower() switch
{
".wav" => 20,
".ogg" => 14,
".mp3" => 13,
_ => 0,
});
}
public void PlayRandomSound(float volume = 1f)
{
if (!isInitialized || loadedClips.Count == 0)
{
Log.LogWarning((object)$"Cannot play sound - initialized={isInitialized}, clipCount={loadedClips.Count}");
return;
}
int index = Random.Range(0, loadedClips.Count);
AudioClip val = loadedClips[index];
audioSource.volume = Mathf.Clamp01(volume);
audioSource.PlayOneShot(val);
Log.LogInfo((object)$"Playing random sound: {((Object)val).name} (Volume: {audioSource.volume})");
}
public int GetLoadedClipCount()
{
return loadedClips.Count;
}
public bool IsInitialized()
{
return isInitialized;
}
public bool IsLoading()
{
lock (loadingLock)
{
return isLoading;
}
}
public string GetDeadlineDistanceTier(int roundsPlayed, int roundsTotal)
{
if (roundsTotal <= 0)
{
return "far";
}
float num = (float)(roundsTotal - roundsPlayed) / (float)roundsTotal * 100f;
if (num > 50f)
{
return "far";
}
if (num > 25f)
{
return "medium";
}
if (num > 10f)
{
return "close";
}
return "critical";
}
public void LoadSoundsForDeadlineDistance(string baseFolderPath, int roundsPlayed, int roundsTotal)
{
string deadlineDistanceTier = GetDeadlineDistanceTier(roundsPlayed, roundsTotal);
string folderPath = Path.Combine(baseFolderPath, deadlineDistanceTier);
float num = ((roundsTotal > 0) ? ((float)(roundsTotal - roundsPlayed) / (float)roundsTotal * 100f) : 100f);
Log.LogInfo((object)$"Loading deadline sounds for {roundsPlayed}/{roundsTotal} rounds ({num:F1}% remaining) from tier: {deadlineDistanceTier}");
LoadSoundsFromFolder(folderPath);
}
public string GetCoinTierFolder(int coinsEarnedThisRound)
{
if (coinsEarnedThisRound <= coinTiers[0])
{
return $"0-{coinTiers[0]}";
}
for (int i = 0; i < coinTiers.Length - 1; i++)
{
if (coinsEarnedThisRound <= coinTiers[i + 1])
{
return $"{coinTiers[i] + 1}-{coinTiers[i + 1]}";
}
}
return $"{coinTiers[coinTiers.Length - 1]}+";
}
public void LoadSoundsForRoundCoins(string baseFolderPath, int coinsEarnedThisRound)
{
string coinTierFolder = GetCoinTierFolder(coinsEarnedThisRound);
string folderPath = Path.Combine(baseFolderPath, coinTierFolder);
Log.LogInfo((object)$"Loading sounds for {coinsEarnedThisRound} coins earned this round from tier: {coinTierFolder}");
LoadSoundsFromFolder(folderPath);
}
public void LoadAndPlayForRoundCoins(string baseFolderPath, int coinsEarnedThisRound, float volume = 1f)
{
LoadSoundsForRoundCoins(baseFolderPath, coinsEarnedThisRound);
((MonoBehaviour)this).StartCoroutine(WaitAndPlayCoroutine(volume));
}
[IteratorStateMachine(typeof(<WaitAndPlayCoroutine>d__26))]
private IEnumerator WaitAndPlayCoroutine(float volume)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <WaitAndPlayCoroutine>d__26(0)
{
<>4__this = this,
volume = volume
};
}
}
public static class TextureLoader
{
private static readonly MethodInfo? LoadImageMethod;
private static ManualLogSource Log => BossmanJackModPlugin.Log;
static TextureLoader()
{
try
{
LoadImageMethod = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "UnityEngine.ImageConversionModule", StringComparison.Ordinal))?.GetType("UnityEngine.ImageConversion")?.GetMethod("LoadImage", new Type[3]
{
typeof(Texture2D),
typeof(byte[]),
typeof(bool)
});
if (LoadImageMethod == null)
{
Log.LogWarning((object)"UnityEngine.ImageConversion.LoadImage could not be located. Texture loading may fail.");
}
}
catch (Exception ex)
{
Log.LogWarning((object)("Failed to initialize texture loader reflection: " + ex.Message));
}
}
public static Texture2D? LoadTexture(string filePath)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
try
{
if (!File.Exists(filePath))
{
Log.LogError((object)("Texture file not found: " + filePath));
return null;
}
byte[] array = File.ReadAllBytes(filePath);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
bool flag = false;
if (LoadImageMethod != null)
{
try
{
flag = (bool)LoadImageMethod.Invoke(null, new object[3] { val, array, false });
}
catch (Exception ex)
{
Log.LogWarning((object)("Reflection LoadImage invoke failed: " + ex.Message));
}
}
else
{
Log.LogWarning((object)"LoadImage method unavailable. Texture loading will fail.");
}
if (flag)
{
Log.LogInfo((object)$"Successfully loaded texture: {filePath} ({((Texture)val).width}x{((Texture)val).height})");
return val;
}
Log.LogError((object)("Failed to load image data from: " + filePath));
Object.Destroy((Object)(object)val);
return null;
}
catch (Exception ex2)
{
Log.LogError((object)("Error loading texture from " + filePath + ": " + ex2.Message));
return null;
}
}
public static Texture2D LoadTextureFromPluginFolder(string fileName)
{
return LoadTexture(Path.Combine(Path.GetDirectoryName(typeof(TextureLoader).Assembly.Location), fileName));
}
public static Sprite? CreateSprite(Texture2D? texture)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)texture == (Object)null)
{
Log.LogError((object)"Cannot create sprite from null texture");
return null;
}
return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), 100f);
}
}
public class VisibilityToggler : MonoBehaviour
{
[Tooltip("Time in seconds between visibility toggles")]
public float toggleInterval = 0.2f;
private float nextToggleTime;
private bool isVisible = true;
private Renderer[] renderers;
private Graphic[] uiGraphics;
private void OnEnable()
{
nextToggleTime = Time.time + toggleInterval;
renderers = ((Component)this).GetComponentsInChildren<Renderer>();
uiGraphics = ((Component)this).GetComponentsInChildren<Graphic>();
SetVisibility(enabled: true);
}
private void Update()
{
if (Time.time >= nextToggleTime)
{
isVisible = !isVisible;
SetVisibility(isVisible);
nextToggleTime = Time.time + toggleInterval;
}
}
private void SetVisibility(bool enabled)
{
Renderer[] array = renderers;
for (int i = 0; i < array.Length; i++)
{
array[i].enabled = enabled;
}
Graphic[] array2 = uiGraphics;
for (int i = 0; i < array2.Length; i++)
{
((Behaviour)array2[i]).enabled = enabled;
}
}
}
}
namespace BossmanJackMod.UI
{
public class PromptService : MonoBehaviour
{
private static PromptService instance;
private Canvas canvas;
private CanvasGroup canvasGroup;
private GameObject panel;
private Text headerText;
private Button yesButton;
private Button noButton;
private Text yesButtonText;
private Text noButtonText;
private Action currentOnYes;
private Action currentOnNo;
private static ManualLogSource Log => BossmanJackModPlugin.Log;
public static PromptService Instance => instance;
public static void EnsureCreated()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
if (!((Object)(object)instance != (Object)null))
{
GameObject val = new GameObject("ModPromptService");
Object.DontDestroyOnLoad((Object)val);
instance = val.AddComponent<PromptService>();
instance.BuildUI();
Log.LogInfo((object)"PromptService created and initialized");
}
}
public static void ShowYesNo(string header, Action onYes, Action onNo)
{
EnsureCreated();
instance.ShowPrompt(header, onYes, onNo);
}
private void BuildUI()
{
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Expected O, but got Unknown
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Expected O, but got Unknown
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Expected O, but got Unknown
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_021a: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Expected O, but got Unknown
canvas = ((Component)this).gameObject.AddComponent<Canvas>();
canvas.renderMode = (RenderMode)0;
canvas.sortingOrder = 999;
((Component)this).gameObject.AddComponent<CanvasScaler>();
((Component)this).gameObject.AddComponent<GraphicRaycaster>();
canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>();
canvasGroup.alpha = 0f;
canvasGroup.interactable = false;
canvasGroup.blocksRaycasts = false;
panel = new GameObject("PromptPanel");
panel.transform.SetParent(((Component)this).transform, false);
RectTransform obj = panel.AddComponent<RectTransform>();
obj.anchorMin = new Vector2(0.5f, 0.5f);
obj.anchorMax = new Vector2(0.5f, 0.5f);
obj.sizeDelta = new Vector2(400f, 200f);
((Graphic)panel.AddComponent<Image>()).color = new Color(0.1f, 0.1f, 0.1f, 0.95f);
GameObject val = new GameObject("HeaderText");
val.transform.SetParent(panel.transform, false);
RectTransform obj2 = val.AddComponent<RectTransform>();
obj2.anchorMin = new Vector2(0.5f, 0.7f);
obj2.anchorMax = new Vector2(0.5f, 0.7f);
obj2.sizeDelta = new Vector2(350f, 60f);
headerText = val.AddComponent<Text>();
headerText.text = "Prompt";
headerText.fontSize = 24;
((Graphic)headerText).color = Color.white;
CreateButton(ref yesButton, ref yesButtonText, "YesButton", "YES", new Vector2(-60f, -30f), new UnityAction(OnYesClicked));
CreateButton(ref noButton, ref noButtonText, "NoButton", "NO", new Vector2(60f, -30f), new UnityAction(OnNoClicked));
Log.LogInfo((object)"PromptService UI built successfully");
}
private void CreateButton(ref Button button, ref Text buttonText, string name, string text, Vector2 position, UnityAction onClick)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_002f: 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_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Expected O, but got Unknown
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name);
val.transform.SetParent(panel.transform, false);
RectTransform obj = val.AddComponent<RectTransform>();
obj.anchorMin = new Vector2(0.5f, 0.5f);
obj.anchorMax = new Vector2(0.5f, 0.5f);
obj.anchoredPosition = position;
obj.sizeDelta = new Vector2(100f, 40f);
Image val2 = val.AddComponent<Image>();
((Graphic)val2).color = new Color(0.3f, 0.3f, 0.3f, 1f);
button = val.AddComponent<Button>();
((Selectable)button).targetGraphic = (Graphic)(object)val2;
((UnityEvent)button.onClick).AddListener(onClick);
ColorBlock colors = ((Selectable)button).colors;
((ColorBlock)(ref colors)).highlightedColor = new Color(0.5f, 0.5f, 0.5f, 1f);
((ColorBlock)(ref colors)).pressedColor = new Color(0.2f, 0.2f, 0.2f, 1f);
((Selectable)button).colors = colors;
GameObject val3 = new GameObject("Text");
val3.transform.SetParent(val.transform, false);
RectTransform obj2 = val3.AddComponent<RectTransform>();
obj2.anchorMin = Vector2.zero;
obj2.anchorMax = Vector2.one;
obj2.offsetMin = Vector2.zero;
obj2.offsetMax = Vector2.zero;
buttonText = val3.AddComponent<Text>();
buttonText.text = text;
buttonText.fontSize = 18;
((Graphic)buttonText).color = Color.white;
}
private void ShowPrompt(string header, Action onYes, Action onNo)
{
if ((Object)(object)headerText != (Object)null)
{
headerText.text = header;
}
currentOnYes = onYes;
currentOnNo = onNo;
canvasGroup.alpha = 1f;
canvasGroup.interactable = true;
canvasGroup.blocksRaycasts = true;
SlotPauseManager.Pause();
Log.LogInfo((object)("Prompt shown: " + header));
}
private void HidePrompt()
{
canvasGroup.alpha = 0f;
canvasGroup.interactable = false;
canvasGroup.blocksRaycasts = false;
currentOnYes = null;
currentOnNo = null;
SlotPauseManager.Resume();
Log.LogInfo((object)"Prompt hidden");
}
private void OnYesClicked()
{
Log.LogInfo((object)"YES button clicked");
Action action = currentOnYes;
HidePrompt();
action?.Invoke();
}
private void OnNoClicked()
{
Log.LogInfo((object)"NO button clicked");
Action action = currentOnNo;
HidePrompt();
action?.Invoke();
}
}
}
namespace BossmanJackMod.State
{
public static class SlotPauseManager
{
public static bool IsPaused { get; set; }
public static void Pause()
{
IsPaused = true;
}
public static void Resume()
{
IsPaused = false;
}
}
}
namespace BossmanJackMod.Patches
{
[HarmonyPatch(typeof(SlotMachineScript), "Start")]
public class SlotMachine_InitializeModSystems
{
private static ManualLogSource Log => BossmanJackModPlugin.Log;
[HarmonyPostfix]
private static void Postfix()
{
try
{
PromptService.EnsureCreated();
Log.LogInfo((object)"Mod systems initialized");
}
catch (Exception arg)
{
Log.LogError((object)$"Error initializing mod systems: {arg}");
}
}
}
[HarmonyPatch(typeof(SlotMachineScript), "Update")]
public class SlotMachine_PauseWhilePromptActive
{
[HarmonyPrefix]
private static bool Prefix()
{
if (SlotPauseManager.IsPaused)
{
return false;
}
return true;
}
}
[HarmonyPatch(typeof(SlotMachineScript), "Spin")]
public class SlotMachine_BlockSpinWhilePaused
{
private static ManualLogSource Log => BossmanJackModPlugin.Log;
[HarmonyPrefix]
private static bool Prefix()
{
if (SlotPauseManager.IsPaused)
{
Log.LogDebug((object)"Blocked spin while paused");
return false;
}
return true;
}
}
}