Decompiled source of PEAK SLOTS v1.0.2

plugins/SlotMachines.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using Photon.Pun;
using Photon.Realtime;
using SlotMachines.Localization;
using SlotMachines.Machines;
using SlotMachines.Net;
using SlotMachines.Placement;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ThomasAusHH")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Slot machines at every campfire, hidden along the climb and in the airport lounge. Pay with your life bar, win real loot - or get cursed. The house always wins.")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+29201138faf991e84c01d0b08d03668c942a58e9")]
[assembly: AssemblyProduct("SlotMachines")]
[assembly: AssemblyTitle("SlotMachines")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://discord.gg/nKUHvzdmVp")]
[assembly: AssemblyVersion("1.0.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SlotMachines
{
	[BepInPlugin("com.thomasaushh.peakslots", "PEAK SLOTS", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.thomasaushh.peakslots";

		public const string PluginName = "PEAK SLOTS";

		public const string PluginVersion = "1.0.2";

		public const string VersionLabel = "";

		public static string DisplayVersion
		{
			get
			{
				if (!string.IsNullOrEmpty(""))
				{
					return "1.0.2 ";
				}
				return "1.0.2";
			}
		}

		internal static ManualLogSource Log { get; private set; }

		internal static Plugin Instance { get; private set; }

		internal static ConfigEntry<bool> EnableAtCampfires { get; private set; }

		internal static ConfigEntry<bool> EnableAtAirport { get; private set; }

		internal static ConfigEntry<int> MachinesPerCampfire { get; private set; }

		internal static ConfigEntry<float> PriceMultiplier { get; private set; }

		internal static ConfigEntry<bool> AllowDeath { get; private set; }

		internal static ConfigEntry<bool> AllowSkeleton { get; private set; }

		internal static ConfigEntry<SlotLogLevel> LogLevel { get; private set; }

		internal static ConfigEntry<bool> UseBundleModel { get; private set; }

		internal static ConfigEntry<bool> PeakShader { get; private set; }

		internal static ConfigEntry<float> SoundVolume { get; private set; }

		internal static ConfigEntry<float> AttractVolume { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)("PEAK SLOTS " + DisplayVersion + " geladen."));
			InitializeConfig();
			Loc.Initialize();
			SlotNet.Register();
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void InitializeConfig()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			EnableAtCampfires = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableAtCampfires", true, "Eine Maschine neben jedem Lagerfeuer auf der Insel.");
			EnableAtAirport = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableAtAirport", true, "Maschinen im Flughafen (Freispiele: kein Preis, Items ja, Effekte nein).");
			MachinesPerCampfire = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MachinesPerCampfire", 1, new ConfigDescription("Maschinen je Lagerfeuer.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 3), Array.Empty<object>()));
			PriceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "PriceMultiplier", 1f, new ConfigDescription("Multiplikator auf den Lebenspreis je Dreh.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			AllowDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "AllowDeath", true, "Darf ein Dreh toedlich enden (nur an hoeheren Stufen)?");
			AllowSkeleton = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "AllowSkeleton", true, "Darf ein Dreh den Spieler zum Skelett machen?");
			LogLevel = ((BaseUnityPlugin)this).Config.Bind<SlotLogLevel>("Logging", "LogLevel", SlotLogLevel.Info, "Wie gespraechig der Mod im BepInEx-Log ist.");
			UseBundleModel = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "UseBundleModel", true, "Modell aus dem eingebetteten AssetBundle (Fasen, Partikel, Licht). Aus = einfaches Modell aus Primitiven.");
			PeakShader = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "PeakShader", true, "Korpus im Spiel-Look (Shader W/Peak_Standard mit gemalten Schichten). Aus = glattes URP-Material.");
			SoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Volume", 1f, new ConfigDescription("Lautstaerke des Mods, zusaetzlich zu Master- und SFX-Regler des Spiels. 0 = stumm.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			AttractVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "AttractVolume", 1f, new ConfigDescription("Lautstaerke der Lockmelodie im Leerlauf, zusaetzlich zu Audio.Volume. 0 = aus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Loc.Refresh();
			try
			{
				if ((int)mode == 0)
				{
					SlotLog.Info("[Plugin] Szene '" + ((Scene)(ref scene)).name + "' geladen.");
					((MonoBehaviour)this).StartCoroutine(MachinePlacer.PlaceForScene(((Scene)(ref scene)).name));
				}
			}
			catch (Exception arg)
			{
				SlotLog.Error($"[Plugin] Fehler in OnSceneLoaded: {arg}");
			}
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}
	}
	public enum SlotLogLevel
	{
		Error,
		Warning,
		Info,
		Debug
	}
	internal static class SlotLog
	{
		private const string Prefix = "[PeakSlots] ";

		public static void Error(string message)
		{
			if (Enabled(SlotLogLevel.Error))
			{
				Plugin.Log.LogError((object)("[PeakSlots] " + message));
			}
		}

		public static void Warning(string message)
		{
			if (Enabled(SlotLogLevel.Warning))
			{
				Plugin.Log.LogWarning((object)("[PeakSlots] " + message));
			}
		}

		public static void Info(string message)
		{
			if (Enabled(SlotLogLevel.Info))
			{
				Plugin.Log.LogInfo((object)("[PeakSlots] " + message));
			}
		}

		public static void Debug(string message)
		{
			if (Enabled(SlotLogLevel.Debug))
			{
				Plugin.Log.LogInfo((object)("[PeakSlots] " + message));
			}
		}

		private static bool Enabled(SlotLogLevel level)
		{
			if (Plugin.Log == null)
			{
				return false;
			}
			SlotLogLevel slotLogLevel = ((Plugin.LogLevel != null) ? Plugin.LogLevel.Value : SlotLogLevel.Info);
			return level <= slotLogLevel;
		}
	}
	internal static class BuildInfo
	{
		public const string Version = "1.0.2";

		public const string Label = "";

		public const string ProductName = "PEAK SLOTS";
	}
}
namespace SlotMachines.Placement
{
	public static class MachinePlacer
	{
		public readonly struct Placement
		{
			public readonly int Id;

			public readonly MachineTier Tier;

			public readonly Vector3 Point;

			public readonly Quaternion Rotation;

			public readonly Vector3 Anchor;

			public Placement(int id, MachineTier tier, Vector3 point, Quaternion rotation, Vector3 anchor)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: 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: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				Id = id;
				Tier = tier;
				Point = point;
				Rotation = rotation;
				Anchor = anchor;
			}
		}

		private readonly struct AirportSpot
		{
			public readonly float X;

			public readonly float Y;

			public readonly float Z;

			public readonly float Yaw;

			public readonly MachineTier Tier;

			public AirportSpot(float x, float y, float z, float yaw, MachineTier tier)
			{
				X = x;
				Y = y;
				Z = z;
				Yaw = yaw;
				Tier = tier;
			}
		}

		private static readonly List<SlotMachine> Spawned = new List<SlotMachine>();

		private static readonly List<Placement> Layout = new List<Placement>();

		private static string _scene;

		private static bool _gotLayout;

		private static int _nextDevId = 10000;

		private const int WildPerBiome = 3;

		private const float WildMinDistanceToCampfire = 15f;

		private const float WildMinDistanceBetween = 20f;

		private static readonly AirportSpot[] AirportLayout = new AirportSpot[10]
		{
			new AirportSpot(-4.34f, 0.55f, 106.93f, 180f, MachineTier.Diamond),
			new AirportSpot(-3.39f, 0.55f, 106.93f, 180f, MachineTier.Gold),
			new AirportSpot(-2.44f, 0.55f, 106.93f, 180f, MachineTier.Silver),
			new AirportSpot(-1.49f, 0.55f, 106.93f, 180f, MachineTier.Bronze),
			new AirportSpot(-0.54f, 0.55f, 106.93f, 180f, MachineTier.Rusty),
			new AirportSpot(-4.34f, 0.55f, 99.35f, 0f, MachineTier.Rusty),
			new AirportSpot(-3.39f, 0.55f, 99.35f, 0f, MachineTier.Bronze),
			new AirportSpot(-2.44f, 0.55f, 99.35f, 0f, MachineTier.Silver),
			new AirportSpot(-1.49f, 0.55f, 99.35f, 0f, MachineTier.Gold),
			new AirportSpot(-0.54f, 0.55f, 99.35f, 0f, MachineTier.Diamond)
		};

		private static int GroundMask => LayerMask.GetMask(new string[3] { "Terrain", "Map", "Default" });

		private static int ClearanceMask => LayerMask.GetMask(new string[4] { "Terrain", "Map", "Default", "Character" });

		public static IReadOnlyList<SlotMachine> All => Spawned;

