plugins/Echo/Echo.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Duplicator;
using EntityStates.Scrapper;
using HG;
using Microsoft.CodeAnalysis;
using On.EntityStates.Duplicator;
using On.EntityStates.Scrapper;
using On.RoR2;
using On.RoR2.Items;
using On.RoR2.UI;
using R2API;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.Utils;
using RoR2;
using RoR2.Stats;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

[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("Echo")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Echo")]
[assembly: AssemblyTitle("Echo")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Echo
{
	[BepInPlugin("com.echo.Echo", "Echo", "1.3.2")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Echo : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static EventCallback <>9__84_0;

			public static Comparison<(string Name, double Value)> <>9__95_0;

			internal void <PlaySoundLocal>b__84_0(object cookie, AkCallbackType type, AkCallbackInfo info)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = (GameObject)((cookie is GameObject) ? cookie : null);
				if (val != null)
				{
					AkSoundEngine.SetGameObjectOutputBusVolume(val, val, 1f);
				}
			}

			internal int <ShowStat>b__95_0((string Name, double Value) a, (string Name, double Value) b)
			{
				return b.Value.CompareTo(a.Value);
			}
		}

		public const string PluginGUID = "com.echo.Echo";

		public const string PluginName = "Echo";

		public const string PluginVersion = "1.3.2";

		internal static ManualLogSource Log;

		internal static Echo Instance;

		private ConfigEntry<bool> _bossKillEnabled;

		private ConfigEntry<bool> _teleporterStartEnabled;

		private ConfigEntry<bool> _teleporterChargedEnabled;

		private ConfigEntry<bool> _playerDeathEnabled;

		private ConfigEntry<bool> _chatEvetEnabled;

		private ConfigEntry<bool> _chatHayirEnabled;

		private ConfigEntry<bool> _chat31Enabled;

		private ConfigEntry<bool> _tiltedPlayerEnabled;

		private ConfigEntry<bool> _equipmentDroneEnabled;

		private ConfigEntry<bool> _rareItemDropEnabled;

		private ConfigEntry<bool> _lastSurvivorEnabled;

		private ConfigEntry<bool> _damageMilestoneEnabled;

		private ConfigEntry<bool> _killMilestoneEnabled;

		private ConfigEntry<bool> _eliteKillMilestoneEnabled;

		private ConfigEntry<bool> _runSummaryEnabled;

		private ConfigEntry<bool> _nearDeathEnabled;

		private ConfigEntry<float> _nearDeathThreshold;

		private ConfigEntry<bool> _deathDetailsEnabled;

		private ConfigEntry<KeyCode> _reportCloseKey;

		private ConfigEntry<float> _volumeMultiplier;

		internal static KeyCode ReportCloseKey = (KeyCode)283;

		private readonly Dictionary<NetworkUser, int> _deathCounts = new Dictionary<NetworkUser, int>();

		private bool _lastSurvivorTriggered;

		private bool _testRunning;

		private readonly Dictionary<NetworkUser, int> _damageMilestoneTier = new Dictionary<NetworkUser, int>();

		private readonly Dictionary<NetworkUser, int> _killMilestoneTier = new Dictionary<NetworkUser, int>();

		private readonly Dictionary<NetworkUser, int> _eliteKillMilestoneTier = new Dictionary<NetworkUser, int>();

		private readonly Dictionary<NetworkUser, int> _deathMilestoneTier = new Dictionary<NetworkUser, int>();

		private readonly Dictionary<NetworkUser, float> _lastHealthFraction = new Dictionary<NetworkUser, float>();

		private const double DamageMilestoneBase = 100000.0;

		private const double DamageMilestoneFactor = 10.0;

		private const double KillMilestoneBase = 100.0;

		private const double KillMilestoneFactor = 5.0;

		private const int EliteKillMilestoneBase = 10;

		private const double EliteKillMilestoneFactor = 2.0;

		private const int DeathMilestoneBase = 5;

		private const double DeathMilestoneFactor = 2.0;

		private StatDef _damageStatDefCache;

		private StatDef _minionDamageStatDefCache;

		private StatDef _killStatDefCache;

		private StatDef _eliteKillStatDefCache;

		private static readonly string[] BossKillMessages = new string[15]
		{
			"{0} boss'u yerle bir etti!", "{0} teleporter canavarını haklayarak destan yazdı!", "{0} boss'a göz açtırmadı!", "{0} boss avında zirveye çıktı!", "{0} teleporter'ı temizledi, sıra kaçışta!", "{0} boss katliamı yaptı!", "{0} yine iş başında: boss düştü!", "{0} boss'u tek başına eritti!", "{0} korkusuzca boss'un üstüne yürüdü ve kazandı!", "{0} teleporter bekçisini alt etti!",
			"{0} boss'u sahadan sildi!", "{0} yine sahneye çıktı, boss düştü!", "{0} boss karşısında aman vermedi!", "{0} teleporter savaşını kazandı!", "{0} boss'u tarihe gömdü!"
		};

		private static readonly string[] DamageMilestoneMessages = new string[15]
		{
			"{0} {1} damage'a ulaştı, seriye bağladı!", "{0} {1} hasarla destan yazıyor!", "{0} {1} damage'ı geçti, aman vermiyor!", "{0} sahayı yakıp yıkıyor: {1} damage!", "{0} {1} hasara ulaştı, kimse durduramıyor!", "{0} damage sayacını {1}'a taşıdı, çılgın gidiyor!", "{0} {1} damage ile liderliği kimseye bırakmıyor!", "{0} {1} hasar bastı, ortalık savaş alanı!", "{0} {1}'a ulaştı, hız kesmiyor!", "{0} {1} damage'la tarih yazıyor!",
			"{0} sayaç {1}'ı gösterdi, canavar gibi gidiyor!", "{0} {1} hasarla resmen uçuyor!", "{0} {1} damage'a vardı, rakip tanımıyor!", "{0} {1}'ı geçti, bu performansa diyecek yok!", "{0} {1} damage ile efsane yazıyor!"
		};

		private static readonly string[] KillMilestoneMessages = new string[15]
		{
			"{0} {1} kill'e ulaştı, seriye bağladı!", "{0} {1} canavar avladı, durdurulamıyor!", "{0} {1} kill ile ortalığı kasıp kavuruyor!", "{0} {1} avla listeye adını yazdırdı!", "{0} {1} kill'de, aman vermiyor!", "{0} {1} canlıyı sahadan sildi!", "{0} {1} kill'e ulaştı, katliam devam ediyor!", "{0} {1} avla zirvede!", "{0} {1} kill'i geçti, hız kesmiyor!", "{0} {1} canavarı gönderdi!",
			"{0} {1} kill'de, resmen makine gibi!", "{0} {1} avla destan yazıyor!", "{0} {1} kill'e vardı, kimse yaklaşamıyor!", "{0} {1} canavarı temizledi, sahne onun!", "{0} {1} kill ile tarihe geçiyor!"
		};

		private static readonly string[] EliteKillMilestoneMessages = new string[15]
		{
			"{0} {1} elite avladı, sahayı temizliyor!", "{0} {1} elite'i devirdi, korkusuz!", "{0} {1} elite kill'e ulaştı, zorluk tanımıyor!", "{0} {1} elite'i haklayarak fark yaratıyor!", "{0} {1} elite avıyla listeye adını yazdırdı!", "{0} {1} elite düşürdü, ortalık savaş alanı!", "{0} {1} elite'i sahadan sildi!", "{0} {1} elite kill'de, güçlüler ona pes ediyor!", "{0} {1} elite avladı, sınıf atlıyor!", "{0} {1} elite'i tek başına eritti!",
			"{0} {1} elite kill'e vardı, rakip tanımıyor!", "{0} {1} elite düşürdü, destan yazıyor!", "{0} {1} elite'i temizledi, hız kesmiyor!", "{0} {1} elite avıyla zirvede!", "{0} {1} elite kill ile tarihe geçiyor!"
		};

		private static readonly string[] DeathMilestoneMessages = new string[15]
		{
			"{0} {1}. kez öldü, iyi gidiyor... ters yönde!", "{0} {1} ölümle rekor kırıyor (kötü anlamda)!", "{0} {1}. kez yerle bir oldu!", "{0} {1} ölüm, zemin ona alıştı artık!", "{0} {1}. ölümüyle sınıf atlıyor... yerin dibine!", "{0} {1} kez can verdi, pes etmiyor ama yer de öyle!", "{0} {1}. ölüm, artık spawn ekranı ev gibi!", "{0} {1} kez öldü, respawn butonuna aşık olmuş olmalı!", "{0} {1}. kez toprakla buluştu!", "{0} {1} ölümle liderlik yarışında (yanlış kategoride)!",
			"{0} {1}. kez öldü, azim var ama şans yok!", "{0} {1} ölüm, artık bu bir yetenek!", "{0} {1}. kez sahneden erken ayrıldı!", "{0} {1} ölümle destan yazıyor, kötü bir destan!", "{0} {1}. kez öldü, tilt modu aktif!"
		};

		private static readonly string[] NearDeathMessages = new string[15]
		{
			"{0} ölümden döndü!", "{0} beyaz ışığı gördü, geri geldi!", "{0} son anda kurtuldu!", "{0} ecel terini döktü ama ayakta!", "{0} mezara bir adım kala geri çekildi!", "{0} az kalsın gidiyordu, şans yaver gitti!", "{0} kıl payı hayatta kaldı!", "{0} tabutun kapağını kapatmadı!", "{0} sınırda dans etti, düşmedi!", "{0} can havliyle kurtuldu!",
			"{0} bir kez daha şansını denedi, kazandı!", "{0} ölümle göz göze geldi, geri adım attı!", "{0} son saniyede toparladı!", "{0} uçurumun kenarından döndü!", "{0} bu sefer ecel yakalayamadı!"
		};

		private static readonly Dictionary<DotIndex, string> DotNames = new Dictionary<DotIndex, string>
		{
			[(DotIndex)0] = "kanama",
			[(DotIndex)6] = "şiddetli kanama",
			[(DotIndex)1] = "yanma",
			[(DotIndex)7] = "şiddetli yanma",
			[(DotIndex)3] = "yanma",
			[(DotIndex)2] = "cehennem ateşi",
			[(DotIndex)4] = "zehir",
			[(DotIndex)5] = "çürüme",
			[(DotIndex)8] = "kırık",
			[(DotIndex)9] = "lunar yıkım",
			[(DotIndex)10] = "donma",
			[(DotIndex)11] = "elektrik"
		};

		private static readonly Dictionary<string, string> StatAliases = new Dictionary<string, string>
		{
			["kills"] = "totalKills",
			["deaths"] = "totalDeaths",
			["minion_kills"] = "totalMinionKills",
			["elite_kills"] = "totalEliteKills",
			["total_damage"] = "totalDamageDealt",
			["minion_damage"] = "totalMinionDamageDealt",
			["highest_damage"] = "highestDamageDealt",
			["damage_taken"] = "totalDamageTaken",
			["healing"] = "totalHealthHealed",
			["gold"] = "goldCollected",
			["items"] = "totalItemsCollected",
			["distance"] = "totalDistanceTraveled",
			["time_alive"] = "totalTimeAlive",
			["stages"] = "totalStagesCompleted"
		};

		private const string PrefixColor = "#FDA4AF";

		private const string DamageColor = "#FB923C";

		private const string HealthColor = "#F87171";

		private const string HealColor = "#34D399";

		private const string UtilityColor = "#38BDF8";

		private const string AccentColor = "#A78BFA";

		private const string MutedColor = "#94A3B8";

		private const string BossColor = "#FBBF24";

		private const string KillColor = "#F43F5E";

		private const string EliteKillColor = "#2DD4BF";

		private const string NearDeathColor = "#FB7185";

		private static readonly string[] NameColors = new string[10] { "#38BDF8", "#FB923C", "#34D399", "#A78BFA", "#FBBF24", "#67E8F9", "#E879F9", "#A3E635", "#F472B6", "#818CF8" };

		private static readonly Dictionary<string, string> StatColorMap = new Dictionary<string, string>
		{
			["kills"] = "#FB923C",
			["minion_kills"] = "#FB923C",
			["elite_kills"] = "#FB923C",
			["total_damage"] = "#FB923C",
			["minion_damage"] = "#FB923C",
			["highest_damage"] = "#FB923C",
			["damage_taken"] = "#F87171",
			["deaths"] = "#F87171",
			["healing"] = "#34D399",
			["gold"] = "#38BDF8",
			["items"] = "#38BDF8",
			["distance"] = "#38BDF8",
			["time_alive"] = "#38BDF8",
			["stages"] = "#38BDF8"
		};

		private static readonly (string EventName, string Label)[] TestSequence = new(string, string)[12]
		{
			("Play_SoundAlert_BossKill", "Boss Kill"),
			("Play_SoundAlert_TeleporterStart", "Teleporter Start"),
			("Play_SoundAlert_TeleporterCharged", "Teleporter Charged"),
			("Play_SoundAlert_PlayerDeath", "Player Death"),
			("Play_SoundAlert_ChatEvet", "Chat Evet"),
			("Play_SoundAlert_ChatHayir", "Chat Hayır"),
			("Play_SoundAlert_Chat31", "Chat 31"),
			("Play_SoundAlert_TiltedPlayer", "Tilted Player"),
			("Play_SoundAlert_EquipmentDrone", "Equipment Drone"),
			("Play_SoundAlert_RareItemDrop", "Rare Item Drop"),
			("Play_SoundAlert_LastSurvivor", "Last Survivor"),
			("Play_SoundAlert_PlayerDeathBass", "Player Death (BASS BOOSTED)")
		};

		private static string Colorize(string text, string hex)
		{
			return "<color=" + hex + ">" + text + "</color>";
		}

		private static string ColorForName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return NameColors[0];
			}
			int num = 0;
			foreach (char c in name)
			{
				num = num * 31 + c;
			}
			int num2 = Math.Abs(num) % NameColors.Length;
			return NameColors[num2];
		}

		private static string ColorizeName(string name)
		{
			return Colorize(name, ColorForName(name));
		}

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			InitConfig();
			NetworkingAPI.RegisterMessageType<EchoNetMessage>();
			NetworkingAPI.RegisterMessageType<EchoReportMessage>();
			NetworkingAPI.RegisterMessageType<EchoGambleMessage>();
			NetworkingAPI.RegisterMessageType<EchoGambleRequest>();
			NetworkingAPI.RegisterMessageType<EchoForgeRequest>();
			NetworkingAPI.RegisterMessageType<EchoForgeSyncMessage>();
			NetworkingAPI.RegisterMessageType<EchoBulkPrintRequest>();
			NetworkingAPI.RegisterMessageType<EchoPowerMessage>();
			EchoForgeStacks.Install();
			EchoForgeVisuals.Install();
			EchoStations.Install();
			EchoBulkPrint.Install();
			EchoSetTracker.Install();
			EchoSetScoreboard.Install();
			EchoPower.Install();
			EchoPowerHud.Install();
			EchoJumpscare.Install();
			EchoPanels.Install();
			HookEvents();
			Log.LogInfo((object)"Echo yüklendi!");
		}

		private void Start()
		{
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(LoadBank));
			((MonoBehaviour)this).StartCoroutine(MilestoneWatcherCoroutine());
		}

		private IEnumerator MilestoneWatcherCoroutine()
		{
			while (true)
			{
				yield return (object)new WaitForSeconds(5f);
				if (NetworkServer.active)
				{
					CheckDamageAndKillMilestones();
				}
			}
		}

		private void CheckDamageAndKillMilestones()
		{
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster val = ((instance != null) ? instance.master : null);
				NetworkUser val2 = ((instance != null) ? instance.networkUser : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					continue;
				}
				PlayerStatsComponent val3 = PlayerStatsComponent.FindMasterStatsComponent(val);
				if (val3?.currentStats == null)
				{
					continue;
				}
				if (_damageMilestoneEnabled.Value)
				{
					if (_damageStatDefCache == null)
					{
						_damageStatDefCache = StatDef.Find("totalDamageDealt");
					}
					if (_minionDamageStatDefCache == null)
					{
						_minionDamageStatDefCache = StatDef.Find("totalMinionDamageDealt");
					}
					if (_damageStatDefCache != null)
					{
						double num = val3.currentStats.GetStatValueAsDouble(_damageStatDefCache);
						if (_minionDamageStatDefCache != null)
						{
							num += val3.currentStats.GetStatValueAsDouble(_minionDamageStatDefCache);
						}
						CheckMilestone(_damageMilestoneTier, val2, num, 100000.0, 10.0, DamageMilestoneMessages, "#FB923C");
					}
				}
				if (_killMilestoneEnabled.Value)
				{
					if (_killStatDefCache == null)
					{
						_killStatDefCache = StatDef.Find("totalKills");
					}
					if (_killStatDefCache != null)
					{
						double statValueAsDouble = val3.currentStats.GetStatValueAsDouble(_killStatDefCache);
						CheckMilestone(_killMilestoneTier, val2, statValueAsDouble, 100.0, 5.0, KillMilestoneMessages, "#F43F5E");
					}
				}
				if (_eliteKillMilestoneEnabled.Value)
				{
					if (_eliteKillStatDefCache == null)
					{
						_eliteKillStatDefCache = StatDef.Find("totalEliteKills");
					}
					if (_eliteKillStatDefCache != null)
					{
						double statValueAsDouble2 = val3.currentStats.GetStatValueAsDouble(_eliteKillStatDefCache);
						CheckMilestone(_eliteKillMilestoneTier, val2, statValueAsDouble2, 10.0, 2.0, EliteKillMilestoneMessages, "#2DD4BF");
					}
				}
			}
		}

		private static int TierForValue(double value, double baseThreshold, double factor)
		{
			if (value < baseThreshold)
			{
				return -1;
			}
			return (int)Math.Floor(Math.Log(value / baseThreshold, factor));
		}

		private void CheckMilestone(Dictionary<NetworkUser, int> tierMap, NetworkUser user, double value, double baseThreshold, double factor, string[] messages, string color)
		{
			int num = TierForValue(value, baseThreshold, factor);
			if (num >= 0)
			{
				int value2;
				int num2 = (tierMap.TryGetValue(user, out value2) ? value2 : (-1));
				if (num > num2)
				{
					tierMap[user] = num;
					double value3 = baseThreshold * Math.Pow(factor, num);
					string text = string.Format(messages[Random.Range(0, messages.Length)], ColorizeName(user.userName), FormatNumber(value3));
					SendRaw(Colorize(text, color));
				}
			}
		}

		private static string FormatNumber(double value)
		{
			if (value >= 1000000000.0)
			{
				return (value / 1000000000.0).ToString("0.#") + "B";
			}
			if (value >= 1000000.0)
			{
				return (value / 1000000.0).ToString("0.#") + "M";
			}
			if (value >= 1000.0)
			{
				return (value / 1000.0).ToString("0.#") + "K";
			}
			return value.ToString("0");
		}

		private static string FormatDuration(float seconds)
		{
			if (seconds < 0f)
			{
				seconds = 0f;
			}
			TimeSpan timeSpan = TimeSpan.FromSeconds(seconds);
			if (!(timeSpan.TotalHours >= 1.0))
			{
				return $"{timeSpan.Minutes}:{timeSpan.Seconds:00}";
			}
			return $"{(int)timeSpan.TotalHours}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00}";
		}

		private string BuildDeathDetail(DamageReport report)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_004c: 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_0195: Invalid comparison between Unknown and I4
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			string text = null;
			if (!((Object)(object)report.attackerBody != (Object)null))
			{
				text = (((int)report.dotType == -1 || !DotNames.TryGetValue(report.dotType, out string value)) ? "çevre" : value);
			}
			else
			{
				text = report.attackerBody.GetDisplayName();
				if (report.attackerBody.isElite)
				{
					text += " (elit)";
				}
			}
			list.Add(Colorize("katil:", "#94A3B8") + " " + Colorize(text, "#FB923C"));
			if (report.damageDealt > 0f)
			{
				string text2 = Colorize(FormatNumber(report.damageDealt), "#FB923C") + " hasar";
				float num = (((Object)(object)report.victimBody.healthComponent != (Object)null) ? report.victimBody.healthComponent.fullCombinedHealth : 0f);
				if (num > 0f)
				{
					float num2 = report.damageDealt / num * 100f;
					text2 = text2 + " " + Colorize($"(max canının %{num2:0}'ı)", "#F87171");
					if (num2 >= 200f)
					{
						list.Add(Colorize("AŞIRI ÖLDÜRME", "#FBBF24"));
					}
				}
				list.Insert(1, text2);
			}
			if (report.damageInfo != null && report.damageInfo.crit)
			{
				list.Add(Colorize("KRİTİK", "#FBBF24"));
			}
			if ((Object)(object)report.attackerBody != (Object)null && (int)report.dotType != -1 && DotNames.TryGetValue(report.dotType, out string value2))
			{
				list.Add(Colorize(value2, "#FB923C"));
			}
			if (list.Count <= 0)
			{
				return null;
			}
			return string.Join(Colorize(" · ", "#94A3B8"), list);
		}

		private void InitConfig()
		{
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			_bossKillEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "BossKillSound", true, "Boss ölünce ses çalsın mı?");
			_teleporterStartEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "TeleporterStartSound", true, "Teleporter aktive olunca ses çalsın mı?");
			_teleporterChargedEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "TeleporterChargedSound", true, "Teleporter tamamlanınca ses çalsın mı?");
			_playerDeathEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "PlayerDeathSound", true, "Oyuncu ölünce ses çalsın mı?");
			_chatEvetEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "ChatEvetSound", true, "Chate 'evet' yazılınca ses çalsın mı?");
			_chatHayirEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "ChatHayirSound", true, "Chate 'hayır' yazılınca ses çalsın mı?");
			_chat31Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "Chat31Sound", true, "Chate '31' yazılınca ses çalsın mı?");
			_tiltedPlayerEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "TiltedPlayerSound", true, "Oyuncu 5+ kez ölünce ses çalsın mı?");
			_equipmentDroneEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "EquipmentDroneSound", true, "Equipment Drone chate yazınca ses çalsın mı?");
			_rareItemDropEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "RareItemDropSound", true, "Kırmızı/sarı/mor item alındığında ses çalsın mı?");
			_lastSurvivorEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "LastSurvivorSound", true, "Son hayatta kalan 1 kişi olunca ses çalsın mı?");
			_damageMilestoneEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Milestones", "DamageMilestone", true, "Damage 100K/1M/10M... eşiklerini geçince chate duyuru yapsın mı?");
			_killMilestoneEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Milestones", "KillMilestone", true, "Kill sayısı 100/1000/10000... eşiklerini geçince chate duyuru yapsın mı?");
			_eliteKillMilestoneEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Milestones", "EliteKillMilestone", true, "Elite kill sayısı 10/20/40... eşiklerini geçince chate duyuru yapsın mı?");
			_runSummaryEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Milestones", "RunSummary", true, "Run bitince (zafer/yenilgi) MVP özet mesajı basılsın mı?");
			_nearDeathEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Milestones", "NearDeathSurvival", true, "Bir oyuncu can eşiğinin altına düşüp ölmeden kurtulunca chate duyuru yapsın mı?");
			_nearDeathThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Milestones", "NearDeathHealthFraction", 0.15f, "Can yüzdesi bu değerin altına düşünce (ölmeden) 'az kalsın ölüyordu' duyurusu tetiklenir (0.15 = %15)");
			_deathDetailsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "DeathReportDetails", true, "Ölüm mesajında katil/hasar/kritik detayı gösterilsin mi?");
			_reportCloseKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("UI", "PanelCloseKey", (KeyCode)27, "Echo panelleri hangi tuşla kapansın? (ESC: panel açıkken pause menüsü açılmaz)");
			ReportCloseKey = _reportCloseKey.Value;
			_reportCloseKey.SettingChanged += delegate
			{
				//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)
				ReportCloseKey = _reportCloseKey.Value;
			};
			_volumeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "VolumeMultiplier", 2f, "Ses seviyesi çarpanı (1.0 = normal, 2.0 = 2 kat)");
			EchoStations.Bind(((BaseUnityPlugin)this).Config);
			EchoGamble.Bind(((BaseUnityPlugin)this).Config);
			EchoPower.Bind(((BaseUnityPlugin)this).Config);
			EchoJumpscare.Bind(((BaseUnityPlugin)this).Config);
			EchoBulkPrint.Bind(((BaseUnityPlugin)this).Config);
		}

		private void LoadBank()
		{
			string? directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string path = Path.Combine(directoryName, "Init.bnk");
			string path2 = Path.Combine(directoryName, "Echo.bnk");
			LoadBankFromBytes(path, "Init");
			LoadBankFromBytes(path2, "Echo");
		}

		private void LoadBankFromBytes(string path, string name)
		{
			//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_004a: Unknown result type (might be due to invalid IL or missing references)
			if (!File.Exists(path))
			{
				Log.LogError((object)("BNK bulunamadı: " + path));
				return;
			}
			byte[] array = File.ReadAllBytes(path);
			GCHandle gCHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
			try
			{
				uint num = default(uint);
				AKRESULT val = AkSoundEngine.LoadBankMemoryCopy(gCHandle.AddrOfPinnedObject(), (uint)array.Length, ref num);
				Log.LogInfo((object)$"{name} BNK: result={val}, id={num}");
			}
			finally
			{
				gCHandle.Free();
			}
		}

		internal void PlaySound(string eventName)
		{
			if (NetworkServer.active)
			{
				NetMessageExtensions.Send((INetMessage)(object)new EchoNetMessage(eventName), (NetworkDestination)1);
			}
		}

		internal void PlaySoundLocal(string eventName)
		{
			//IL_0029: 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_0051: Expected O, but got Unknown
			Camera main = Camera.main;
			GameObject val = ((main != null) ? ((Component)main).gameObject : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			AkSoundEngine.SetGameObjectOutputBusVolume(val, val, _volumeMultiplier.Value);
			object obj = <>c.<>9__84_0;
			if (obj == null)
			{
				EventCallback val2 = delegate(object cookie, AkCallbackType type, AkCallbackInfo info)
				{
					//IL_0011: Unknown result type (might be due to invalid IL or missing references)
					GameObject val3 = (GameObject)((cookie is GameObject) ? cookie : null);
					if (val3 != null)
					{
						AkSoundEngine.SetGameObjectOutputBusVolume(val3, val3, 1f);
					}
				};
				<>c.<>9__84_0 = val2;
				obj = (object)val2;
			}
			AkSoundEngine.PostEvent(eventName, val, 1u, (EventCallback)obj, (object)val);
			Log.LogInfo((object)("PostEvent [" + eventName + "]"));
		}

		private void SendRaw(string richTextBody)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			if (NetworkServer.active)
			{
				string baseToken = Colorize("<b>[Echo]</b>", "#FDA4AF") + " " + richTextBody;
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = baseToken
				});
			}
		}

		private void SendStatus(string text)
		{
			SendRaw(text);
		}

		internal void Tell(NetworkUser user, string text)
		{
			//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_0042: Expected O, but got Unknown
			if (NetworkServer.active)
			{
				string baseToken = Colorize("<b>[Echo]</b>", "#FDA4AF") + " " + text;
				if (((user != null) ? ((NetworkBehaviour)user).connectionToClient : null) != null)
				{
					Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
					{
						baseToken = baseToken
					});
				}
				else
				{
					SendRaw(text);
				}
			}
		}

		internal void AnnounceForge(NetworkUser user, string itemName, string colorHex, int level)
		{
			if (!((Object)(object)user == (Object)null) && !string.IsNullOrEmpty(itemName))
			{
				SendRaw(ColorizeName(user.userName) + " örste " + Colorize(itemName, colorHex) + " " + Colorize($"(lv {level})", "#94A3B8") + " dövdü.");
			}
		}

		internal void AnnounceJumpscare()
		{
			SendRaw(Colorize("1/10000", "#FBBF24") + " " + Colorize("— BASS BOOSTED", "#F87171"));
		}

		internal void AnnounceSet(NetworkUser user, EchoSets.SetDef set, EchoSets.State state, string verb, bool gained)
		{
			if (!((Object)(object)user == (Object)null) && set != null)
			{
				string text = (state.Active ? $"({state.Pieces}/4 · lv {state.Level} · ×{EchoSets.Multiplier(state):0.00})" : $"({state.Pieces}/4)");
				SendRaw(ColorizeName(user.userName) + " " + Colorize(set.Name, set.Color) + " " + Colorize(verb, gained ? "#34D399" : "#F87171") + " " + Colorize(text, "#94A3B8"));
			}
		}

		internal void AnnounceGamble(NetworkUser user, EchoGambleResult result)
		{
			if (!((Object)(object)user == (Object)null) && result != null)
			{
				string text = ColorizeName(user.userName);
				if (result.Jackpot)
				{
					SendRaw(text + " " + Colorize("JACKPOT", "#FBBF24") + " vurdu! " + result.StakeLabel + " → " + Colorize(result.ResultLabel, "#FBBF24"));
				}
				else if (result.Won)
				{
					SendRaw(text + " kazandı: " + result.StakeLabel + " → " + Colorize(result.ResultLabel, "#34D399"));
				}
				else
				{
					SendRaw(text + " yaktı: " + Colorize(result.StakeLabel, "#F87171") + " gitti " + Colorize("(şans " + result.ChanceLabel + ")", "#94A3B8"));
				}
			}
		}

		private void RunSoundTest()
		{
			if (NetworkServer.active)
			{
				if (_testRunning)
				{
					SendStatus("Test zaten çalışıyor, bitmesini bekle.");
					return;
				}
				_testRunning = true;
				((MonoBehaviour)this).StartCoroutine(SoundTestCoroutine());
			}
		}

		private IEnumerator SoundTestCoroutine()
		{
			SendStatus($"Test başlıyor ({TestSequence.Length} ses, herkese yollanacak)...");
			for (int i = 0; i < TestSequence.Length; i++)
			{
				var (eventName, text) = TestSequence[i];
				SendRaw(Colorize($"[{i + 1}/{TestSequence.Length}]", "#94A3B8") + " çalınıyor: " + Colorize(text, "#A78BFA"));
				PlaySound(eventName);
				yield return (object)new WaitForSeconds(2f);
			}
			SendStatus($"Test tamamlandı, {TestSequence.Length}/{TestSequence.Length} ses gönderildi. Herkes duydu mu kontrol et.");
			_testRunning = false;
		}

		private void ShowStatHelp()
		{
			List<string> list = new List<string>();
			foreach (string key in StatAliases.Keys)
			{
				list.Add(Colorize(key, StatColorMap.TryGetValue(key, out string value) ? value : "#38BDF8"));
			}
			SendRaw("statlar: " + string.Join(", ", list) + " | kullanım: " + Colorize("echo_stat <isim>", "#A78BFA"));
		}

		private void ShowStat(string alias)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			if (string.IsNullOrEmpty(alias))
			{
				ShowStatHelp();
				return;
			}
			if (!StatAliases.TryGetValue(alias, out string value))
			{
				SendStatus("Bilinmeyen stat: '" + alias + "'. Sadece 'echo_stat' yazarsan listeyi görürsün.");
				return;
			}
			StatDef val = StatDef.Find(value);
			if (val == null)
			{
				SendStatus("Stat RoR2 tarafında bulunamadı: " + value + " (oyun versiyonu değişmiş olabilir).");
				return;
			}
			List<(string, double)> list = new List<(string, double)>();
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster val2 = ((instance != null) ? instance.master : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					PlayerStatsComponent val3 = PlayerStatsComponent.FindMasterStatsComponent(val2);
					if (val3?.currentStats != null)
					{
						double statValueAsDouble = val3.currentStats.GetStatValueAsDouble(val);
						string item = (((Object)(object)instance.networkUser != (Object)null) ? instance.networkUser.userName : "?");
						list.Add((item, statValueAsDouble));
					}
				}
			}
			if (list.Count == 0)
			{
				SendStatus("Şu an sahada oyuncu bulunamadı.");
				return;
			}
			list.Sort(((string Name, double Value) a, (string Name, double Value) b) => b.Value.CompareTo(a.Value));
			string value2;
			string hex = (StatColorMap.TryGetValue(alias, out value2) ? value2 : "#38BDF8");
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(Colorize("<b>" + alias + "</b>", hex));
			for (int num = 0; num < list.Count; num++)
			{
				stringBuilder.Append('\n').Append(Colorize($"{num + 1})", "#94A3B8")).Append(' ')
					.Append(ColorizeName(list[num].Item1))
					.Append(' ')
					.Append(list[num].Item2.ToString("0.##"));
			}
			SendRaw(stringBuilder.ToString());
		}

		private void ShowHelp()
		{
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			SendRaw("<b>Echo</b> — sesli olaylar, kumarhane, örs, set bonusları, run raporu");
			SendRaw(Colorize("<b>echo_gamble</b>", "#A78BFA") + " kumarhane: item çoğalt/takas | " + Colorize("<b>echo_forge</b>", "#A78BFA") + " örs: item'a level bas | " + Colorize("<b>echo_sets</b>", "#A78BFA") + " setler: ne lazım, kimde açık");
			SendRaw(Colorize("<b>echo_report</b>", "#A78BFA") + " skor tablosu paneli | " + Colorize("<b>echo_stat [isim]</b>", "#A78BFA") + " canlı leaderboard | " + Colorize("<b>echo_test</b>", "#A78BFA") + " tüm sesleri dener | " + Colorize("<b>echo_help</b>", "#A78BFA") + " bu mesaj | " + Colorize("<b>echo_help ui</b>", "#A78BFA") + " detaylı rehber paneli");
			SendRaw(Colorize("printer", "#94A3B8") + ": " + Colorize("<b>Shift+E</b>", "#A78BFA") + " 5'li · " + Colorize("<b>Ctrl+E</b>", "#A78BFA") + " 10'lu" + Colorize(" (config'den değişir) · paneller " + EchoPanels.KeyName(ReportCloseKey) + " ile kapanır", "#94A3B8"));
		}

		private void HookEvents()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath;
			TeleporterInteraction.onTeleporterBeginChargingGlobal += OnTeleporterStart;
			TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterCharged;
			Chat.AddMessage_ChatMessageBase += new hook_AddMessage_ChatMessageBase(OnChatMessage);
			Inventory.onServerItemGiven += OnItemGiven;
			Run.onRunStartGlobal += OnRunStart;
			Run.onServerGameOver += OnServerGameOver;
			EquipmentSlot.FireBossHunterConsumed += new hook_FireBossHunterConsumed(OnBossHunterConsumed);
			GlobalEventManager.onServerDamageDealt += OnServerDamageDealt;
		}

		private void OnServerDamageDealt(DamageReport report)
		{
			if (!_nearDeathEnabled.Value || (Object)(object)report?.victim == (Object)null || (Object)(object)report.victimBody == (Object)null || !report.victim.alive)
			{
				return;
			}
			CharacterMaster master = report.victimBody.master;
			object obj;
			if (master == null)
			{
				obj = null;
			}
			else
			{
				PlayerCharacterMasterController playerCharacterMasterController = master.playerCharacterMasterController;
				obj = ((playerCharacterMasterController != null) ? playerCharacterMasterController.networkUser : null);
			}
			NetworkUser val = (NetworkUser)obj;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			float fullHealth = report.victim.fullHealth;
			if (!(fullHealth <= 0f))
			{
				float num = report.victim.health / fullHealth;
				float value;
				float num2 = (_lastHealthFraction.TryGetValue(val, out value) ? value : 1f);
				_lastHealthFraction[val] = num;
				if (num2 > _nearDeathThreshold.Value && num <= _nearDeathThreshold.Value)
				{
					Log.LogInfo((object)$"Near-death: {val.userName} ({num:P0} can)");
					string format = NearDeathMessages[Random.Range(0, NearDeathMessages.Length)];
					SendRaw(Colorize(string.Format(format, ColorizeName(val.userName)), "#FB7185"));
				}
			}
		}

		private void OnCharacterDeath(DamageReport report)
		{
			if ((Object)(object)report?.victimBody == (Object)null)
			{
				return;
			}
			if (_bossKillEnabled.Value && report.victimBody.isBoss)
			{
				Log.LogInfo((object)("Boss öldü: " + report.victimBody.GetDisplayName()));
				PlaySound("Play_SoundAlert_BossKill");
				CharacterMaster attackerMaster = report.attackerMaster;
				object obj;
				if (attackerMaster == null)
				{
					obj = null;
				}
				else
				{
					PlayerCharacterMasterController playerCharacterMasterController = attackerMaster.playerCharacterMasterController;
					obj = ((playerCharacterMasterController != null) ? playerCharacterMasterController.networkUser : null);
				}
				if (obj == null)
				{
					CharacterMaster attackerOwnerMaster = report.attackerOwnerMaster;
					if (attackerOwnerMaster == null)
					{
						obj = null;
					}
					else
					{
						PlayerCharacterMasterController playerCharacterMasterController2 = attackerOwnerMaster.playerCharacterMasterController;
						obj = ((playerCharacterMasterController2 != null) ? playerCharacterMasterController2.networkUser : null);
					}
				}
				NetworkUser val = (NetworkUser)obj;
				if ((Object)(object)val != (Object)null)
				{
					string format = BossKillMessages[Random.Range(0, BossKillMessages.Length)];
					SendRaw(Colorize(string.Format(format, ColorizeName(val.userName)), "#FBBF24"));
				}
			}
			CharacterMaster master = report.victimBody.master;
			object obj2;
			if (master == null)
			{
				obj2 = null;
			}
			else
			{
				PlayerCharacterMasterController playerCharacterMasterController3 = master.playerCharacterMasterController;
				obj2 = ((playerCharacterMasterController3 != null) ? playerCharacterMasterController3.networkUser : null);
			}
			NetworkUser val2 = (NetworkUser)obj2;
			if (!((Object)(object)val2 != (Object)null))
			{
				return;
			}
			if (!_deathCounts.ContainsKey(val2))
			{
				_deathCounts[val2] = 0;
			}
			_deathCounts[val2]++;
			if (_playerDeathEnabled.Value)
			{
				Log.LogInfo((object)("Oyuncu öldü: " + val2.userName));
				PlaySound("Play_SoundAlert_PlayerDeath");
				string text = ColorizeName(val2.userName) + " öldü! (bu run'da " + Colorize(_deathCounts[val2].ToString(), "#F87171") + ". ölüm)";
				if (_deathDetailsEnabled.Value)
				{
					string text2 = BuildDeathDetail(report);
					if (!string.IsNullOrEmpty(text2))
					{
						text = text + "\n" + text2;
					}
				}
				SendRaw(text);
			}
			if (_tiltedPlayerEnabled.Value)
			{
				int num = TierForValue(_deathCounts[val2], 5.0, 2.0);
				int value;
				int num2 = (_deathMilestoneTier.TryGetValue(val2, out value) ? value : (-1));
				if (num > num2)
				{
					_deathMilestoneTier[val2] = num;
					int num3 = (int)(5.0 * Math.Pow(2.0, num));
					Log.LogInfo((object)$"Death milestone: {val2.userName} ({num3}. ölüm)");
					PlaySound("Play_SoundAlert_TiltedPlayer");
					string format2 = DeathMilestoneMessages[Random.Range(0, DeathMilestoneMessages.Length)];
					SendRaw(Colorize(string.Format(format2, ColorizeName(val2.userName), num3), "#F87171"));
				}
			}
			if (!_lastSurvivorEnabled.Value || PlayerCharacterMasterController.instances.Count <= 1)
			{
				return;
			}
			int num4 = 0;
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if ((Object)(object)instance.master != (Object)null && !instance.master.IsDeadAndOutOfLivesServer())
				{
					num4++;
				}
			}
			if (num4 == 1)
			{
				if (!_lastSurvivorTriggered)
				{
					_lastSurvivorTriggered = true;
					Log.LogInfo((object)"Son survivor!");
					PlaySound("Play_SoundAlert_LastSurvivor");
				}
			}
			else
			{
				_lastSurvivorTriggered = false;
			}
		}

		private void OnRunStart(Run run)
		{
			_lastSurvivorTriggered = false;
			_deathCounts.Clear();
			_damageMilestoneTier.Clear();
			_killMilestoneTier.Clear();
			_eliteKillMilestoneTier.Clear();
			_deathMilestoneTier.Clear();
			_lastHealthFraction.Clear();
		}

		private EchoReportData BuildReport(Run run, GameEndingDef gameEndingDef, bool isFinished)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			StatDef def = StatDef.Find("totalDamageDealt");
			StatDef def2 = StatDef.Find("totalMinionDamageDealt");
			StatDef def3 = StatDef.Find("totalKills");
			StatDef def4 = StatDef.Find("totalHealthHealed");
			StatDef def5 = StatDef.Find("goldCollected");
			EchoReportData echoReportData = new EchoReportData
			{
				IsFinished = isFinished,
				IsWin = ((Object)(object)gameEndingDef != (Object)null && gameEndingDef.isWin)
			};
			if ((Object)(object)run != (Object)null)
			{
				echoReportData.Duration = run.GetRunStopwatch();
				echoReportData.StageCount = run.stageClearCount;
				echoReportData.LoopCount = run.loopClearCount;
				string text = DifficultyCatalog.GetDifficultyDef(run.selectedDifficulty)?.nameToken;
				if (!string.IsNullOrEmpty(text))
				{
					echoReportData.Difficulty = Language.GetString(text);
				}
			}
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster val = ((instance != null) ? instance.master : null);
				NetworkUser val2 = ((instance != null) ? instance.networkUser : null);
				StatSheet stats;
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
				{
					stats = PlayerStatsComponent.FindMasterStatsComponent(val)?.currentStats;
					CharacterBody body = val.GetBody();
					string text2 = ((body != null) ? body.GetDisplayName() : null);
					if (string.IsNullOrEmpty(text2) && (Object)(object)val.bodyPrefab != (Object)null)
					{
						CharacterBody component = val.bodyPrefab.GetComponent<CharacterBody>();
						text2 = ((component != null) ? component.GetDisplayName() : null);
					}
					echoReportData.Rows.Add(new EchoReportData.Row
					{
						Name = val2.userName,
						Survivor = (text2 ?? ""),
						Damage = Read(def) + Read(def2),
						Kills = Read(def3),
						Deaths = (_deathCounts.TryGetValue(val2, out var value) ? value : 0),
						Healing = Read(def4),
						Gold = Read(def5)
					});
				}
				float Read(StatDef val3)
				{
					if (stats == null || val3 == null)
					{
						return 0f;
					}
					return (float)stats.GetStatValueAsDouble(val3);
				}
			}
			if (echoReportData.Rows.Count == 0)
			{
				return echoReportData;
			}
			float maxDamage = 0f;
			float maxKills = 0f;
			int maxDeaths = 0;
			foreach (EchoReportData.Row row in echoReportData.Rows)
			{
				if (row.Damage > maxDamage)
				{
					maxDamage = row.Damage;
				}
				if (row.Kills > maxKills)
				{
					maxKills = row.Kills;
				}
				if (row.Deaths > maxDeaths)
				{
					maxDeaths = row.Deaths;
				}
			}
			echoReportData.Rows.Sort((EchoReportData.Row a, EchoReportData.Row b) => ScoreOf(b).CompareTo(ScoreOf(a)));
			echoReportData.MvpName = echoReportData.Rows[0].Name;
			return echoReportData;
			double ScoreOf(EchoReportData.Row r)
			{
				double num = ((maxDamage > 0f) ? ((double)r.Damage / (double)maxDamage) : 0.0);
				double num2 = ((maxKills > 0f) ? ((double)r.Kills / (double)maxKills) : 0.0);
				double num3 = ((maxDeaths > 0) ? ((double)r.Deaths / (double)maxDeaths) : 0.0);
				return num + num2 - num3 * 0.5;
			}
		}

		private void OnServerGameOver(Run run, GameEndingDef gameEndingDef)
		{
			if (_runSummaryEnabled.Value && NetworkServer.active)
			{
				EchoReportData echoReportData = BuildReport(run, gameEndingDef, isFinished: true);
				if (echoReportData.Rows.Count != 0)
				{
					NetMessageExtensions.Send((INetMessage)(object)new EchoReportMessage(echoReportData), (NetworkDestination)1);
				}
			}
		}

		private void ShowReportTo(NetworkUser requester)
		{
			if (NetworkServer.active)
			{
				EchoReportData echoReportData = BuildReport(Run.instance, null, isFinished: false);
				if (echoReportData.Rows.Count == 0)
				{
					SendStatus("Rapor için veri yok (run başlamamış olabilir).");
				}
				else if (((requester != null) ? ((NetworkBehaviour)requester).connectionToClient : null) != null)
				{
					NetMessageExtensions.Send((INetMessage)(object)new EchoReportMessage(echoReportData), ((NetworkBehaviour)requester).connectionToClient);
				}
				else
				{
					NetMessageExtensions.Send((INetMessage)(object)new EchoReportMessage(echoReportData), (NetworkDestination)1);
				}
			}
		}

		private static bool IsLocalSender(GameObject sender)
		{
			if ((Object)(object)sender == (Object)null)
			{
				return false;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			if (firstLocalUser == null)
			{
				return false;
			}
			if ((Object)(object)firstLocalUser.cachedBodyObject == (Object)(object)sender || (Object)(object)firstLocalUser.cachedMasterObject == (Object)(object)sender)
			{
				return true;
			}
			NetworkUser val = ResolveSender(sender);
			if ((Object)(object)val != (Object)null)
			{
				return (Object)(object)val == (Object)(object)firstLocalUser.currentNetworkUser;
			}
			return false;
		}

		private static NetworkUser ResolveSender(GameObject sender)
		{
			if ((Object)(object)sender == (Object)null)
			{
				return null;
			}
			NetworkUser component = sender.GetComponent<NetworkUser>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			CharacterBody component2 = sender.GetComponent<CharacterBody>();
			if (component2 == null)
			{
				return null;
			}
			CharacterMaster master = component2.master;
			if (master == null)
			{
				return null;
			}
			PlayerCharacterMasterController playerCharacterMasterController = master.playerCharacterMasterController;
			if (playerCharacterMasterController == null)
			{
				return null;
			}
			return playerCharacterMasterController.networkUser;
		}

		private void OnTeleporterStart(TeleporterInteraction teleporter)
		{
			if (_teleporterStartEnabled.Value)
			{
				Log.LogInfo((object)"Teleporter başladı!");
				PlaySound("Play_SoundAlert_TeleporterStart");
			}
		}

		private void OnTeleporterCharged(TeleporterInteraction teleporter)
		{
			if (_teleporterChargedEnabled.Value)
			{
				Log.LogInfo((object)"Teleporter tamamlandı!");
				PlaySound("Play_SoundAlert_TeleporterCharged");
			}
		}

		private void OnChatMessage(orig_AddMessage_ChatMessageBase orig, ChatMessageBase msg)
		{
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Invalid comparison between Unknown and I4
			//IL_0332: 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_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: 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)
			orig.Invoke(msg);
			UserChatMessage val = (UserChatMessage)(object)((msg is UserChatMessage) ? msg : null);
			if (val != null)
			{
				string text = val.text?.ToLower().Trim() ?? "";
				Log.LogInfo((object)("Chat mesajı: '" + text + "'"));
				if (_chatEvetEnabled.Value && text == "evet")
				{
					Log.LogInfo((object)"Chat: evet");
					PlaySound("Play_SoundAlert_ChatEvet");
				}
				else if (_chatHayirEnabled.Value && (text == "hayır" || text == "hayir"))
				{
					Log.LogInfo((object)"Chat: hayır");
					PlaySound("Play_SoundAlert_ChatHayir");
				}
				else if (_chat31Enabled.Value && text == "31")
				{
					Log.LogInfo((object)"Chat: 31");
					PlaySound("Play_SoundAlert_Chat31");
				}
				else
				{
					switch (text)
					{
					case "echo_test":
						Log.LogInfo((object)"Chat: echo_test");
						RunSoundTest();
						break;
					case "echo_help":
						Log.LogInfo((object)"Chat: echo_help");
						ShowHelp();
						break;
					case "echo_report":
						Log.LogInfo((object)"Chat: echo_report");
						ShowReportTo(ResolveSender(val.sender));
						break;
					case "echo_gamble":
						Log.LogInfo((object)"Chat: echo_gamble");
						if (IsLocalSender(val.sender))
						{
							EchoCasinoUI.Open(ReportCloseKey);
						}
						break;
					case "echo_help ui":
						Log.LogInfo((object)"Chat: echo_help ui");
						if (IsLocalSender(val.sender))
						{
							EchoHelpUI.Open(ReportCloseKey);
						}
						break;
					case "echo_sets":
						Log.LogInfo((object)"Chat: echo_sets");
						if (IsLocalSender(val.sender))
						{
							EchoSetsUI.Open(ReportCloseKey);
						}
						break;
					case "echo_forge":
						Log.LogInfo((object)"Chat: echo_forge");
						if (IsLocalSender(val.sender))
						{
							EchoForgeUI.Open(ReportCloseKey);
						}
						break;
					case "echo_stat":
						Log.LogInfo((object)"Chat: echo_stat");
						ShowStatHelp();
						break;
					default:
						if (text.StartsWith("echo_stat "))
						{
							string text2 = text.Substring("echo_stat ".Length).Trim();
							Log.LogInfo((object)("Chat: echo_stat " + text2));
							ShowStat(text2);
						}
						break;
					}
				}
			}
			if (!_equipmentDroneEnabled.Value)
			{
				return;
			}
			PlayerPickupChatMessage val2 = (PlayerPickupChatMessage)(object)((msg is PlayerPickupChatMessage) ? msg : null);
			if (val2 == null)
			{
				return;
			}
			PickupIndex val3 = PickupCatalog.FindPickupIndex(val2.pickupToken ?? "");
			if (val3 != PickupIndex.none)
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(val3);
				if ((pickupDef == null || (int)pickupDef.equipmentIndex != -1) && EquipmentCatalog.GetEquipmentDef(pickupDef.equipmentIndex)?.nameToken == "EQUIPMENT_BOSSHUNTER_NAME")
				{
					Log.LogInfo((object)"Equipment Drone: Trophy Hunter's Tricorn alındı!");
					PlaySound("Play_SoundAlert_EquipmentDrone");
				}
			}
		}

		private bool OnBossHunterConsumed(orig_FireBossHunterConsumed orig, EquipmentSlot self)
		{
			bool result = orig.Invoke(self);
			if (_equipmentDroneEnabled.Value)
			{
				Log.LogInfo((object)"Trophy Hunter's Tricorn: tüketilmiş şarj kullanıldı (Ahoy!/Selamlar!)");
				PlaySound("Play_SoundAlert_EquipmentDrone");
			}
			return result;
		}

		private void OnItemGiven(Inventory inventory, ItemIndex itemIndex, int count)
		{
			//IL_000e: 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)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_004b: 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)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			if (_rareItemDropEnabled.Value)
			{
				ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
				if (!((Object)(object)itemDef == (Object)null) && ((int)itemDef.tier == 2 || (int)itemDef.tier == 4 || (int)itemDef.tier == 3))
				{
					Log.LogInfo((object)$"Rare item alındı: {((Object)itemDef).name} ({itemDef.tier})");
					PlaySound("Play_SoundAlert_RareItemDrop");
				}
			}
		}

		private void OnDestroy()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath;
			TeleporterInteraction.onTeleporterBeginChargingGlobal -= OnTeleporterStart;
			TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterCharged;
			Chat.AddMessage_ChatMessageBase -= new hook_AddMessage_ChatMessageBase(OnChatMessage);
			Inventory.onServerItemGiven -= OnItemGiven;
			Run.onRunStartGlobal -= OnRunStart;
			Run.onServerGameOver -= OnServerGameOver;
			EquipmentSlot.FireBossHunterConsumed -= new hook_FireBossHunterConsumed(OnBossHunterConsumed);
			GlobalEventManager.onServerDamageDealt -= OnServerDamageDealt;
		}
	}
	public class EchoNetMessage : INetMessage, ISerializableObject
	{
		private string _eventName;

		public EchoNetMessage()
		{
		}

		public EchoNetMessage(string eventName)
		{
			_eventName = eventName;
		}

		public void Serialize(NetworkWriter writer)
		{
			writer.Write(_eventName);
		}

		public void Deserialize(NetworkReader reader)
		{
			_eventName = reader.ReadString();
		}

		public void OnReceived()
		{
			Echo.Instance?.PlaySoundLocal(_eventName);
		}
	}
	internal static class EchoBulkPrint
	{
		private class Order
		{
			public Interactor Interactor;

			public int Remaining;

			public float Expires;
		}

		private static ConfigEntry<int> _shiftCount;

		private static ConfigEntry<int> _ctrlCount;

		private static readonly Dictionary<uint, Order> Orders = new Dictionary<uint, Order>();

		public static void Bind(ConfigFile config)
		{
			_shiftCount = config.Bind<int>("Stations", "BulkPrintShift", 5, "Shift + E ile printer'dan kaç item basılsın?");
			_ctrlCount = config.Bind<int>("Stations", "BulkPrintCtrl", 10, "Ctrl + E ile printer'dan kaç item basılsın?");
		}

		public static void Install()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Interactor.AttemptInteraction += new hook_AttemptInteraction(OnAttemptInteraction);
			Duplicating.OnExit += new hook_OnExit(OnCookFinished);
			Run.onRunStartGlobal += delegate
			{
				Orders.Clear();
			};
		}

		private static void OnAttemptInteraction(orig_AttemptInteraction orig, Interactor self, GameObject target)
		{
			TrySendOrder(self, target);
			orig.Invoke(self, target);
		}

		private static void TrySendOrder(Interactor self, GameObject target)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)self == (Object)null || (Object)(object)target == (Object)null)
			{
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if ((Object)(object)val == (Object)null || (Object)(object)((Component)self).gameObject != (Object)(object)((Component)val).gameObject)
			{
				return;
			}
			PurchaseInteraction component = target.GetComponent<PurchaseInteraction>();
			if ((Object)(object)component == (Object)null || !IsPrinter(component))
			{
				return;
			}
			int num = 1;
			if (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305))
			{
				num = _ctrlCount.Value;
			}
			else if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303))
			{
				num = _shiftCount.Value;
			}
			if (num > 1)
			{
				NetworkIdentity component2 = target.GetComponent<NetworkIdentity>();
				LocalUser firstLocalUser2 = LocalUserManager.GetFirstLocalUser();
				NetworkUser val2 = ((firstLocalUser2 != null) ? firstLocalUser2.currentNetworkUser : null);
				if (!((Object)(object)component2 == (Object)null) && !((Object)(object)val2 == (Object)null))
				{
					NetworkInstanceId netId = component2.netId;
					NetMessageExtensions.Send((INetMessage)(object)new EchoBulkPrintRequest(((NetworkInstanceId)(ref netId)).Value, num - 1, ((NetworkBehaviour)val2).netId), (NetworkDestination)2);
				}
			}
		}

		private static bool IsPrinter(PurchaseInteraction purchase)
		{
			//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_0007: 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_000b: Invalid comparison between Unknown and I4
			//IL_000d: 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_0012: Invalid comparison between Unknown and I4
			CostTypeIndex costType = purchase.costType;
			if (costType - 4 <= 2 || costType - 9 <= 1)
			{
				return true;
			}
			return false;
		}

		public static void Register(uint printerNetId, int extra, NetworkInstanceId senderId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active && extra > 0)
			{
				NetworkUser obj = FindUser(senderId);
				object obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					CharacterMaster master = obj.master;
					obj2 = ((master != null) ? master.GetBody() : null);
				}
				Interactor val = ((obj2 != null) ? ((Component)obj2).GetComponent<Interactor>() : null);
				if (!((Object)(object)val == (Object)null))
				{
					Orders[printerNetId] = new Order
					{
						Interactor = val,
						Remaining = Mathf.Min(extra, 99),
						Expires = Time.time + 30f
					};
				}
			}
		}

		private static void OnCookFinished(orig_OnExit orig, Duplicating self)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00d0: 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)
			orig.Invoke(self);
			if (!NetworkServer.active || (Object)(object)((EntityState)(self?)).outer == (Object)null)
			{
				return;
			}
			GameObject gameObject = ((Component)((EntityState)self).outer).gameObject;
			NetworkIdentity component = gameObject.GetComponent<NetworkIdentity>();
			PurchaseInteraction component2 = gameObject.GetComponent<PurchaseInteraction>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				return;
			}
			Dictionary<uint, Order> orders = Orders;
			NetworkInstanceId netId = component.netId;
			if (!orders.TryGetValue(((NetworkInstanceId)(ref netId)).Value, out Order value))
			{
				return;
			}
			if (value.Remaining <= 0 || Time.time > value.Expires || (Object)(object)value.Interactor == (Object)null)
			{
				Dictionary<uint, Order> orders2 = Orders;
				netId = component.netId;
				orders2.Remove(((NetworkInstanceId)(ref netId)).Value);
				return;
			}
			if ((Object)(object)component2.lastActivator != (Object)null && (Object)(object)component2.lastActivator != (Object)(object)value.Interactor)
			{
				Dictionary<uint, Order> orders3 = Orders;
				netId = component.netId;
				orders3.Remove(((NetworkInstanceId)(ref netId)).Value);
				return;
			}
			Echo instance = Echo.Instance;
			if (instance != null)
			{
				netId = component.netId;
				((MonoBehaviour)instance).StartCoroutine(ChainNext(component2, ((NetworkInstanceId)(ref netId)).Value, value));
			}
		}

		private static IEnumerator ChainNext(PurchaseInteraction purchase, uint netId, Order order)
		{
			float deadline = Time.time + 2f;
			while ((Object)(object)purchase != (Object)null && !purchase.available && Time.time < deadline)
			{
				yield return null;
			}
			if ((Object)(object)purchase == (Object)null || !purchase.available)
			{
				Orders.Remove(netId);
				yield break;
			}
			if ((Object)(object)order.Interactor == (Object)null)
			{
				Orders.Remove(netId);
				yield break;
			}
			if (!purchase.CanBeAffordedByInteractor(order.Interactor))
			{
				Orders.Remove(netId);
				yield break;
			}
			order.Remaining--;
			if (order.Remaining <= 0)
			{
				Orders.Remove(netId);
			}
			purchase.OnInteractionBegin(order.Interactor);
		}

		private static NetworkUser FindUser(NetworkInstanceId id)
		{
			//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)
			foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
			{
				if ((Object)(object)readOnlyInstances != (Object)null && ((NetworkBehaviour)readOnlyInstances).netId == id)
				{
					return readOnlyInstances;
				}
			}
			return null;
		}
	}
	public class EchoBulkPrintRequest : INetMessage, ISerializableObject
	{
		private uint _printer;

		private int _extra;

		private NetworkInstanceId _sender;

		public EchoBulkPrintRequest()
		{
		}

		public EchoBulkPrintRequest(uint printer, int extra, NetworkInstanceId sender)
		{
			//IL_0015: 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)
			_printer = printer;
			_extra = extra;
			_sender = sender;
		}

		public void Serialize(NetworkWriter writer)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			writer.Write(_printer);
			writer.Write(_extra);
			writer.Write(_sender);
		}

		public void Deserialize(NetworkReader reader)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			_printer = reader.ReadUInt32();
			_extra = reader.ReadInt32();
			_sender = reader.ReadNetworkId();
		}

		public void OnReceived()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active)
			{
				EchoBulkPrint.Register(_printer, _extra, _sender);
			}
		}
	}
	internal class EchoCasinoUI : MonoBehaviour
	{
		private enum Phase
		{
			Selecting,
			Picking,
			Spinning,
			Done
		}

		private enum Field
		{
			Item,
			Mode,
			Target,
			Count,
			Gold,
			Spin
		}

		private static class Memory
		{
			public static ItemIndex Item = (ItemIndex)(-1);

			public static int ModeIndex;

			public static ItemIndex Target = (ItemIndex)(-1);

			public static int Count = 1;

			public static int Gold;

			public static readonly Dictionary<ItemIndex, int> Stake = new Dictionary<ItemIndex, int>();

			public static string LastResult = "";

			public static void Clear()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				Item = (ItemIndex)(-1);
				ModeIndex = 0;
				Target = (ItemIndex)(-1);
				Count = 1;
				Gold = 0;
				Stake.Clear();
				LastResult = "";
			}
		}

		private const int FieldCount = 6;

		private const int PickerColumns = 8;

		private const int CellCount = 5;

		private const int Selector = 2;

		private static EchoCasinoUI _instance;

		private static KeyCode _closeKey = (KeyCode)283;

		private Phase _phase;

		private Field _focus;

		private readonly List<ItemDef> _items = new List<ItemDef>();

		private int _itemIndex;

		private readonly List<(EchoOdds.Mode Mode, ItemTier Target, string Label)> _modes = new List<(EchoOdds.Mode, ItemTier, string)>();

		private int _modeIndex;

		private int _count = 1;

		private int _gold;

		private readonly List<int> _stake = new List<int>();

		private readonly List<ItemDef> _targetPool = new List<ItemDef>();

		private int _targetIndex = -1;

		private Field _pickingField;

		private readonly List<ItemDef> _pickList = new List<ItemDef>();

		private readonly List<Image> _pickCells = new List<Image>();

		private readonly List<TextMeshProUGUI> _pickLabels = new List<TextMeshProUGUI>();

		private bool _pickerMulti;

		private int _pickCursor;

		private GameObject _pickerGroup;

		private TextMeshProUGUI _pickerTitle;

		private readonly TextMeshProUGUI[] _rows = (TextMeshProUGUI[])(object)new TextMeshProUGUI[6];

		private TextMeshProUGUI _chanceText;

		private TextMeshProUGUI _hintText;

		private readonly TextMeshProUGUI[] _cells = (TextMeshProUGUI[])(object)new TextMeshProUGUI[5];

		private GameObject _reelGroup;

		private GameObject _formGroup;

		private static bool _memoryHooked;

		public static bool IsOpen => (Object)(object)_instance != (Object)null;

		private ItemDef CurrentItem
		{
			get
			{
				if (_items.Count != 0)
				{
					return _items[Mathf.Clamp(_itemIndex, 0, _items.Count - 1)];
				}
				return null;
			}
		}

		private (EchoOdds.Mode Mode, ItemTier Target, string Label)? CurrentMode
		{
			get
			{
				if (_modes.Count != 0)
				{
					return _modes[Mathf.Clamp(_modeIndex, 0, _modes.Count - 1)];
				}
				return null;
			}
		}

		private ItemDef CurrentTarget
		{
			get
			{
				if (_targetIndex >= 0 && _targetIndex < _targetPool.Count)
				{
					return _targetPool[_targetIndex];
				}
				return null;
			}
		}

		public static void Open(KeyCode closeKey)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!_memoryHooked)
			{
				Run.onRunStartGlobal += delegate
				{
					Memory.Clear();
				};
				_memoryHooked = true;
			}
			_closeKey = closeKey;
			Close();
			GameObject obj = EchoUI.Canvas("EchoCasinoCanvas", 1001);
			Object.DontDestroyOnLoad((Object)(object)obj);
			_instance = obj.AddComponent<EchoCasinoUI>();
			_instance.Init();
		}

		public static void Close()
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				Object.Destroy((Object)(object)((Component)_instance).gameObject);
			}
		}

		public static bool OnEscape()
		{
			if ((Object)(object)_instance == (Object)null)
			{
				return false;
			}
			if (_instance._phase == Phase.Picking)
			{
				_instance.ClosePicker(commit: false);
			}
			else
			{
				Close();
			}
			return true;
		}

		public static void PlayResult(EchoGambleResult result)
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				((MonoBehaviour)_instance).StartCoroutine(_instance.Spin(result));
			}
		}

		private void Init()
		{
			LoadInventory();
			Recall();
			Build();
			Refresh();
		}

		private void OnDestroy()
		{
			//IL_002e: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
			if (_phase == Phase.Spinning)
			{
				return;
			}
			ItemDef currentItem = CurrentItem;
			Memory.Item = (ItemIndex)(((Object)(object)currentItem == (Object)null) ? (-1) : ((int)currentItem.itemIndex));
			Memory.ModeIndex = _modeIndex;
			ItemDef currentTarget = CurrentTarget;
			Memory.Target = (ItemIndex)(((Object)(object)currentTarget == (Object)null) ? (-1) : ((int)currentTarget.itemIndex));
			Memory.Count = _count;
			Memory.Gold = _gold;
			Memory.Stake.Clear();
			for (int i = 0; i < _items.Count && i < _stake.Count; i++)
			{
				if (_stake[i] > 0)
				{
					Memory.Stake[_items[i].itemIndex] = _stake[i];
				}
			}
		}

		private void Recall()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Memory.Item == -1)
			{
				return;
			}
			int num = _items.FindIndex((ItemDef i) => i.itemIndex == Memory.Item);
			if (num < 0)
			{
				return;
			}
			_itemIndex = num;
			RebuildModes();
			_modeIndex = Mathf.Clamp(Memory.ModeIndex, 0, Mathf.Max(0, _modes.Count - 1));
			RebuildTargetPool();
			_targetIndex = _targetPool.FindIndex((ItemDef i) => i.itemIndex == Memory.Target);
			_count = Mathf.Max(1, Memory.Count);
			_gold = Mathf.Max(0, Memory.Gold);
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			object obj;
			if (firstLocalUser == null)
			{
				obj = null;
			}
			else
			{
				CharacterMaster cachedMaster = firstLocalUser.cachedMaster;
				obj = ((cachedMaster != null) ? cachedMaster.inventory : null);
			}
			Inventory val = (Inventory)obj;
			for (int num2 = 0; num2 < _items.Count; num2++)
			{
				if (Memory.Stake.TryGetValue(_items[num2].itemIndex, out var value))
				{
					int num3 = ((!((Object)(object)val == (Object)null)) ? val.GetItemCount(_items[num2].itemIndex) : 0);
					_stake[num2] = Mathf.Clamp(value, 0, num3);
				}
			}
		}

		private void LoadInventory()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0055: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Invalid comparison between Unknown and I4
			_items.Clear();
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			object obj;
			if (firstLocalUser == null)
			{
				obj = null;
			}
			else
			{
				CharacterMaster cachedMaster = firstLocalUser.cachedMaster;
				obj = ((cachedMaster != null) ? cachedMaster.inventory : null);
			}
			Inventory val = (Inventory)obj;
			if ((Object)(object)val != (Object)null)
			{
				Enumerator<ItemDef> enumerator = ItemCatalog.allItemDefs.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						ItemDef current = enumerator.Current;
						if (!((Object)(object)current == (Object)null) && val.GetItemCount(current.itemIndex) > 0 && (EchoOdds.TierIndex(current.tier) >= 0 || (int)current.tier == 3))
						{
							_items.Add(current);
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
			_stake.Clear();
			for (int i = 0; i < _items.Count; i++)
			{
				_stake.Add(0);
			}
			_itemIndex = 0;
		}

		private int StakeTotal()
		{
			int num = 0;
			foreach (int item in _stake)
			{
				num += item;
			}
			return num;
		}

		private int StakeKinds()
		{
			int num = 0;
			foreach (int item in _stake)
			{
				if (item > 0)
				{
					num++;
				}
			}
			return num;
		}

		private void ClearStake()
		{
			for (int i = 0; i < _stake.Count; i++)
			{
				_stake[i] = 0;
			}
		}

		private int StakeCap()
		{
			int num = TradeDistance();
			return EchoOdds.DifficultyFor((num < 0) ? (EchoOdds.Ladder.Length - 1) : num).MaxCount;
		}

		private void TrimStake(int excess)
		{
			int num = _stake.Count - 1;
			while (num >= 0 && excess > 0)
			{
				int num2 = Mathf.Min(_stake[num], excess);
				_stake[num] -= num2;
				excess -= num2;
				num--;
			}
		}

		private void StakeAdd(int index, int delta)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			if (index < 0 || index >= _items.Count)
			{
				return;
			}
			ItemDef val = _items[index];
			if (EchoOdds.TierIndex(val.tier) < 0)
			{
				return;
			}
			ItemDef val2 = StakeAnchor();
			if ((Object)(object)val2 != (Object)null && val2.tier != val.tier)
			{
				if (delta <= 0)
				{
					return;
				}
				ClearStake();
				_targetIndex = -1;
				_gold = 0;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			object obj;
			if (firstLocalUser == null)
			{
				obj = null;
			}
			else
			{
				CharacterMaster cachedMaster = firstLocalUser.cachedMaster;
				obj = ((cachedMaster != null) ? cachedMaster.inventory : null);
			}
			Inventory val3 = (Inventory)obj;
			int num = ((!((Object)(object)val3 == (Object)null)) ? val3.GetItemCount(val.itemIndex) : 0);
			int num2 = Mathf.Max(0, StakeCap() - StakeTotal());
			int num3 = ((delta > 0) ? Mathf.Min(delta, num2) : delta);
			_stake[index] = Mathf.Clamp(_stake[index] + num3, 0, num);
			_itemIndex = Mathf.Max(0, _items.IndexOf(StakeAnchor() ?? val));
		}

		private ItemDef StakeAnchor()
		{
			for (int i = 0; i < _stake.Count; i++)
			{
				if (_stake[i] > 0)
				{
					return _items[i];
				}
			}
			return null;
		}

		private int OwnedCount()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			object obj;
			if (firstLocalUser == null)
			{
				obj = null;
			}
			else
			{
				CharacterMaster cachedMaster = firstLocalUser.cachedMaster;
				obj = ((cachedMaster != null) ? cachedMaster.inventory : null);
			}
			Inventory val = (Inventory)obj;
			ItemDef currentItem = CurrentItem;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)currentItem == (Object)null))
			{
				return val.GetItemCount(currentItem.itemIndex);
			}
			return 0;
		}

		private int TradeDistance()
		{
			//IL_0044: 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)
			(EchoOdds.Mode, ItemTier, string)? currentMode = CurrentMode;
			ItemDef currentItem = CurrentItem;
			ItemDef currentTarget = CurrentTarget;
			if (!currentMode.HasValue || (Object)(object)currentItem == (Object)null || (Object)(object)currentTarget == (Object)null)
			{
				return -1;
			}
			if (currentMode.Value.Item1 != EchoOdds.Mode.Trade)
			{
				return -1;
			}
			return EchoOdds.Distance(currentItem.tier, currentTarget.tier);
		}

		private int MaxStake()
		{
			return Mathf.Max(1, OwnedCount());
		}

		private int WalletGold()
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			uint? obj;
			if (firstLocalUser == null)
			{
				obj = null;
			}
			else
			{
				CharacterMaster cachedMaster = firstLocalUser.cachedMaster;
				obj = ((cachedMaster != null) ? new uint?(cachedMaster.money) : ((uint?)null));
			}
			uint? num = obj;
			return (int)num.GetValueOrDefault();
		}

		private void RebuildModes()
		{
			//IL_0024: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			_modes.Clear();
			ItemDef currentItem = CurrentItem;
			if (!((Object)(object)currentItem == (Object)null))
			{
				_modes.Add((EchoOdds.Mode.Multiply, currentItem.tier, "ÇOĞALT"));
				if (EchoOdds.TierIndex(currentItem.tier) >= 0)
				{
					_modes.Add((EchoOdds.Mode.Trade, currentItem.tier, "TAKAS"));
				}
				_modeIndex = Mathf.Clamp(_modeIndex, 0, _modes.Count - 1);
			}
		}

		private void RebuildTargetPool()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			_targetPool.Clear();
			(EchoOdds.Mode, ItemTier, string)? currentMode = CurrentMode;
			ItemDef currentItem = CurrentItem;
			if (!currentMode.HasValue || (Object)(object)currentItem == (Object)null || currentMode.Value.Item1 != EchoOdds.Mode.Trade)
			{
				_targetIndex = -1;
				return;
			}
			int num = EchoOdds.TierIndex(currentItem.tier);
			if (num < 0)
			{
				_targetIndex = -1;
				return;
			}
			for (int i = num; i < EchoOdds.Ladder.Length; i++)
			{
				_targetPool.AddRange(EchoOdds.PoolFor(EchoOdds.Ladder[i]));
			}
			if (_targetIndex >= _targetPool.Count)
			{
				_targetIndex = -1;
			}
		}

		private void Build()
		{
			GameObject val = EchoUI.Panel(((Component)this).transform, 940f);
			EchoUI.Text(val.transform, EchoUI.B(EchoUI.C("ECHO", "#FDA4AF") + "  " + EchoUI.C("KUMARHANE", "#FBBF24")), 32f, (TextAlignmentOptions)4097);
			if (!string.IsNullOrEmpty(Memory.LastResult))
			{
				EchoUI.Text(val.transform, EchoUI.C("son oyun:  ", "#94A3B8") + Memory.LastResult, 16f, (TextAlignmentOptions)4097);
			}
			EchoUI.Divider(val.transform);
			_formGroup = EchoUI.Card(val.transform, "#A78BFA");
			for (int i = 0; i < 6; i++)
			{
				_rows[i] = EchoUI.Text(_formGroup.transform, "", 24f, (TextAlignmentOptions)4097);
			}
			EchoUI.Divider(val.transform);
			_chanceText = EchoUI.Text(val.transform, "", 24f, (TextAlignmentOptions)4097);
			_reelGroup = EchoUI.Card(val.transform, "#FBBF24", emphasized: true);
			for (int j = 0; j < 5; j++)
			{
				_cells[j] = EchoUI.Text(_reelGroup.transform, "", (j == 2) ? 24f : 20f, (TextAlignmentOptions)514);
			}
			((Component)_reelGroup.transform.parent).gameObject.SetActive(false);
			_pickerGroup = EchoUI.Card(val.transform, "#38BDF8", emphasized: true);
			_pickerTitle = EchoUI.Text(_pickerGroup.transform, "", 20f, (TextAlignmentOptions)4097);
			((Component)_pickerGroup.transform.parent).gameObject.SetActive(false);
			EchoUI.Divider(val.transform);
			_hintText = EchoUI.Text(val.transform, "", 16f, (TextAlignmentOptions)4097);
		}

		private void OpenPicker(Field field)
		{
			_pickList.Clear();
			_pickCells.Clear();
			_pickLabels.Clear();
			for (int num = _pickerGroup.transform.childCount - 1; num >= 1; num--)
			{
				Object.Destroy((Object)(object)((Component)_pickerGroup.transform.GetChild(num)).gameObject);
			}
			(EchoOdds.Mode, ItemTier, string)? currentMode = CurrentMode;
			_pickerMulti = field == Field.Item && currentMode.HasValue && currentMode.Value.Item1 == EchoOdds.Mode.Trade;
			if (field == Field.Item)
			{
				_pickList.AddRange(_items);
				_pickCursor = Mathf.Clamp(_itemIndex, 0, Mathf.Max(0, _pickList.Count - 1));
				((TMP_Text)_pickerTitle).text = EchoUI.C(_pickerMulti ? "yığını kur — aynı tier'dan istediğin kadar item at" : "hangi item'ı masaya süreceksin?", "#94A3B8");
			}
			else
			{
				_pickList.AddRange(_targetPool);
				_pickCursor = Mathf.Clamp(_targetIndex, 0, Mathf.Max(0, _pickList.Count - 1));
				((TMP_Text)_pickerTitle).text = EchoUI.C("ne almak istiyorsun? (kendi tier'ın ve üstü)", "#94A3B8");
			}
			if (_pickList.Count == 0)
			{
				return;
			}
			GameObject val = EchoUI.Grid(_pickerGroup.transform, 8, 74f);
			foreach (ItemDef pick in _pickList)
			{
				_pickCells.Add(EchoUI.IconCell(val.transform, pick?.pickupIconSprite, "", out TextMeshProUGUI label));
				_pickLabels.Add(label);
			}
			_pickingField = field;
			_phase = Phase.Picking;
			((Component)_formGroup.transform.parent).gameObject.SetActive(false);
			((Component)_pickerGroup.transform.parent).gameObject.SetActive(true);
			PaintPicker();
		}

		private void ClosePicker(bool commit)
		{
			if (commit && !_pickerMulti && _pickList.Count > 0)
			{
				ItemDef item = _pickList[Mathf.Clamp(_pickCursor, 0, _pickList.Count - 1)];
				if (_pickingField == Field.Item)
				{
					int num = _items.IndexOf(item);
					if (num >= 0)
					{
						_itemIndex = num;
						_modeIndex = 0;
						_count = 1;
						_gold = 0;
						_targetIndex = -1;
						ClearStake();
					}
				}
				else
				{
					_targetIndex = _pickCursor;
				}
			}
			_phase = Phase.Selecting;
			((Component)_pickerGroup.transform.parent).gameObject.SetActive(false);
			((Component)_formGroup.transform.parent).gameObject.SetActive(true);
			Refresh();
		}

		private void StakeAtCursor(int delta)
		{
			if (_pickList.Count != 0)
			{
				ItemDef item = _pickList[Mathf.Clamp(_pickCursor, 0, _pickList.Count - 1)];
				int num = _items.IndexOf(item);
				if (num >= 0)
				{
					StakeAdd(num, delta);
					PaintPicker();
				}
			}
		}

		private void MovePicker(int delta)
		{
			if (_pickList.Count != 0)
			{
				_pickCursor = Mathf.Clamp(_pickCursor + delta, 0, _pickList.Count - 1);
				PaintPicker();
			}
		}

		private void PaintPicker()
		{
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0215: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			object obj;
			if (firstLocalUser == null)
			{
				obj = null;
			}
			else
			{
				CharacterMaster cachedMaster = firstLocalUser.cachedMaster;
				obj = ((cachedMaster != null) ? cachedMaster.inventory : null);
			}
			Inventory val = (Inventory)obj;
			ItemDef val2 = StakeAnchor();
			for (int i = 0; i < _pickCells.Count; i++)
			{
				if ((Object)(object)_pickCells[i] == (Object)null)
				{
					continue;
				}
				ItemDef val3 = ((i < _pickList.Count) ? _pickList[i] : null);
				int num = ((_pickerMulti && (Object)(object)val3 != (Object)null) ? _stake[_items.IndexOf(val3)] : 0);
				bool flag = _pickerMulti && (Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null && val3.tier != val2.tier;
				((Graphic)_pickCells[i]).color = ((i == _pickCursor) ? EchoUI.Hex("#FBBF24", 0.55f) : ((num > 0) ? EchoUI.Hex("#34D399", 0.4f) : (flag ? EchoUI.Hex("#94A3B8", 0.06f) : EchoUI.Hex("#94A3B8", 0.15f))));
				if (i < _pickLabels.Count && !((Object)(object)_pickLabels[i] == (Object)null))
				{
					if ((Object)(object)val3 == (Object)null)
					{
						((TMP_Text)_pickLabels[i]).text = "";
					}
					else if (_pickerMulti)
					{
						int num2 = ((!((Object)(object)val == (Object)null)) ? val.GetItemCount(val3.itemIndex) : 0);
						((TMP_Text)_pickLabels[i]).text = ((num > 0) ? EchoUI.B(EchoUI.C($"{num}/{num2}", "#34D399")) : EchoUI.C(num2.ToString(), "#94A3B8"));
					}
					else if (_pickingField == Field.Item && (Object)(object)val != (Object)null)
					{
						((TMP_Text)_pickLabels[i]).text = EchoUI.C(val.GetItemCount(val3.itemIndex).ToString(), "#94A3B8");
					}
				}
			}
			ItemDef val4 = ((_pickList.Count == 0) ? null : _pickList[Mathf.Clamp(_pickCursor, 0, _pickList.Count - 1)]);
			string text = (((Object)(object)val4 == (Object)null) ? "" : (EchoUI.B(EchoUI.C(EchoOdds.ItemName(val4), EchoOdds.TierColor(val4.tier))) + "   " + EchoUI.C(EchoOdds.TierName(val4.tier), "#94A3B8")));
			if (_pickerMulti)
			{
				text = text + "     " + EchoUI.Stat("yığın", $"{StakeTotal()}/{StakeCap()}", "#A78BFA") + "  " + EchoUI.C($"{StakeKinds()} çeşit", "#94A3B8");
			}
			((TMP_Text)_chanceText).text = text;
			((TMP_Text)_hintText).text = EchoUI.C(_pickerMulti ? ("←→↑↓ gez   ENTER ekle (shift = doldur)   BACKSPACE çıkar   " + EchoPanels.KeyName(_closeKey) + " bitir") : ("←→↑↓ gez   ENTER seç   " + EchoPanels.KeyName(_closeKey) + " vazgeç"), "#94A3B8");
		}

		private void Update()
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (_phase == Phase.Picking)
			{
				bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
				if (EchoPanels.ClosePressed(_closeKey))
				{
					ClosePicker(commit: false);
				}
				else if (_pickerMulti && Input.GetKeyDown((KeyCode)13))
				{
					StakeAtCursor((!flag) ? 1 : 99);
				}
				else if (_pickerMulti && Input.GetKeyDown((KeyCode)8))
				{
					StakeAtCursor(flag ? (-99) : (-1));
				}
				else if (Input.GetKeyDown((KeyCode)13))
				{
					ClosePicker(commit: true);
				}
				else if (Input.GetKeyDown((KeyCode)276))
				{
					MovePicker(-1);
				}
				else if (Input.GetKeyDown((KeyCode)275))
				{
					MovePicker(1);
				}
				else if (Input.GetKeyDown((KeyCode)273))
				{
					MovePicker(-8);
				}
				else if (Input.GetKeyDown((KeyCode)274))
				{
					MovePicker(8);
				}
			}
			else if (EchoPanels.ClosePressed(_closeKey))
			{
				Close();
			}
			else if (_phase == Phase.Done && Input.GetKeyDown((KeyCode)13))
			{
				_phase = Phase.Selecting;
				((Component)_reelGroup.transform.parent).gameObject.SetActive(false);
				((Component)_formGroup.transform.parent).gameObject.SetActive(true);
				ItemDef keep = CurrentItem;
				LoadInventory();
				if ((Object)(object)keep != (Object)null)
				{
					_itemIndex = Mathf.Max(0, _items.FindIndex((ItemDef i) => (Object)(object)i == (Object)(object)keep));
				}
				Refresh();
			}
			else if (_phase == Phase.Selecting)
			{
				if (Input.GetKeyDown((KeyCode)273))
				{
					Step(ref _focus, -1);
					Refresh();
				}
				else if (Input.GetKeyDown((KeyCode)274))
				{
					Step(ref _focus, 1);
					Refresh();
				}
				else if (Input.GetKeyDown((KeyCode)276))
				{
					Adjust(-1);
					Refresh();
				}
				else if (Input.GetKeyDown((KeyCode)275))
				{
					Adjust(1);
					Refresh();
				}
				else if (Input.GetKeyDown((KeyCode)13))
				{
					Activate();
				}
			}
		}

		private static void Step(ref Field field, int delta)
		{
			int num = (int)(field + delta + 6) % 6;
			field = (Field)num;
		}

		private void Adjust(int direction)
		{
			bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			switch (_focus)
			{
			case Field.Item:
				if (_items.Count != 0)
				{
					(EchoOdds.Mode, ItemTier, string)? currentMode = CurrentMode;
					if (!currentMode.HasValue || currentMode.GetValueOrDefault().Item1 != EchoOdds.Mode.Trade)
					{
						_itemIndex = (_itemIndex + direction + _items.Count) % _items.Count;
						_modeIndex = 0;
						_count = 1;
						_gold = 0;
						_targetIndex = -1;
						ClearStake();
					}
				}
				break;
			case Field.Mode:
				if (_modes.Count != 0)
				{
					_modeIndex = (_modeIndex + direction + _modes.Count) % _modes.Count;
					_gold = 0;
					_targetIndex = -1;
				}
				break;
			case Field.Target:
			{
				(EchoOdds.Mode, ItemTier, string)? currentMode2 = CurrentMode;
				if (currentMode2.HasValue && currentMode2.Value.Item1 == EchoOdds.Mode.Trade && _targetPool.Count != 0)
				{
					int num3 = Mathf.Max(_targetIndex, 0);
					_targetIndex = (num3 + direction + _targetPool.Count) % _targetPool.Count;
				}
				break;
			}
			case Field.Count:
			{
				(EchoOdds.Mode, ItemTier, string)? currentMode = CurrentMode;
				if (!currentMode.HasValue || currentMode.GetValueOrDefault().Item1 != EchoOdds.Mode.Trade)
				{
					_count = Mathf.Clamp(_count + direction * ((!flag) ? 1 : 10), 1, MaxStake());
				}
				break;
			}
			case Field.Gold:
			{
				int num = TradeDistance();
				if (num >= 0)
				{
					EchoOdds.Difficulty difficulty = EchoOdds.DifficultyFor(num);
					int num2 = Mathf.Min(Mathf.RoundToInt(5f) * difficulty.GoldPerStep, WalletGold());
					_gold = Mathf.Clamp(_gold + direction * difficulty.GoldPerStep * ((!flag) ? 1 : 5), 0, num2);
				}
				break;
			}
			}
		}

		private void Activate()
		{
			switch (_focus)
			{
			case Field.Item:
				if (_items.Count > 0)
				{
					OpenPicker(Field.Item);
				}
				break;
			case Field.Target:
			{
				(EchoOdds.Mode, ItemTier, string)? currentMode = CurrentMode;
				if (currentMode.HasValue && currentMode.Value.Item1 == EchoOdds.Mode.Trade && _targetPool.Count > 0)
				{
					OpenPicker(Field.Target);
				}
				break;
			}
			case Field.Spin:
				Submit();
				break;
			}
		}

		private void Submit()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected I4, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected I4, but got Unknown
			//IL_012d: 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_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: 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_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			ItemDef currentItem = CurrentItem;
			(EchoOdds.Mode, ItemTier, string)? currentMode = CurrentMode;
			if ((Object)(object)currentItem == (Object)null || !currentMode.HasValue)
			{
				return;
			}
			bool flag = currentMode.Value.Item1 == EchoOdds.Mode.Trade;
			List<int> list = new List<int>();
			List<int> list2 = new List<int>();
			if (flag)
			{
				for (int i = 0; i < _stake.Count; i++)
				{
					if (_stake[i] > 0)
					{
						list.Add((int)_items[i].itemIndex);
						list2.Add(_stake[i]);
					}
				}
			}
			else
			{
				if (_count > OwnedCount())
				{
					return;
				}
				list.Add((int)currentItem.itemIndex);
				list2.Add(_count);
			}
			if (list.Count == 0)
			{
				return;
			}
			if (flag)
			{
				int num = TradeDistance();
				if (num < 0)
				{
					return;
				}
				EchoOdds.Difficulty difficulty = EchoOdds.DifficultyFor(num);
				int num2 = StakeTotal();
				if (num2 < difficulty.MinCount || num2 > difficulty.MaxCount)
				{
					return;
				}
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			NetworkInstanceId? obj;
			if (firstLocalUser == null)
			{
				obj = null;
			}
			else
			{
				NetworkUser currentNetworkUser = firstLocalUser.currentNetworkUser;
				obj = ((currentNetworkUser != null) ? new NetworkInstanceId?(((NetworkBehaviour)currentNetworkUser).netId) : ((NetworkInstanceId?)null));
			}
			NetworkInstanceId val = (NetworkInstanceId)(((??)obj) ?? NetworkInstanceId.Invalid);
			if (!(val == NetworkInstanceId.Invalid))
			{
				_phase = Phase.Spinning;
				((TMP_Text)_hintText).text = EchoUI.C("çekiliyor...", "#94A3B8");
				ItemDef currentTarget = CurrentTarget;
				int targetItem = (((Object)(object)currentTarget == (Object)null) ? (-1) : ((int)currentTarget.itemIndex));
				NetMessageExtensions.Send((INetMessage)(object)new EchoGambleRequest(list.ToArray(), list2.ToArray(), currentMode.Value.Item1, _gold, targetItem, val), (NetworkDestination)2);
			}
		}

		private void Refresh()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			RebuildModes();
			RebuildTargetPool();
			(EchoOdds.Mode, ItemTier, string)? currentMode = CurrentMode;
			if (currentMode.HasValue && currentMode.Value.Item1 == EchoOdds.Mode.Trade && StakeTotal() == 0)
			{
				StakeAdd(_itemIndex, 1);
			}
			ItemDef currentItem = CurrentItem;
			bool flag = currentMode.HasValue && currentMode.Value.Item1 == EchoOdds.Mode.Trade;
			int num = StakeKinds();
			((TMP_Text)_rows[0]).text = Row("ITEM", _focus == Field.Item, ((Object)(object)currentItem == (Object)null) ? "—" : ((flag && num > 1) ? EchoUI.C($"{StakeTotal()} {EchoOdds.TierName(currentItem.tier)} item", EchoOdds.TierColor(currentItem.tier)) : EchoUI.C(EchoOdds.ItemName(currentItem), EchoOdds.TierColor(currentItem.tier))), ((Object)(object)currentItem == (Object)null) ? "" : (flag ? EchoUI.C((num > 1) ? $"{num} çeşit" : "ENTER = yığın kur", "#94A3B8") : EchoUI.C($"sende {OwnedCount()}", "#94A3B8")));
			((TMP_Text)_rows[1]).text = Row("MOD", _focus == Field.Mode, currentMode?.Item3 ?? "—", "");
			bool flag2 = currentMode.HasValue && currentMode.Value.Item1 == EchoOdds.Mode.Trade && _targetPool.Count > 0;
			ItemDef currentTarget = CurrentTarget;
			((TMP_Text)_rows[2]).text = Row("HEDEF", _focus == Field.Target, (!flag2) ? EchoUI.C("—", "#94A3B8") : (((Object)(object)currentTarget == (Object)null) ? EchoUI.C("seçilmedi", "#94A3B8") : EchoUI.C(EchoOdds.ItemName(currentTarget), EchoOdds.TierColor(currentTarget.tier))), (flag2 && (Object)(object)currentTarget != (Object)null) ? EchoUI.C(EchoOdds.TierName(currentTarget.tier), "#94A3B8") : "");
			if (flag)
			{
				int num2 = StakeTotal() - StakeCap();
				if (num2 > 0)
				{
					TrimStake(num2);
				}
			}
			else
			{
				_count = Mathf.Clamp(_count, 1, MaxStake());
			}
			((TMP_Text)_rows[3]).text = Row("ADET", _focus == Field.Count, flag ? EchoUI.C(StakeTotal().ToString(), "#94A3B8") : _count.ToString(), flag ? EchoUI.C($"tavan {StakeCap()} · ITEM'dan ayarla", "#94A3B8") : EchoUI.C("shift = 10'ar", "#94A3B8"));
			bool flag3 = currentMode.HasValue && currentMode.Value.Item1 == EchoOdds.Mode.Trade;
			((TMP_Text)_rows[4]).text = Row("ALTIN", _focus == Field.Gold, flag3 ? _gold.ToString() : EchoUI.C("—", "#94A3B8"), EchoUI.C($"cüzdan {WalletGold()}", "#94A3B8"));
			((TMP_Text)_rows[5]).text = ((_focus == Field.Spin) ? EchoUI.B(EchoUI.C("[ ÇEVİR ]", "#FBBF24")) : EchoUI.C("  ÇEVİR", "#94A3B8"));
			((TMP_Text)_chanceText).text = BuildChanceLine(currentItem, currentMode);
			string text = ((_focus == Field.Item || _focus == Field.Target) ? ("↑↓ satır   ENTER listeyi aç   " + EchoPanels.KeyName(_closeKey) + " kapat") : ((_focus != Field.Spin) ? ("↑↓ satır   ←→ değer (shift = 10'ar)   " + EchoPanels.KeyName(_closeKey) + " kapat") : ("↑↓ satır   ENTER masayı çevir   " + EchoPanels.KeyName(_closeKey) + " kapat")));
			((TMP_Text)_hintText).text = EchoUI.C(text, "#94A3B8");
		}

		private string BuildChanceLine(ItemDef item, (EchoOdds.Mode Mode, ItemTier Target, string Label)? mode)
		{
			//IL_00d4: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null || !mode.HasValue)
			{
				return EchoUI.C("oynanabilir item'ın yok.", "#F87171");
			}
			if (mode.Value.Mode == EchoOdds.Mode.Multiply)
			{
				return EchoUI.Stat("şans", $"%{Mathf.RoundToInt(50f)} kazanç", "#A78BFA") + "     " + EchoUI.C($"(%50 → 0  ·  %25 → {EchoOdds.BoostedCount(_count)}  ·  " + $"%20 → {_count * 2}  ·  %5 → {_count * 3})", "#94A3B8");
			}
			ItemDef currentTarget = CurrentTarget;
			if ((Object)(object)currentTarget == (Object)null)
			{
				return EchoUI.C("HEDEF satırından ne istediğini seç.", "#94A3B8");
			}
			int num = EchoOdds.Distance(item.tier, currentTarget.tier);
			if (num < 0)
			{
				return EchoUI.C("bu takas yapılamaz.", "#F87171");
			}
			EchoOdds.Difficulty difficulty = EchoOdds.DifficultyFor(num);
			int num2 = StakeTotal();
			if (num2 < difficulty.MinCount)
			{
				return EchoUI.C($"bu takas {difficulty.MinCount} adet istiyor, yığında {num2} var — " + "ITEM satırından ekle.", "#F87171");
			}
			int num3 = EchoOdds.GoldSteps(_gold, WalletGold(), difficulty);
			float num4 = EchoOdds.TradeChance(item.tier, currentTarget.tier, num2, num3);
			string text = EchoUI.Stat("şans", $"%{Mathf.RoundToInt(num4 * 100f)}", "#A78BFA");
			if (num3 > 0)
			{
				text = text + "     " + EchoUI.C($"(altından +%{Mathf.RoundToInt((float)num3 * 0.05f * 100f)})", "#FBBF24");
			}
			return text + "     " + EchoUI.C("→ " + EchoOdds.ItemName(currentTarget), EchoOdds.TierColor(currentTarget.tier));
		}

		private static string Row(string label, bool focused, string value, string suffix)
		{
			string text = (focused ? EchoUI.C("> ", "#FBBF24") : "  ");
			string text2 = "";
			string hex = (focused ? "#FBBF24" : "#94A3B8");
			string text3 = EchoUI.C(label.PadRight(6), hex) + text + EchoUI.B(value) + text2;
			if (!string.IsNullOrEmpty(suffix))
			{
				text3 = text3 + "     " + suffix;
			}
			return text3;
		}

		private IEnumerator Spin(EchoGambleResult result)
		{
			_phase = Phase.Spinning;
			((Component)_formGroup.transform.parent).gameObject.SetActive(false);
			((Component)_reelGroup.transform.parent).gameObject.SetActive(true);
			List<string> reel = result.Reel;
			if (reel.Count == 0)
			{
				yield break;
			}
			int totalTicks = reel.Count + 2;
			float wait = 0.045f;
			for (int tick = 0; tick < totalTicks; tick++)
			{
				for (int i = 0; i < 5; i++)
				{
					int num = tick - 2 + i;
					string label = ((num >= 0 && num < reel.Count) ? reel[num] : "");
					((TMP_Text)_cells[i]).text = Paint(label, i == 2, result.ResultTier);
				}
				yield return (object)new WaitForSecondsRealtime(wait);
				int num2 = totalTicks - tick;
				if (num2 < 6)
				{
					wait += 0.09f;
				}
				else if (num2 < 12)
				{
					wait += 0.02f;
				}
			}
			((TMP_Text)_chanceText).text = Verdict(result);
			Memory.LastResult = EchoUI.C(result.StakeLabel, "#94A3B8") + "  →  " + Verdict(result);
			((TMP_Text)_hintText).text = EchoUI.C("ENTER tekrar oyna   " + EchoPanels.KeyName(_closeKey) + " kapat", "#94A3B8");
			_phase = Phase.Done;
		}

		private static string Paint(string label, bool isSelector, byte tier)
		{
			if (string.IsNullOrEmpty(label))
			{
				return "";
			}
			string hex = ((label == "YANDI") ? "#F87171" : EchoOdds.TierColor((ItemTier)tier));
			if (!isSelector)
			{
				hex = "#94A3B8";
			}
			if (!isSelector)
			{
				return EchoUI.C(label, hex);
			}
			return EchoUI.B(EchoUI.C(label, hex));
		}

		private static string Verdict(EchoGambleResult result)
		{
			if (result.Jackpot)
			{
				return EchoUI.B(EchoUI.C("JACKPOT — " + result.ResultLabel, "#FBBF24"));
			}
			if (result.Won)
			{
				return EchoUI.B(EchoUI.C("KAZANDIN — " + result.ResultLabel, "#34D399"));
			}
			string text = ((result.GoldSpent > 0) ? $"  (+{result.GoldSpent} altın da gitti)" : "");
			return EchoUI.B(EchoUI.C("YANDI" + text, "#F87171"));
		}
	}
	internal static class EchoForge
	{
		private struct Burn
		{
			public ItemDef Item;

			public int Count;
		}

		public static void HandleRequest(NetworkInstanceId senderId, int targetItem, int goldPoints, int[] fuelItems, int[] fuelCounts)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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)
			//I