		public static void ClearAll()
		{
			foreach (SlotMachine item in Spawned)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)item).gameObject);
				}
			}
			Spawned.Clear();
			Layout.Clear();
			SlotMachine.Registry.Clear();
		}

		public static IEnumerator PlaceForScene(string sceneName)
		{
			ClearAll();
			_scene = sceneName;
			_gotLayout = false;
			if (sceneName == "Airport")
			{
				if (Plugin.EnableAtAirport.Value)
				{
					yield return PlaceAirport();
				}
			}
			else if (sceneName.StartsWith("Level_", StringComparison.Ordinal) && Plugin.EnableAtCampfires.Value)
			{
				yield return PlaceCampfires(sceneName);
			}
		}

		private static int SeedFor(string sceneName)
		{
			string arg = "solo";
			try
			{
				if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null)
				{
					arg = PhotonNetwork.CurrentRoom.Name ?? "solo";
				}
			}
			catch
			{
			}
			return Fnv($"{sceneName}|{arg}|{Ascents.currentAscent}");
		}

		private static int Fnv(string text)
		{
			int num = -2128831035;
			foreach (char c in text)
			{
				num = (num ^ c) * 16777619;
			}
			return num;
		}

		private static IEnumerator PlaceCampfires(string sceneName)
		{
			SlotLog.Info("[Placer] Beobachte Lagerfeuer in '" + sceneName + "' ...");
			HashSet<Campfire> handled = new HashSet<Campfire>();
			HashSet<int> handledSegments = new HashSet<int>();
			int sceneSeed = SeedFor(sceneName);
			int perFire = Mathf.Clamp(Plugin.MachinesPerCampfire.Value, 1, 3);
			int placedTotal = 0;
			while (true)
			{
				Scene val = SceneManager.GetActiveScene();
				if (!(((Scene)(ref val)).name == sceneName))
				{
					break;
				}
				if ((Object)(object)Character.localCharacter != (Object)null)
				{
					bool authority = SlotNet.IsAuthority;
					bool somethingNew = false;
					Campfire[] array = Object.FindObjectsByType<Campfire>((FindObjectsSortMode)0);
					foreach (Campfire val2 in array)
					{
						if ((Object)(object)val2 == (Object)null || handled.Contains(val2) || !((Component)val2).gameObject.activeInHierarchy)
						{
							continue;
						}
						val = ((Component)val2).gameObject.scene;
						if (!(((Scene)(ref val)).name != sceneName))
						{
							handled.Add(val2);
							somethingNew = true;
							if (authority)
							{
								placedTotal += PlaceAtCampfire(val2, sceneSeed, perFire);
							}
							yield return null;
						}
					}
					MapHandler handler = null;
					try
					{
						handler = Singleton<MapHandler>.Instance;
					}
					catch
					{
					}
					if ((Object)(object)handler != (Object)null && handler.segments != null)
					{
						for (int i = 0; i < handler.segments.Length; i++)
						{
							if (handledSegments.Contains(i))
							{
								continue;
							}
							GameObject parent = null;
							try
							{
								parent = handler.segments[i].segmentParent;
							}
							catch
							{
							}
							if (!((Object)(object)parent == (Object)null) && parent.activeInHierarchy)
							{
								handledSegments.Add(i);
								somethingNew = true;
								yield return (object)new WaitForSeconds(0.5f);
								if (authority)
								{
									placedTotal += PlaceWildInSegment(i, parent, sceneSeed);
								}
								yield return null;
							}
						}
					}
					if (authority)
					{
						if (somethingNew)
						{
							SlotNet.SendLayout(sceneName, Layout, 0);
						}
					}
					else if (somethingNew || !_gotLayout)
					{
						SlotNet.RequestLayout(sceneName);
					}
				}
				yield return (object)new WaitForSeconds(2f);
			}
			SlotLog.Info($"[Placer] '{sceneName}' verlassen - {placedTotal} Maschinen an {handled.Count} Lagerfeuern / {handledSegments.Count} Biomen gebaut.");
		}

		private static int PlaceAtCampfire(Campfire campfire, int sceneSeed, int perFire)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)campfire).transform.position;
			int num = Fnv($"{Mathf.RoundToInt(position.x * 2f)}|{Mathf.RoundToInt(position.y * 2f)}|{Mathf.RoundToInt(position.z * 2f)}");
			int num2 = (num & 0x3FFFFFFF) % 900000000 + 100000;
			Random random = new Random(sceneSeed ^ num);
			int num3 = random.Next();
			List<Vector3> list = new List<Vector3>();
			int num4 = 0;
			for (int i = 0; i < perFire; i++)
			{
				MachineTier tier = TierInfo.Roll(random);
				int num5 = num2 + i;
				if (SlotMachine.Registry.ContainsKey(num5))
				{
					continue;
				}
				if (!TryFindSpotNear(position, ((Component)campfire).transform.forward, 3.4f, num3 + i * 7919, list, out var point, out var rotation))
				{
					SlotLog.Debug("[Placer] Kein Platz an Lagerfeuer '" + ((Object)campfire).name + "' bei " + Fmt(position) + " - uebersprungen.");
				}
				else
				{
					list.Add(point);
					if (CreateAndRecord(num5, tier, point, rotation, Vector3.zero))
					{
						num4++;
					}
				}
			}
			SlotLog.Info($"[Placer] Lagerfeuer '{((Object)campfire).name}' bei {Fmt(position)}: {num4} Maschine(n).");
			return num4;
		}

		private static int PlaceWildInSegment(int segmentIndex, GameObject segmentParent, int sceneSeed)
		{
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_042e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_044c: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0488: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			List<Transform> list = new List<Transform>();
			Luggage[] array = Object.FindObjectsByType<Luggage>((FindObjectsSortMode)0);
			foreach (Luggage val in array)
			{
				if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy && ((Component)val).transform.IsChildOf(segmentParent.transform) && !list.Contains(((Component)val).transform))
				{
					list.Add(((Component)val).transform);
				}
			}
			Transform[] componentsInChildren = segmentParent.GetComponentsInChildren<Transform>();
			foreach (Transform val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && ((Object)val2).name.StartsWith("Luggage", StringComparison.Ordinal) && (!((Object)(object)val2.parent != (Object)null) || !((Object)val2.parent).name.StartsWith("Luggage", StringComparison.Ordinal)) && !list.Contains(val2))
				{
					list.Add(val2);
				}
			}
			if (list.Count == 0)
			{
				SlotLog.Info($"[Placer] Biom {segmentIndex} ('{((Object)segmentParent).name}'): keine Koffer, keine wilden Maschinen.");
				return 0;
			}
			List<Vector3> list2 = new List<Vector3>();
			Campfire[] array2 = Object.FindObjectsByType<Campfire>((FindObjectsSortMode)0);
			foreach (Campfire val3 in array2)
			{
				if ((Object)(object)val3 != (Object)null && ((Component)val3).gameObject.activeInHierarchy)
				{
					list2.Add(((Component)val3).transform.position);
				}
			}
			List<Transform> list3 = new List<Transform>();
			foreach (Transform item in list)
			{
				bool flag = false;
				foreach (Vector3 item2 in list2)
				{
					if (Vector3.Distance(item.position, item2) < 15f)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list3.Add(item);
				}
			}
			list3.Sort(delegate(Transform x, Transform y)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				int num10 = x.position.y.CompareTo(y.position.y);
				return (num10 == 0) ? string.CompareOrdinal(AnchorKey(x), AnchorKey(y)) : num10;
			});
			Random random = new Random(sceneSeed ^ (segmentIndex * 7919 + 17));
			List<Transform> list4 = new List<Transform>();
			int num = Mathf.Min(3, list3.Count);
			for (int num2 = 0; num2 < num; num2++)
			{
				int num3 = num2 * list3.Count / num;
				int num4 = (num2 + 1) * list3.Count / num;
				List<int> list5 = new List<int>();
				for (int num5 = num3; num5 < num4; num5++)
				{
					list5.Add(num5);
				}
				for (int num6 = list5.Count - 1; num6 > 0; num6--)
				{
					int num7 = random.Next(num6 + 1);
					List<int> list6 = list5;
					int i = num6;
					List<int> list7 = list5;
					int index = num7;
					int value = list5[num7];
					int value2 = list5[num6];
					list6[i] = value;
					list7[index] = value2;
				}
				foreach (int item3 in list5)
				{
					Transform val4 = list3[item3];
					bool flag2 = true;
					foreach (Transform item4 in list4)
					{
						if (Vector3.Distance(item4.position, val4.position) < 20f)
						{
							flag2 = false;
							break;
						}
					}
					if (flag2)
					{
						if (TryStandingSpot(val4.position, Quaternion.Euler(0f, val4.eulerAngles.y, 0f), val4, out var _, out var _))
						{
							list4.Add(val4);
							break;
						}
						SlotLog.Debug("[Placer]   Koffer '" + ((Object)val4).name + "' bei " + Fmt(val4.position) + " ungeeignet (kein sauberer Stand).");
					}
				}
			}
			int num8 = 0;
			foreach (Transform item5 in list4)
			{
				Quaternion val5 = Quaternion.Euler(0f, item5.eulerAngles.y, 0f);
				if (!TryStandingSpot(item5.position, val5, item5, out var point2, out var normal2))
				{
					continue;
				}
				Quaternion rotation = Quaternion.FromToRotation(Vector3.up, normal2) * val5;
				int num9 = (Fnv($"wild|{Mathf.RoundToInt(point2.x * 2f)}|{Mathf.RoundToInt(point2.y * 2f)}|{Mathf.RoundToInt(point2.z * 2f)}") & 0x3FFFFFFF) % 900000000 + 100000;
				if (!SlotMachine.Registry.ContainsKey(num9))
				{
					MachineTier machineTier = TierInfo.Roll(random);
					if (CreateAndRecord(num9, machineTier, point2, rotation, item5.position))
					{
						((Component)item5).gameObject.SetActive(false);
						num8++;
						SlotLog.Debug($"[Placer]   Koffer '{((Object)item5).name}' bei {Fmt(point2)} durch {machineTier} ersetzt");
					}
				}
			}
			SlotLog.Info($"[Placer] Biom {segmentIndex} ('{((Object)segmentParent).name}'): {num8} wilde Maschine(n), {list3.Count} Koffer an der Route.");
			return num8;
		}

		private static bool TryStandingSpot(Vector3 around, Quaternion rotation, Transform ignore, out Vector3 point, out Vector3 normal)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: 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_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			point = around;
			normal = Vector3.up;
			if (!GroundBelow(around + Vector3.up * 1f, 40f, ignore, out var best))
			{
				return false;
			}
			if (((RaycastHit)(ref best)).normal.y < 0.9f)
			{
				return false;
			}
			Vector3 point2 = ((RaycastHit)(ref best)).point;
			Vector3 val = ((RaycastHit)(ref best)).normal;
			int num = 1;
			Vector3[] array = (Vector3[])(object)new Vector3[4]
			{
				new Vector3(0.36f, 0f, 0.26f),
				new Vector3(-0.36f, 0f, 0.26f),
				new Vector3(0.36f, 0f, -0.26f),
				new Vector3(-0.36f, 0f, -0.26f)
			};
			foreach (Vector3 val2 in array)
			{
				Vector3 val3 = point2 + rotation * val2;
				if (!GroundBelow(val3 + Vector3.up * 1f, 2f, ignore, out var best2))
				{
					return false;
				}
				float num2 = point2.y - (((RaycastHit)(ref best)).normal.x * (val3.x - point2.x) + ((RaycastHit)(ref best)).normal.z * (val3.z - point2.z)) / ((RaycastHit)(ref best)).normal.y;
				if (Mathf.Abs(((RaycastHit)(ref best2)).point.y - num2) > 0.35f)
				{
					return false;
				}
				val += ((RaycastHit)(ref best2)).normal;
				num++;
			}
			Vector3 val4 = val / (float)num;
			normal = ((Vector3)(ref val4)).normalized;
			if (normal.y < 0.9f)
			{
				return false;
			}
			RaycastHit[] array2 = Physics.RaycastAll(point2 + Vector3.up * 0.3f, Vector3.up, 2.3f, ClearanceMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val5 = array2[i];
				if (!IsPartOf(((RaycastHit)(ref val5)).collider, ignore))
				{
					return false;
				}
			}
			Collider[] array3 = Physics.OverlapBox(point2 + normal * 1.2f, new Vector3(0.4f, 0.95f, 0.3f), Quaternion.FromToRotation(Vector3.up, normal) * rotation, ClearanceMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array3.Length; i++)
			{
				if (!IsPartOf(array3[i], ignore))
				{
					return false;
				}
			}
			point = point2;
			return true;
		}

		private static bool GroundBelow(Vector3 origin, float maxDistance, Transform ignore, out RaycastHit best)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			best = default(RaycastHit);
			bool flag = false;
			RaycastHit[] array = Physics.RaycastAll(origin, Vector3.down, maxDistance, GroundMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val = array[i];
				if (!IsPartOf(((RaycastHit)(ref val)).collider, ignore) && (!flag || ((RaycastHit)(ref val)).distance < ((RaycastHit)(ref best)).distance))
				{
					best = val;
					flag = true;
				}
			}
			return flag;
		}

		private static bool IsPartOf(Collider col, Transform root)
		{
			if ((Object)(object)root != (Object)null && (Object)(object)col != (Object)null)
			{
				if (!((Object)(object)((Component)col).transform == (Object)(object)root))
				{
					return ((Component)col).transform.IsChildOf(root);
				}
				return true;
			}
			return false;
		}

		private static string AnchorKey(Transform t)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = t.position;
			return string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}|{3}", ((Object)t).name, Mathf.RoundToInt(position.x * 2f), Mathf.RoundToInt(position.y * 2f), Mathf.RoundToInt(position.z * 2f));
		}

		private static bool TryFindSpotNear(Vector3 center, Vector3 forward, float distance, int seed, List<Vector3> used, out Vector3 point, out Quaternion rotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: 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_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			point = default(Vector3);
			rotation = Quaternion.identity;
			Vector3 forward2 = default(Vector3);
			((Vector3)(ref forward2))..ctor(forward.x, 0f, forward.z);
			if (((Vector3)(ref forward2)).sqrMagnitude < 0.01f)
			{
				forward2 = Vector3.forward;
			}
			((Vector3)(ref forward2)).Normalize();
			int num = new Random(seed).Next(0, 360);
			int[] obj = new int[12]
			{
				0, 60, -60, 120, -120, 180, 30, -30, 90, -90,
				150, -150
			};
			Vector3? val = null;
			Quaternion val2 = Quaternion.identity;
			int[] array = obj;
			RaycastHit val4 = default(RaycastHit);
			foreach (int num2 in array)
			{
				Vector3 val3 = Quaternion.Euler(0f, (float)(num + num2), 0f) * forward2;
				for (float num3 = distance; num3 <= distance + 1.6f; num3 += 0.8f)
				{
					if (!Physics.Raycast(center + val3 * num3 + Vector3.up * 3f, Vector3.down, ref val4, 9f, GroundMask, (QueryTriggerInteraction)1) || ((RaycastHit)(ref val4)).normal.y < 0.75f || Mathf.Abs(((RaycastHit)(ref val4)).point.y - center.y) > 2.5f)
					{
						continue;
					}
					bool flag = false;
					foreach (Vector3 item in used)
					{
						if (Vector3.Distance(item, ((RaycastHit)(ref val4)).point) < 1.4f)
						{
							flag = true;
						}
					}
					if (!flag)
					{
						Vector3 val5 = center - ((RaycastHit)(ref val4)).point;
						val5.y = 0f;
						if (((Vector3)(ref val5)).sqrMagnitude < 0.01f)
						{
							val5 = -val3;
						}
						Quaternion val6 = Quaternion.LookRotation(((Vector3)(ref val5)).normalized, Vector3.up);
						if (!val.HasValue)
						{
							val = ((RaycastHit)(ref val4)).point;
							val2 = val6;
						}
						if (!Physics.CheckBox(((RaycastHit)(ref val4)).point + Vector3.up * 1.15f, new Vector3(0.42f, 0.95f, 0.32f), val6, ClearanceMask, (QueryTriggerInteraction)1))
						{
							point = ((RaycastHit)(ref val4)).point;
							rotation = val6;
							return true;
						}
					}
				}
			}
			if (val.HasValue)
			{
				point = val.Value;
				rotation = val2;
				return true;
			}
			return false;
		}

		private static IEnumerator PlaceAirport()
		{
			yield return null;
			yield return null;
			int num = 0;
			AirportSpot[] airportLayout = AirportLayout;
			for (int i = 0; i < airportLayout.Length; i++)
			{
				AirportSpot airportSpot = airportLayout[i];
				Vector3 point = SnapToGround(new Vector3(airportSpot.X, airportSpot.Y, airportSpot.Z));
				Create(num, airportSpot.Tier, point, Quaternion.Euler(0f, airportSpot.Yaw, 0f), airport: true);
				num++;
			}
			SlotLog.Info($"[Placer] {num} Maschinen im Flughafen (fester Aufbau).");
		}

		private static Vector3 SnapToGround(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(pos + Vector3.up * 2f, Vector3.down, ref val, 8f, GroundMask, (QueryTriggerInteraction)1))
			{
				return ((RaycastHit)(ref val)).point;
			}
			return pos;
		}

		public static void SendLayoutTo(string sceneName, int actor)
		{
			if (sceneName != _scene)
			{
				SlotLog.Debug("[Placer] Anfrage fuer '" + sceneName + "', hier laeuft '" + _scene + "' - ignoriert.");
			}
			else
			{
				SlotNet.SendLayout(_scene, Layout, actor);
			}
		}

		public static void ApplyLayout(string sceneName, IReadOnlyList<Placement> layout)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if (layout == null)
			{
				return;
			}
			if (sceneName != _scene)
			{
				SlotLog.Debug("[Placer] Aufbau fuer '" + sceneName + "' erhalten, hier laeuft '" + _scene + "' - verworfen.");
				return;
			}
			_gotLayout = true;
			int num = 0;
			foreach (Placement item in layout)
			{
				if (!SlotMachine.Registry.ContainsKey(item.Id))
				{
					HideLuggageNear(item.Anchor);
					if (CreateAndRecord(item.Id, item.Tier, item.Point, item.Rotation, item.Anchor))
					{
						num++;
					}
				}
			}
			if (num > 0)
			{
				SlotLog.Info($"[Placer] Aufbau vom Master: {num} Maschine(n) dazu ({Layout.Count} insgesamt).");
			}
		}

		private static void HideLuggageNear(Vector3 anchor)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (((Vector3)(ref anchor)).sqrMagnitude < 0.01f)
			{
				return;
			}
			Transform val = null;
			float num = float.MaxValue;
			Collider[] array = Physics.OverlapSphere(anchor, 3f, -1, (QueryTriggerInteraction)2);
			foreach (Collider val2 in array)
			{
				Transform val3 = LuggageRoot(((Object)(object)val2 != (Object)null) ? ((Component)val2).transform : null);
				if (!((Object)(object)val3 == (Object)null) && ((Component)val3).gameObject.activeInHierarchy)
				{
					Vector3 val4 = val3.position - anchor;
					float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
					if (!(sqrMagnitude >= num))
					{
						num = sqrMagnitude;
						val = val3;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				SlotLog.Debug("[Placer] Kein Koffer bei " + Fmt(anchor) + " - nichts ausgeblendet.");
			}
			else
			{
				((Component)val).gameObject.SetActive(false);
			}
		}

		private static Transform LuggageRoot(Transform t)
		{
			int num = 0;
			while ((Object)(object)t != (Object)null && num < 4)
			{
				if (!((Object)(object)((Component)t).GetComponent<Luggage>() == (Object)null) || ((Object)t).name.StartsWith("Luggage", StringComparison.Ordinal))
				{
					Transform val = t;
					while ((Object)(object)val.parent != (Object)null && ((Object)val.parent).name.StartsWith("Luggage", StringComparison.Ordinal))
					{
						val = val.parent;
					}
					return val;
				}
				num++;
				t = t.parent;
			}
			return null;
		}

		private static bool CreateAndRecord(int id, MachineTier tier, Vector3 point, Quaternion rotation, Vector3 anchor)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			if ((Object)(object)Create(id, tier, point, rotation, airport: false) == (Object)null)
			{
				return false;
			}
			Layout.Add(new Placement(id, tier, point, rotation, anchor));
			return true;
		}

		private static SlotMachine Create(int id, MachineTier tier, Vector3 point, Quaternion rotation, bool airport)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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)
			try
			{
				SlotMachine slotMachine = SlotMachineBuilder.Build(id, tier, point, rotation, airport);
				Spawned.Add(slotMachine);
				SlotLog.Debug(string.Format("[Placer] #{0} {1} bei {2} yaw {3:F0}{4}", id, tier, Fmt(point), ((Quaternion)(ref rotation)).eulerAngles.y, airport ? " (Flughafen)" : ""));
				return slotMachine;
			}
			catch (Exception arg)
			{
				SlotLog.Error($"[Placer] Maschine #{id} konnte nicht gebaut werden: {arg}");
				return null;
			}
		}

		public static SlotMachine CreateAdHoc(MachineTier tier, Vector3 point, Quaternion rotation, bool airport)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return Create(_nextDevId++, tier, point, rotation, airport);
		}

		public static string Fmt(Vector3 v)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			return string.Format(CultureInfo.InvariantCulture, "{0:F2},{1:F2},{2:F2}", v.x, v.y, v.z);
		}
	}
}
namespace SlotMachines.Net
{
	public sealed class SlotNet : IOnEventCallback
	{
		public const byte EventCode = 179;

		private const byte KindSpin = 1;

		private const byte KindSpawn = 2;

		private const byte KindLayout = 3;

		private const byte KindLayoutRequest = 4;

		private static SlotNet _instance;

		private static readonly Queue<(int machineId, string itemName, int index)> SpawnQueue = new Queue<(int, string, int)>();

		private static bool _spawnRunning;

		private const float SpawnInterval = 0.45f;

		public static bool IsAuthority
		{
			get
			{
				try
				{
					return !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient;
				}
				catch
				{
					return true;
				}
			}
		}

		private static bool InRoom
		{
			get
			{
				try
				{
					return PhotonNetwork.InRoom;
				}
				catch
				{
					return false;
				}
			}
		}

		public static void Register()
		{
			if (_instance != null)
			{
				return;
			}
			_instance = new SlotNet();
			try
			{
				PhotonNetwork.AddCallbackTarget((object)_instance);
				SlotLog.Info("[Net] Photon-Callback registriert.");
			}
			catch (Exception ex)
			{
				SlotLog.Error("[Net] Registrierung fehlgeschlagen: " + ex.Message);
				_instance = null;
			}
		}

		public static void SendSpin(int machineId, SlotOutcome outcome, SlotSymbol[] symbols, string spinnerName)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom)
			{
				return;
			}
			try
			{
				object[] array = new object[7]
				{
					(byte)1,
					machineId,
					(byte)outcome,
					(byte)symbols[0],
					(byte)symbols[1],
					(byte)symbols[2],
					spinnerName ?? "SCOUT"
				};
				PhotonNetwork.RaiseEvent((byte)179, (object)array, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				SlotLog.Warning("[Net] Spin konnte nicht gesendet werden: " + ex.Message);
			}
		}

		public static void RequestItemSpawn(int machineId, string itemName, int index)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				SpawnAsMaster(machineId, itemName, index);
				return;
			}
			try
			{
				object[] array = new object[4]
				{
					(byte)2,
					machineId,
					itemName,
					index
				};
				PhotonNetwork.RaiseEvent((byte)179, (object)array, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				SlotLog.Warning("[Net] Spawn-Anfrage konnte nicht gesendet werden: " + ex.Message);
			}
		}

		public static void SendLayout(string sceneName, IReadOnlyList<MachinePlacer.Placement> layout, int targetActor)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00eb: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			if (!InRoom || layout == null || (layout.Count == 0 && targetActor <= 0))
			{
				return;
			}
			try
			{
				object[] array = new object[3 + layout.Count * 5];
				array[0] = (byte)3;
				array[1] = sceneName ?? string.Empty;
				array[2] = layout.Count;
				int num = 3;
				foreach (MachinePlacer.Placement item in layout)
				{
					array[num++] = item.Id;
					array[num++] = (byte)item.Tier;
					array[num++] = item.Point;
					array[num++] = item.Rotation;
					array[num++] = item.Anchor;
				}
				object obj;
				if (targetActor <= 0)
				{
					obj = (object)new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)0
					};
				}
				else
				{
					RaiseEventOptions val = new RaiseEventOptions();
					val.TargetActors = new int[1] { targetActor };
					obj = val;
				}
				RaiseEventOptions val2 = (RaiseEventOptions)obj;
				PhotonNetwork.RaiseEvent((byte)179, (object)array, val2, SendOptions.SendReliable);
				SlotLog.Debug(string.Format("[Net] Aufbau '{0}' mit {1} Maschine(n) verkuendet{2}.", sceneName, layout.Count, (targetActor > 0) ? $" (an Actor {targetActor})" : ""));
			}
			catch (Exception ex)
			{
				SlotLog.Warning("[Net] Aufbau konnte nicht verkuendet werden: " + ex.Message);
			}
		}

		public static void RequestLayout(string sceneName)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			if (!InRoom || IsAuthority)
			{
				return;
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)179, (object)new object[2]
				{
					(byte)4,
					sceneName ?? string.Empty
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				SlotLog.Warning("[Net] Aufbau konnte nicht angefragt werden: " + ex.Message);
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			if (photonEvent == null || photonEvent.Code != 179)
			{
				return;
			}
			try
			{
				if (!(photonEvent.CustomData is object[] array) || array.Length == 0)
				{
					return;
				}
				byte b = Convert.ToByte(array[0]);
				switch (b)
				{
				case 1:
					HandleSpin(array, photonEvent.Sender);
					break;
				case 2:
					HandleSpawn(array);
					break;
				case 3:
					HandleLayout(array);
					break;
				case 4:
					if (IsAuthority && array.Length >= 2)
					{
						MachinePlacer.SendLayoutTo(array[1] as string, photonEvent.Sender);
					}
					break;
				default:
					SlotLog.Debug($"[Net] Unbekannte Art {b}.");
					break;
				}
			}
			catch (Exception arg)
			{
				SlotLog.Error($"[Net] Ereignis fehlerhaft: {arg}");
			}
		}

		private static void HandleSpin(object[] data, int sender)
		{
			if (data.Length >= 7)
			{
				int num = Convert.ToInt32(data[1]);
				SlotOutcome slotOutcome = (SlotOutcome)Convert.ToByte(data[2]);
				SlotSymbol[] symbols = new SlotSymbol[3]
				{
					(SlotSymbol)Convert.ToByte(data[3]),
					(SlotSymbol)Convert.ToByte(data[4]),
					(SlotSymbol)Convert.ToByte(data[5])
				};
				string spinnerName = (data[6] as string) ?? "SCOUT";
				if (!SlotMachine.Registry.TryGetValue(num, out var value) || (Object)(object)value == (Object)null)
				{
					SlotLog.Warning($"[Net] Spin fuer unbekannte Maschine {num} (von Actor {sender}).");
					return;
				}
				SlotLog.Debug($"[Net] Spin von Actor {sender} an Maschine {num}: {slotOutcome}");
				value.PlaySpin(slotOutcome, symbols, sender, localSpinner: false, spinnerName);
			}
		}

		private static void HandleLayout(object[] data)
		{
			//IL_004a: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (data.Length < 3)
			{
				return;
			}
			string sceneName = data[1] as string;
			int num = Convert.ToInt32(data[2]);
			List<MachinePlacer.Placement> list = new List<MachinePlacer.Placement>(num);
			int num2 = 3;
			for (int i = 0; i < num; i++)
			{
				if (num2 + 4 >= data.Length)
				{
					break;
				}
				int id = Convert.ToInt32(data[num2++]);
				MachineTier tier = (MachineTier)Convert.ToByte(data[num2++]);
				Vector3 point = (Vector3)data[num2++];
				Quaternion rotation = (Quaternion)data[num2++];
				Vector3 anchor = (Vector3)data[num2++];
				list.Add(new MachinePlacer.Placement(id, tier, point, rotation, anchor));
			}
			MachinePlacer.ApplyLayout(sceneName, list);
		}

		private static void HandleSpawn(object[] data)
		{
			if (PhotonNetwork.IsMasterClient && data.Length >= 4)
			{
				int machineId = Convert.ToInt32(data[1]);
				string itemName = data[2] as string;
				int index = Convert.ToInt32(data[3]);
				SpawnAsMaster(machineId, itemName, index);
			}
		}

		private static void SpawnAsMaster(int machineId, string itemName, int index)
		{
			if (string.IsNullOrEmpty(itemName))
			{
				return;
			}
			SpawnQueue.Enqueue((machineId, itemName, index));
			if (_spawnRunning || (Object)(object)Plugin.Instance == (Object)null)
			{
				if ((Object)(object)Plugin.Instance == (Object)null)
				{
					DrainNow();
				}
			}
			else
			{
				_spawnRunning = true;
				((MonoBehaviour)Plugin.Instance).StartCoroutine(DrainSpawnQueue());
			}
		}

		private static IEnumerator DrainSpawnQueue()
		{
			try
			{
				while (SpawnQueue.Count > 0)
				{
					var (machineId, itemName, index) = SpawnQueue.Dequeue();
					SpawnNow(machineId, itemName, index);
					yield return (object)new WaitForSeconds(0.45f);
				}
			}
			finally
			{
				_spawnRunning = false;
			}
		}

		private static void DrainNow()
		{
			while (SpawnQueue.Count > 0)
			{
				var (machineId, itemName, index) = SpawnQueue.Dequeue();
				SpawnNow(machineId, itemName, index);
			}
		}

		private static void SpawnNow(int machineId, string itemName, int index)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(itemName))
			{
				return;
			}
			if (!SlotMachine.Registry.TryGetValue(machineId, out var value) || (Object)(object)value == (Object)null)
			{
				SlotLog.Warning($"[Net] Spawn fuer unbekannte Maschine {machineId}.");
				return;
			}
			try
			{
				Vector3 val = value.PayoutPoint(index);
				Quaternion val2 = Quaternion.LookRotation(value.PayoutForward, Vector3.up) * Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
				GameObject val3 = PhotonNetwork.InstantiateItemRoom(itemName, val, val2, true);
				if ((Object)(object)val3 == (Object)null)
				{
					SlotLog.Warning("[Net] Item '" + itemName + "' konnte nicht erzeugt werden.");
					return;
				}
				PhotonView component = val3.GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null)
				{
					Vector3 val4 = value.PayoutForward * 1.6f + Vector3.up * 1.4f;
					component.RPC("ApplyForceRPC", (RpcTarget)3, new object[2]
					{
						val4,
						Random.onUnitSphere * 0.4f
					});
				}
				SlotLog.Info($"[Net] Item '{itemName}' an Maschine {machineId} ausgezahlt.");
			}
			catch (Exception arg)
			{
				SlotLog.Error($"[Net] Spawn von '{itemName}' fehlgeschlagen: {arg}");
			}
		}
	}
}
namespace SlotMachines.Machines
{
	public static class BundleAssets
	{
		private const string ResourceName = "SlotMachines.Assets.peakslots.bundle";

		private static AssetBundle _bundle;

		private static GameObject _machinePrefab;

		private static bool _tried;

		public static GameObject MachinePrefab
		{
			get
			{
				if ((Object)(object)_machinePrefab != (Object)null || _tried)
				{
					return _machinePrefab;
				}
				_tried = true;
				try
				{
					Load();
				}
				catch (Exception arg)
				{
					SlotLog.Error($"[Bundle] Laden fehlgeschlagen: {arg}");
					_machinePrefab = null;
				}
				return _machinePrefab;
			}
		}

		private static void Load()
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SlotMachines.Assets.peakslots.bundle");
			if (stream == null)
			{
				SlotLog.Warning("[Bundle] Kein eingebettetes Bundle - prozedurales Modell wird benutzt.");
				return;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			byte[] array = memoryStream.ToArray();
			_bundle = AssetBundle.LoadFromMemory(array);
			if ((Object)(object)_bundle == (Object)null)
			{
				SlotLog.Warning($"[Bundle] AssetBundle.LoadFromMemory lieferte null ({array.Length} Bytes).");
				return;
			}
			_machinePrefab = _bundle.LoadAsset<GameObject>("SlotMachine");
			if ((Object)(object)_machinePrefab == (Object)null)
			{
				string text = string.Join(", ", _bundle.GetAllAssetNames());
				SlotLog.Warning("[Bundle] Prefab 'SlotMachine' nicht im Bundle. Inhalt: " + text);
			}
			else
			{
				RebindShaders(_machinePrefab);
				SlotLog.Info($"[Bundle] Geladen: {array.Length / 1024} KB, Prefab mit {_machinePrefab.GetComponentsInChildren<Renderer>(true).Length} Renderern.");
			}
		}

		private static void RebindShaders(GameObject prefab)
		{
			HashSet<Material> hashSet = new HashSet<Material>();
			int num = 0;
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] sharedMaterials = componentsInChildren[i].sharedMaterials;
				foreach (Material val in sharedMaterials)
				{
					if (!((Object)(object)val == (Object)null) && hashSet.Add(val) && !((Object)(object)val.shader == (Object)null))
					{
						Shader val2 = Shader.Find(((Object)val.shader).name);
						if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val.shader)
						{
							val.shader = val2;
							num++;
						}
					}
				}
			}
			SlotLog.Debug($"[Bundle] {hashSet.Count} Materialien, {num} Shader neu gebunden.");
		}
	}
	public enum MachineTier : byte
	{
		Rusty,
		Bronze,
		Silver,
		Gold,
		Diamond
	}
	public static class TierInfo
	{
		public const int Count = 5;

		public static string NameKey(MachineTier tier)
		{
			return tier switch
			{
				MachineTier.Rusty => "tier.rusty", 
				MachineTier.Bronze => "tier.bronze", 
				MachineTier.Silver => "tier.silver", 
				MachineTier.Gold => "tier.gold", 
				_ => "tier.diamond", 
			};
		}

		public static float BasePrice(MachineTier tier)
		{
			return tier switch
			{
				MachineTier.Rusty => 0.08f, 
				MachineTier.Bronze => 0.12f, 
				MachineTier.Silver => 0.18f, 
				MachineTier.Gold => 0.25f, 
				_ => 0.35f, 
			};
		}

		public static float Price(MachineTier tier)
		{
			float num = ((Plugin.PriceMultiplier != null) ? Plugin.PriceMultiplier.Value : 1f);
			return Mathf.Clamp(BasePrice(tier) * num, 0f, 0.95f);
		}

		public static int PricePercent(MachineTier tier)
		{
			return Mathf.RoundToInt(Price(tier) * 100f);
		}

		public static int SpawnWeight(MachineTier tier)
		{
			return tier switch
			{
				MachineTier.Rusty => 40, 
				MachineTier.Bronze => 30, 
				MachineTier.Silver => 18, 
				MachineTier.Gold => 9, 
				_ => 3, 
			};
		}

		public static Color BodyColor(MachineTier tier)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(tier switch
			{
				MachineTier.Rusty => new Color(0.42f, 0.3f, 0.22f), 
				MachineTier.Bronze => new Color(0.55f, 0.36f, 0.18f), 
				MachineTier.Silver => new Color(0.7f, 0.72f, 0.78f), 
				MachineTier.Gold => new Color(0.85f, 0.65f, 0.15f), 
				_ => new Color(0.12f, 0.12f, 0.16f), 
			});
		}

		public static Color TrimColor(MachineTier tier)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(tier switch
			{
				MachineTier.Rusty => new Color(0.25f, 0.18f, 0.14f), 
				MachineTier.Bronze => new Color(0.3f, 0.18f, 0.08f), 
				MachineTier.Silver => new Color(0.25f, 0.28f, 0.38f), 
				MachineTier.Gold => new Color(0.45f, 0.1f, 0.1f), 
				_ => new Color(0.35f, 0.85f, 1f), 
			});
		}

		public static Color PanelColor(MachineTier tier)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(tier switch
			{
				MachineTier.Rusty => new Color(0.16f, 0.14f, 0.12f), 
				MachineTier.Bronze => new Color(0.12f, 0.1f, 0.08f), 
				MachineTier.Silver => new Color(0.1f, 0.11f, 0.14f), 
				MachineTier.Gold => new Color(0.14f, 0.08f, 0.06f), 
				_ => new Color(0.04f, 0.04f, 0.07f), 
			});
		}

		public static Color GlowColor(MachineTier tier)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(tier switch
			{
				MachineTier.Rusty => new Color(1f, 0.55f, 0.2f), 
				MachineTier.Bronze => new Color(1f, 0.7f, 0.25f), 
				MachineTier.Silver => new Color(0.6f, 0.85f, 1f), 
				MachineTier.Gold => new Color(1f, 0.85f, 0.25f), 
				_ => new Color(0.5f, 1f, 1f), 
			});
		}

		public static float Metallic(MachineTier tier)
		{
			return tier switch
			{
				MachineTier.Rusty => 0.25f, 
				MachineTier.Bronze => 0.6f, 
				MachineTier.Silver => 0.9f, 
				MachineTier.Gold => 0.9f, 
				_ => 0.7f, 
			};
		}

		public static float Smoothness(MachineTier tier)
		{
			return tier switch
			{
				MachineTier.Rusty => 0.2f, 
				MachineTier.Bronze => 0.5f, 
				MachineTier.Silver => 0.8f, 
				MachineTier.Gold => 0.85f, 
				_ => 0.9f, 
			};
		}

		public static Rarity[] LowerPool(MachineTier tier)
		{
			return tier switch
			{
				MachineTier.Rusty => (Rarity[])(object)new Rarity[1], 
				MachineTier.Bronze => (Rarity[])(object)new Rarity[2]
				{
					default(Rarity),
					(Rarity)1
				}, 
				MachineTier.Silver => (Rarity[])(object)new Rarity[1] { (Rarity)1 }, 
				MachineTier.Gold => (Rarity[])(object)new Rarity[1] { (Rarity)2 }, 
				_ => (Rarity[])(object)new Rarity[1] { (Rarity)3 }, 
			};
		}

		public static Rarity[] MainPool(MachineTier tier)
		{
			return tier switch
			{
				MachineTier.Rusty => (Rarity[])(object)new Rarity[2]
				{
					default(Rarity),
					(Rarity)1
				}, 
				MachineTier.Bronze => (Rarity[])(object)new Rarity[2]
				{
					(Rarity)1,
					(Rarity)2
				}, 
				MachineTier.Silver => (Rarity[])(object)new Rarity[2]
				{
					(Rarity)2,
					(Rarity)3
				}, 
				MachineTier.Gold => (Rarity[])(object)new Rarity[2]
				{
					(Rarity)3,
					(Rarity)4
				}, 
				_ => (Rarity[])(object)new Rarity[2]
				{
					(Rarity)4,
					(Rarity)5
				}, 
			};
		}

		public static Rarity[] JackpotPool(MachineTier tier)
		{
			switch (tier)
			{
			case MachineTier.Rusty:
				return (Rarity[])(object)new Rarity[1] { (Rarity)2 };
			case MachineTier.Bronze:
				return (Rarity[])(object)new Rarity[1] { (Rarity)3 };
			case MachineTier.Silver:
				return (Rarity[])(object)new Rarity[1] { (Rarity)4 };
			case MachineTier.Gold:
				return (Rarity[])(object)new Rarity[2]
				{
					(Rarity)5,
					(Rarity)4
				};
			default:
			{
				Rarity[] array = new Rarity[3];
				RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
				return (Rarity[])(object)array;
			}
			}
		}

		public static MachineTier Roll(Random rng)
		{
			int num = 0;
			for (int i = 0; i < 5; i++)
			{
				num += SpawnWeight((MachineTier)i);
			}
			int num2 = rng.Next(num);
			for (int j = 0; j < 5; j++)
			{
				num2 -= SpawnWeight((MachineTier)j);
				if (num2 < 0)
				{
					return (MachineTier)j;
				}
			}
			return MachineTier.Rusty;
		}
	}
	public static class PeakStyle
	{
		private const string ShaderName = "W/Peak_Standard";

		private static Material _template;

		private static bool _searched;

		private static readonly Dictionary<string, Material> Cache = new Dictionary<string, Material>();

		private static readonly string[] PreferredNames = new string[9] { "Kiosk", "Counter", "Desk", "Table", "Chair", "Bench", "Crate", "Box", "Wood" };

		public static bool Enabled
		{
			get
			{
				if (Plugin.PeakShader != null)
				{
					return Plugin.PeakShader.Value;
				}
				return true;
			}
		}

		public static Material Template
		{
			get
			{
				if ((Object)(object)_template != (Object)null || _searched)
				{
					return _template;
				}
				_searched = true;
				try
				{
					Material val = null;
					Material[] array = Resources.FindObjectsOfTypeAll<Material>();
					foreach (Material val2 in array)
					{
						if ((Object)(object)val2 == (Object)null || (Object)(object)val2.shader == (Object)null || ((Object)val2.shader).name != "W/Peak_Standard" || ((Object)val2).name.Contains("(Instance)") || val2.GetFloat("_UseAlpha") > 0.5f)
						{
							continue;
						}
						if ((Object)(object)val == (Object)null)
						{
							val = val2;
						}
						string[] preferredNames = PreferredNames;
						foreach (string value in preferredNames)
						{
							if (((Object)val2).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
							{
								_template = val2;
								break;
							}
						}
						if ((Object)(object)_template != (Object)null)
						{
							break;
						}
					}
					if (_template == null)
					{
						_template = val;
					}
					SlotLog.Info(((Object)(object)_template != (Object)null) ? ("[Style] PEAK-Vorlage: '" + ((Object)_template).name + "'") : "[Style] Kein Material mit W/Peak_Standard geladen - URP-Fallback.");
				}
				catch (Exception ex)
				{
					SlotLog.Warning("[Style] Vorlagensuche fehlgeschlagen: " + ex.Message);
				}
				return _template;
			}
		}

		public static Material Styled(string key, Material urpFallback, Color color, float smoothness, float metallic)
		{
			//IL_013d: 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_0159: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_008d: 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)
			if (Cache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Material val = null;
			Material val2 = (Enabled ? Template : null);
			if ((Object)(object)val2 != (Object)null)
			{
				try
				{
					val = new Material(val2)
					{
						name = "PeakSlots_" + key
					};
					val.SetTexture("_BaseTexture", (Texture)null);
					val.SetFloat("_BaseTexAmount", 0f);
					val.SetFloat("_UseUV2", 0f);
					val.DisableKeyword("_USEUV2_ON");
					val.SetColor("_BaseColor", color);
					val.SetColor("_Tint", Color.white);
					val.SetFloat("_BaseSmooth", smoothness);
					val.SetFloat("_BaseMetallic", metallic);
					val.SetFloat("_Triplanar1On", 1f);
					val.SetFloat("_Triplanar2On", 1f);
					val.SetFloat("_Triplanar3On", 1f);
					val.SetFloat("_VertexColorAmount", 0f);
					val.SetFloat("_Interactable", 0f);
					val.EnableKeyword("_INTERACTABLE_ON");
				}
				catch (Exception ex)
				{
					SlotLog.Warning("[Style] Klonen fehlgeschlagen: " + ex.Message);
					val = null;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = new Material(urpFallback)
				{
					name = "PeakSlots_" + key + "_URP"
				};
				val.SetColor("_BaseColor", color);
				val.SetFloat("_Smoothness", smoothness);
				val.SetFloat("_Metallic", metallic);
				val.EnableKeyword("_EMISSION");
				val.SetColor("_EmissionColor", Color.black);
			}
			Cache[key] = val;
			return val;
		}
	}
	public static class RewardService
	{
		private sealed class ItemEntry
		{
			public string Name;

			public Rarity Rarity;

			public bool BanInSolo;
		}

		private static List<ItemEntry> _items;

		private static readonly HashSet<string> ExcludedItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly string[] CurseItems = new string[9] { "Mushroom Cluster Poison", "Mushroom Lace Poison", "Mushroom Normie Poison", "Berrynana Peel Yellow", "Dynamite", "Cursed Skull", "RitualDagger", "PandorasBox", "Bugle_Scoutmaster Variant" };

		private static readonly HashSet<string> KnownItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private const int RecentItemMemory = 3;

		private static readonly List<string> _recentItems = new List<string>();

		private static bool IsExcluded(string name)
		{
			if (name.StartsWith("GuidebookPage", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (ExcludedItems.Contains(name))
			{
				return true;
			}
			string[] curseItems = CurseItems;
			for (int i = 0; i < curseItems.Length; i++)
			{
				if (string.Equals(curseItems[i], name, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		public static void PayPrice(SlotMachine machine)
		{
			if (!machine.IsAirport)
			{
				float num = TierInfo.Price(machine.Tier);
				if (!(num <= 0f))
				{
					ApplyStatus((STATUSTYPE)0, num, "Preis");
				}
			}
		}

		public static void ApplyOutcome(SlotMachine machine, SlotOutcome outcome)
		{
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Expected O, but got Unknown
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Expected O, but got Unknown
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Expected O, but got Unknown
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Expected O, but got Unknown
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Expected O, but got Unknown
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				SlotLog.Warning("[Reward] Kein lokaler Charakter - Ergebnis verfaellt.");
				return;
			}
			Random rng = new Random();
			MachineTier tier = machine.Tier;
			if (machine.IsAirport)
			{
				switch (outcome)
				{
				case SlotOutcome.SmallWin:
					GrantItems(machine, TierInfo.LowerPool(tier), 1, rng);
					break;
				case SlotOutcome.Win:
					GrantItems(machine, TierInfo.MainPool(tier), 1, rng);
					break;
				case SlotOutcome.BigWin:
					GrantItems(machine, TierInfo.MainPool(tier), 2, rng);
					break;
				case SlotOutcome.Jackpot:
					GrantItems(machine, TierInfo.JackpotPool(tier), 1, rng);
					GrantItems(machine, TierInfo.MainPool(tier), 2, rng, 1);
					break;
				case SlotOutcome.Curse:
				case SlotOutcome.Poison:
				case SlotOutcome.Drowsy:
				case SlotOutcome.Blind:
				case SlotOutcome.Chaos:
					GrantCurseItems(machine, 1, rng);
					break;
				case SlotOutcome.BigCurse:
				case SlotOutcome.Skeleton:
					GrantCurseItems(machine, 2, rng);
					break;
				default:
					SlotLog.Info($"[Reward] Freispiel im Flughafen: {outcome} (ohne Wirkung).");
					break;
				}
				return;
			}
			switch (outcome)
			{
			case SlotOutcome.SmallWin:
				GrantItems(machine, TierInfo.LowerPool(tier), 1, rng);
				break;
			case SlotOutcome.Win:
				GrantItems(machine, TierInfo.MainPool(tier), 1, rng);
				break;
			case SlotOutcome.BigWin:
				GrantItems(machine, TierInfo.MainPool(tier), 2, rng);
				break;
			case SlotOutcome.Jackpot:
				GrantItems(machine, TierInfo.JackpotPool(tier), 1, rng);
				GrantItems(machine, TierInfo.MainPool(tier), 2, rng, 1);
				localCharacter.refs.afflictions.ClearAllStatus(true, true);
				break;
			case SlotOutcome.Heal:
				localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_HealAll
				{
					maxHealing = 0.5f,
					totalTime = 0.1f
				}, false);
				localCharacter.refs.afflictions.AdjustStatus((STATUSTYPE)0, -0.4f, false);
				break;
			case SlotOutcome.BuffStamina:
				localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_InfiniteStamina(60f), false);
				break;
			case SlotOutcome.BuffSpeed:
				localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_FasterBoi
				{
					totalTime = 45f,
					moveSpeedMod = 0.35f,
					climbSpeedMod = 0.35f,
					drowsyOnEnd = 0.08f
				}, false);
				break;
			case SlotOutcome.BuffLowGravity:
				localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_LowGravity(1, 45f), false);
				break;
			case SlotOutcome.BuffBonusStamina:
				localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_AddBonusStamina(0.5f, 0.1f), false);
				break;
			case SlotOutcome.Curse:
				ApplyStatus((STATUSTYPE)5, 0.1f + 0.025f * (float)(int)tier, "Fluch");
				GrantCurseItems(machine, 1, rng);
				break;
			case SlotOutcome.BigCurse:
				ApplyStatus((STATUSTYPE)5, 0.25f + 0.05f * (float)(int)tier, "schwerer Fluch");
				ApplyStatus((STATUSTYPE)0, 0.1f, "schwerer Fluch");
				GrantCurseItems(machine, 2, rng);
				break;
			case SlotOutcome.Poison:
				ApplyStatus((STATUSTYPE)3, 0.25f, "Gift");
				GrantCurseItems(machine, 1, rng);
				break;
			case SlotOutcome.Drowsy:
				ApplyStatus((STATUSTYPE)6, 0.35f, "Muedigkeit");
				GrantCurseItems(machine, 1, rng);
				break;
			case SlotOutcome.Blind:
				localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_Blind
				{
					totalTime = 15f
				}, false);
				GrantCurseItems(machine, 1, rng);
				break;
			case SlotOutcome.Chaos:
				GrantCurseItems(machine, 1, rng);
				localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_Chaos(0.45f, 0.15f, 0.2f, 0.1f)
				{
					totalTime = 0.1f
				}, false);
				break;
			case SlotOutcome.Skeleton:
				if (!localCharacter.data.isSkeleton)
				{
					localCharacter.data.SetSkeleton(true);
				}
				GrantCurseItems(machine, 2, rng);
				break;
			case SlotOutcome.Death:
				Character.Die();
				break;
			}
		}

		private static void ApplyStatus(STATUSTYPE type, float amount, string reason)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter == (Object)null))
			{
				bool flag = localCharacter.refs.afflictions.AddStatus(type, amount, false, true, true, false);
				SlotLog.Info(string.Format("[Reward] {0}: {1} +{2:F2} ({3}).", reason, type, amount, flag ? "angewendet" : "vom Spiel abgelehnt"));
			}
		}

		private static void GrantItems(SlotMachine machine, Rarity[] pool, int count, Random rng, int startIndex = 0)
		{
			for (int i = 0; i < count; i++)
			{
				string text = PickItem(pool, rng);
				if (text == null)
				{
					SlotLog.Warning("[Reward] Kein Item fuer Pool [" + string.Join(",", pool) + "] gefunden.");
					continue;
				}
				RememberItem(text);
				SlotLog.Info("[Reward] " + Loc.T("msg.item", "Spieler", text));
				SlotNet.RequestItemSpawn(machine.Id, text, startIndex + i);
			}
		}

		private static void GrantCurseItems(SlotMachine machine, int count, Random rng)
		{
			EnsureItems();
			List<string> list = new List<string>();
			string[] curseItems = CurseItems;
			foreach (string item in curseItems)
			{
				if (KnownItems.Contains(item))
				{
					list.Add(item);
				}
			}
			if (list.Count == 0)
			{
				SlotLog.Warning("[Reward] Kein Fluch-Item in der Datenbank gefunden.");
				return;
			}
			for (int j = 0; j < count; j++)
			{
				if (list.Count <= 0)
				{
					break;
				}
				string text = list[rng.Next(list.Count)];
				list.Remove(text);
				SlotLog.Info("[Reward] Fluch-Item: " + text);
				SlotNet.RequestItemSpawn(machine.Id, text, j);
			}
		}

		public static List<(string Name, Rarity Rarity)> PoolItems()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			EnsureItems();
			List<(string, Rarity)> list = new List<(string, Rarity)>();
			if (_items == null)
			{
				return list;
			}
			foreach (ItemEntry item2 in _items)
			{
				list.Add((item2.Name, item2.Rarity));
			}
			list.Sort(delegate((string, Rarity) a, (string, Rarity) b)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				if (a.Item2 == b.Item2)
				{
					return string.Compare(a.Item1, b.Item1, StringComparison.OrdinalIgnoreCase);
				}
				ref Rarity item = ref a.Item2;
				object target = b.Item2;
				return ((Enum)Unsafe.As<Rarity, Rarity>(ref item)/*cast due to .constrained prefix*/).CompareTo(target);
			});
			return list;
		}

		private static void RememberItem(string name)
		{
			_recentItems.Remove(name);
			_recentItems.Add(name);
			while (_recentItems.Count > 3)
			{
				_recentItems.RemoveAt(0);
			}
		}

		public static string PickItem(Rarity[] rarities, Random rng)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected I4, but got Unknown
			EnsureItems();
			if (_items.Count == 0)
			{
				return null;
			}
			bool flag = IsSolo();
			List<ItemEntry> list = new List<ItemEntry>();
			foreach (ItemEntry item in _items)
			{
				if ((!flag || !item.BanInSolo) && Array.IndexOf(rarities, item.Rarity) >= 0)
				{
					list.Add(item);
				}
			}
			if (list.Count == 0)
			{
				for (int i = 1; i <= 6; i++)
				{
					if (list.Count != 0)
					{
						break;
					}
					foreach (ItemEntry item2 in _items)
					{
						if (flag && item2.BanInSolo)
						{
							continue;
						}
						foreach (Rarity val in rarities)
						{
							if (Mathf.Abs(item2.Rarity - val) <= i)
							{
								list.Add(item2);
								break;
							}
						}
					}
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			if (_recentItems.Count > 0)
			{
				List<ItemEntry> list2 = list.FindAll((ItemEntry c) => !_recentItems.Contains(c.Name));
				if (list2.Count > 0)
				{
					list = list2;
				}
			}
			return list[rng.Next(list.Count)].Name;
		}

		private static bool IsSolo()
		{
			try
			{
				return PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.PlayerCount <= 1;
			}
			catch
			{
				return false;
			}
		}

		private static void EnsureItems()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			if (_items != null)
			{
				return;
			}
			_items = new List<ItemEntry>();
			try
			{
				ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance;
				if ((Object)(object)instance == (Object)null || instance.itemLookup == null)
				{
					SlotLog.Warning("[Reward] ItemDatabase nicht verfuegbar.");
					_items = null;
					return;
				}
				Dictionary<Rarity, int> dictionary = new Dictionary<Rarity, int>();
				foreach (KeyValuePair<ushort, Item> item in instance.itemLookup)
				{
					Item value = item.Value;
					if ((Object)(object)value == (Object)null)
					{
						continue;
					}
					LootData component = ((Component)value).GetComponent<LootData>();
					if ((Object)(object)component == (Object)null || (int)component.spawnLocations == 0)
					{
						continue;
					}
					string name = ((Object)((Component)value).gameObject).name;
					if (!string.IsNullOrEmpty(name))
					{
						KnownItems.Add(name);
						if (!IsExcluded(name))
						{
							_items.Add(new ItemEntry
							{
								Name = name,
								Rarity = component.Rarity,
								BanInSolo = component.banInSolo
							});
							dictionary.TryGetValue(component.Rarity, out var value2);
							dictionary[component.Rarity] = value2 + 1;
						}
					}
				}
				List<string> list = new List<string>();
				foreach (KeyValuePair<Rarity, int> item2 in dictionary)
				{
					list.Add($"{item2.Key}={item2.Value}");
				}
				SlotLog.Info(string.Format("[Reward] {0} Items im Pool ({1}).", _items.Count, string.Join(", ", list)));
			}
			catch (Exception arg)
			{
				SlotLog.Error($"[Reward] Item-Pool konnte nicht gelesen werden: {arg}");
				_items = null;
			}
		}
	}
	public static class SlotAudio
	{
		private const int Rate = 44100;

		private static AudioMixerGroup _sfxGroup;

		private static float _nextSearch;

		private static AudioClip _lever;

		private static AudioClip _spin;

		private static AudioClip _stop;

		private static AudioClip _win;

		private static AudioClip _jackpot;

		private static AudioClip _lose;

		private static AudioClip _curse;

		private static AudioClip _coin;

		private static AudioClip _death;

		private static AudioClip _attract;

		private static uint _noiseState = 2654435769u;

		public static float Volume
		{
			get
			{
				if (Plugin.SoundVolume == null)
				{
					return 1f;
				}
				return Mathf.Clamp(Plugin.SoundVolume.Value, 0f, 2f);
			}
		}

		public static float AttractVolume => Volume * ((Plugin.AttractVolume != null) ? Mathf.Clamp(Plugin.AttractVolume.Value, 0f, 2f) : 1f);

		public static AudioMixerGroup SfxGroup
		{
			get
			{
				if ((Object)(object)_sfxGroup != (Object)null)
				{
					return _sfxGroup;
				}
				if (Time.unscaledTime < _nextSearch)
				{
					return null;
				}
				_nextSearch = Time.unscaledTime + 5f;
				try
				{
					SFX_Player val = Object.FindFirstObjectByType<SFX_Player>();
					if ((Object)(object)val != (Object)null && (Object)(object)val.defaultMixerGroup != (Object)null)
					{
						_sfxGroup = val.defaultMixerGroup;
					}
					AudioMixer val2 = (((Object)(object)_sfxGroup != (Object)null) ? _sfxGroup.audioMixer : MasterMixer);
					if ((Object)(object)_sfxGroup == (Object)null && (Object)(object)val2 != (Object)null)
					{
						_sfxGroup = FindSfx(val2);
					}
					if ((Object)(object)_sfxGroup == (Object)null)
					{
						AudioMixerGroup val3 = null;
						AudioMixerGroup[] array = Resources.FindObjectsOfTypeAll<AudioMixerGroup>();
						float num = default(float);
						foreach (AudioMixerGroup val4 in array)
						{
							if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4.audioMixer == (Object)null) && val4.audioMixer.GetFloat("SFXVolume", ref num))
							{
								if (string.Equals(((Object)val4).name, "SFX", StringComparison.OrdinalIgnoreCase))
								{
									_sfxGroup = val4;
									break;
								}
								if ((Object)(object)val3 == (Object)null && ((Object)val4).name.IndexOf("sfx", StringComparison.OrdinalIgnoreCase) >= 0)
								{
									val3 = val4;
								}
								if (val2 == null)
								{
									val2 = val4.audioMixer;
								}
							}
						}
						if (_sfxGroup == null)
						{
							_sfxGroup = val3;
						}
					}
					if ((Object)(object)_sfxGroup == (Object)null && (Object)(object)val2 != (Object)null)
					{
						AudioMixerGroup[] array2 = val2.FindMatchingGroups("Master");
						if (array2 != null && array2.Length != 0)
						{
							_sfxGroup = array2[0];
						}
					}
					if ((Object)(object)_sfxGroup != (Object)null)
					{
						SlotLog.Info("[Audio] Ausgabe ueber Mixer-Gruppe '" + ((Object)_sfxGroup).name + "' (" + ((Object)_sfxGroup.audioMixer).name + ") - folgt Master- und SFX-Regler.");
					}
					else
					{
						SlotLog.Warning("[Audio] Keine Mixergruppe gefunden - Lautstaerke folgt den Spielreglern nicht (Config: Audio.Volume).");
					}
				}
				catch (Exception ex)
				{
					SlotLog.Warning("[Audio] Mixer-Suche fehlgeschlagen: " + ex.Message);
				}
				return _sfxGroup;
			}
		}

		private static AudioMixer MasterMixer
		{
			get
			{
				try
				{
					AudioMixerGroup val = (((Object)(object)SingletonAsset<StaticReferences>.Instance != (Object)null) ? SingletonAsset<StaticReferences>.Instance.masterMixerGroup : null);
					return ((Object)(object)val != (Object)null) ? val.audioMixer : null;
				}
				catch (Exception ex)
				{
					SlotLog.Debug("[Audio] StaticReferences nicht lesbar: " + ex.Message);
					return null;
				}
			}
		}

		public static AudioClip Lever => _lever ?? (_lever = Build("PeakSlots_Lever", 0.3f, (float t, float d) => Noise(t) * Env(t, 0f, 0.015f, 30f) * 0.6f + Mathf.Sin(MathF.PI * 260f * t) * Env(t, 0.01f, 0.12f, 14f) * 0.7f));

		public static AudioClip Spin => _spin ?? (_spin = Build("PeakSlots_Spin", 1.1f, delegate(float t, float d)
		{
			float num = t % 0.055f;
			float num2 = Mathf.Sin(MathF.PI * 3800f * num) * Mathf.Exp((0f - num) * 260f);
			float num3 = Mathf.Sin(MathF.PI * 140f * t) * 0.08f;
			return num2 * 0.45f + num3;
		}));

		public static AudioClip Stop => _stop ?? (_stop = Build("PeakSlots_Stop", 0.22f, (float t, float d) => Mathf.Sin(MathF.PI * 360f * t) * Env(t, 0f, 0.14f, 18f) * 0.8f + Noise(t) * Env(t, 0f, 0.01f, 60f) * 0.4f));

		public static AudioClip Win => _win ?? (_win = Build("PeakSlots_Win", 0.95f, (float t, float d) => Arpeggio(t, new float[4] { 523.25f, 659.25f, 783.99f, 1046.5f }, 0.17f, 0.9f)));

		public static AudioClip Jackpot => _jackpot ?? (_jackpot = Build("PeakSlots_Jackpot", 2.4f, delegate(float t, float d)
		{
			if (t < 1.1f)
			{
				return Arpeggio(t, new float[7] { 523.25f, 659.25f, 783.99f, 1046.5f, 1318.5f, 1568f, 2093f }, 0.11f, 0.9f);
			}
			float num = t - 1.1f;
			float num2 = Mathf.Sin(MathF.PI * 2093f * num) + Mathf.Sin(MathF.PI * 2637f * num) + Mathf.Sin(MathF.PI * 3136f * num);
			float num3 = 1f + 0.02f * Mathf.Sin(MathF.PI * 12f * num);
			return num2 / 3f * num3 * Env(num, 0.02f, 1.2f, 2.2f) * 0.8f;
		}));

		public static AudioClip Lose => _lose ?? (_lose = Build("PeakSlots_Lose", 0.7f, (float t, float d) => Saw(Mathf.Lerp(170f, 85f, t / d), t) * Env(t, 0.01f, 0.6f, 3f) * 0.45f));

		public static AudioClip Curse => _curse ?? (_curse = Build("PeakSlots_Curse", 1.4f, delegate(float t, float d)
		{
			float num = Mathf.Lerp(240f, 95f, t / d);
			float num2 = Mathf.Sin(MathF.PI * 2f * num * t);
			float num3 = Mathf.Sin(MathF.PI * 2f * (num * 1.06f) * t);
			float num4 = 0.6f + 0.4f * Mathf.Sin(MathF.PI * 18f * t);
			return (num2 + num3) * 0.5f * num4 * Env(t, 0.05f, 1.2f, 1.8f) * 0.7f;
		}));

		public static AudioClip Coin => _coin ?? (_coin = Build("PeakSlots_Coin", 0.5f, delegate(float t, float d)
		{
			float num = ((t < 0.22f) ? t : (t - 0.22f));
			return (Mathf.Sin(MathF.PI * 4700f * num) + 0.6f * Mathf.Sin(MathF.PI * 7040f * num)) * Env(num, 0f, 0.2f, 22f) * 0.5f;
		}));

		public static AudioClip Death => _death ?? (_death = Build("PeakSlots_Death", 1.8f, (float t, float d) => (Saw(Mathf.Lerp(110f, 40f, t / d), t) * 0.5f + Noise(t) * 0.15f) * Env(t, 0.05f, 1.5f, 1.5f) * 0.8f));

		public static AudioClip Attract => _attract ?? (_attract = Build("PeakSlots_Attract", 6f, delegate(float t, float d)
		{
			float[] array = new float[16]
			{
				523.25f, 659.25f, 783.99f, 1046.5f, 1318.5f, 1046.5f, 783.99f, 659.25f, 587.33f, 698.46f,
				880f, 1174.7f, 1318.5f, 1046.5f, 783.99f, 523.25f
			};
			float num = 0f;
			int num2 = (int)(t / 0.16f);
			if (num2 < array.Length)
			{
				float num3 = t - (float)num2 * 0.16f;
				float num4 = array[num2];
				float num5 = Mathf.Sin(MathF.PI * 2f * num4 * num3) + 0.4f * Mathf.Sin(MathF.PI * 2f * num4 * 2f * num3) + 0.12f * Mathf.Sin(MathF.PI * 2f * num4 * 4f * num3);
				num += num5 / 1.5f * Env(num3, 0.004f, 0.03f, 9f) * 0.55f;
			}
			float num6 = t - 3f;
			if (num6 >= 0f)
			{
				int num7 = (int)(num6 / 0.16f);
				if (num7 < array.Length)
				{
					float num8 = num6 - (float)num7 * 0.16f;
					float num9 = array[num7] * 2f;
					num += Mathf.Sin(MathF.PI * 2f * num9 * num8) * Env(num8, 0.003f, 0.02f, 14f) * 0.22f;
				}
			}
			float[] array2 = new float[2] { 2.7f, 5.75f };
			foreach (float num10 in array2)
			{
				float num11 = t - num10;
				if (num11 >= 0f && num11 < 0.25f)
				{
					num += (Mathf.Sin(MathF.PI * 4700f * num11) + 0.5f * Mathf.Sin(MathF.PI * 7040f * num11)) * Env(num11, 0f, 0.05f, 24f) * 0.25f;
				}
			}
			float num12 = t % 0.09f;
			return num + Mathf.Sin(MathF.PI * 3000f * num12) * Mathf.Exp((0f - num12) * 300f) * 0.06f;
		}));

		private static AudioMixerGroup FindSfx(AudioMixer mixer)
		{
			float num = default(float);
			if ((Object)(object)mixer == (Object)null || !mixer.GetFloat("SFXVolume", ref num))
			{
				return null;
			}
			string[] array = new string[3] { "SFX", "Sfx", "sfx" };
			foreach (string text in array)
			{
				AudioMixerGroup[] array2 = mixer.FindMatchingGroups(text);
				if (array2 != null && array2.Length != 0)
				{
					return array2[0];
				}
			}
			return null;
		}

		public static bool Route(AudioSource source)
		{
			if ((Object)(object)source == (Object)null)
			{
				return false;
			}
			AudioMixerGroup sfxGroup = SfxGroup;
			if ((Object)(object)sfxGroup == (Object)null)
			{
				return false;
			}
			source.outputAudioMixerGroup = sfxGroup;
			return true;
		}

		private static float Env(float t, float attack, float hold, float decayRate)
		{
			if (t < 0f)
			{
				return 0f;
			}
			if (t < attack)
			{
				return t / attack;
			}
			float num = t - attack - hold;
			if (!(num <= 0f))
			{
				return Mathf.Exp((0f - num) * decayRate);
			}
			return 1f;
		}

		private static float Saw(float freq, float t)
		{
			float num = freq * t % 1f;
			return 2f * num - 1f;
		}

		private static float Noise(float t)
		{
			_noiseState ^= _noiseState << 13;
			_noiseState ^= _noiseState >> 17;
			_noiseState ^= _noiseState << 5;
			return (float)_noiseState / 4.2949673E+09f * 2f - 1f;
		}

		private static float Arpeggio(float t, float[] notes, float noteLength, float gain)
		{
			int num = Mathf.Min(notes.Length - 1, (int)(t / noteLength));
			float num2 = t - (float)num * noteLength;
			float num3 = notes[num];
			float num4 = Mathf.Sin(MathF.PI * 2f * num3 * num2) + 0.35f * Mathf.Sin(MathF.PI * 2f * num3 * 2f * num2) + 0.15f * Mathf.Sin(MathF.PI * 2f * num3 * 3f * num2);
			float hold = ((num == notes.Length - 1) ? 0.5f : 0.02f);
			return num4 / 1.5f * Env(num2, 0.005f, hold, 12f) * gain;
		}

		private static AudioClip Build(string name, float seconds, Func<float, float, float> generator)
		{
			int num = (int)(seconds * 44100f);
			float[] array = new float[num];
			float num2 = 0.001f;
			for (int i = 0; i < num; i++)
			{
				float arg =