Decompiled source of Blind Deaf and Mute Challenge v1.1.0

tony4twentys-Blind Deaf and Mute Challenge.dll

Decompiled 17 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PEAKLib.Core;
using Photon.Pun;
using Photon.Realtime;
using PhotonCustomPropsUtils;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;
using Zorro.Settings;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Blind Deaf and Mute Challenge")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Blind Deaf and Mute Challenge")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c2254fa2-c18c-428a-b0c2-1c7b26f94967")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
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 BlindDeafMuteChallenge
{
	internal static class BdmAbilityHud
	{
		private sealed class AbilityWidget
		{
			internal GameObject Root;

			internal Image OuterFill;

			internal Image OuterEmpty;

			internal Image InnerFill;

			internal Image InnerEmpty;

			internal GameObject InnerRoot;

			internal Image Icon;

			internal TextMeshProUGUI Label;

			internal CanvasGroup Group;
		}

		private const int SortOrder = 6000;

		private const float Gap = 100f;

		private const float IconSize = 32f;

		private const float InnerScale = 0.72f;

		private static readonly Color DefaultCooldownColor = new Color(1f, 0.82f, 0.15f, 1f);

		private static readonly Color DefaultUseColor = new Color(0.72f, 0.35f, 0.95f, 1f);

		private static GameObject _root;

		private static Canvas _canvas;

		private static RectTransform _row;

		private static AbilityWidget _sonar;

		private static AbilityWidget _hook;

		private static AbilityWidget _detection;

		private static Sprite _sonarSprite;

		private static Sprite _hookSprite;

		private static Sprite _detectionSprite;

		private static int _hookIconItemId = int.MinValue;

		private static bool _detectionIconTried;

		private static bool _loggedMissingTemplate;

		private static bool _loggedCloned;

		internal static void EnsureCreated()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root != (Object)null))
			{
				_root = new GameObject("BDM_AbilityHud");
				Object.DontDestroyOnLoad((Object)(object)_root);
				_canvas = _root.AddComponent<Canvas>();
				_canvas.renderMode = (RenderMode)0;
				_canvas.sortingOrder = 6000;
				CanvasScaler val = _root.AddComponent<CanvasScaler>();
				val.uiScaleMode = (ScaleMode)1;
				val.referenceResolution = new Vector2(1920f, 1080f);
				GameObject val2 = new GameObject("Row");
				val2.transform.SetParent(_root.transform, false);
				_row = val2.AddComponent<RectTransform>();
				_row.anchorMin = new Vector2(0.5f, 0f);
				_row.anchorMax = new Vector2(0.5f, 0f);
				_row.pivot = new Vector2(0.5f, 0f);
				_row.anchoredPosition = new Vector2(0f, 0f);
				_row.sizeDelta = new Vector2(280f, 140f);
				_root.SetActive(false);
			}
		}

		internal static void Shutdown()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
				_root = null;
			}
			_canvas = null;
			_row = null;
			_sonar = null;
			_hook = null;
			_detection = null;
			_sonarSprite = null;
			_hookSprite = null;
			_detectionSprite = null;
			_hookIconItemId = int.MinValue;
			_detectionIconTried = false;
			_loggedMissingTemplate = false;
			_loggedCloned = false;
		}

		internal static void Tick()
		{
			EnsureCreated();
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)instance == (Object)null || !BdmModAuthorizationService.CanUseSyncedChallenge())
			{
				if ((Object)(object)_root != (Object)null && _root.activeSelf)
				{
					_root.SetActive(false);
				}
				return;
			}
			BdmSyncedSettings effectiveSettings = instance.GetEffectiveSettings();
			bool flag = instance.IsBlindEffectWanted() && effectiveSettings.EnableSonar;
			bool flag2 = instance.IsLocalMuteActive && effectiveSettings.EnableRescueHook;
			bool flag3 = instance.IsLocalDeafActive && effectiveSettings.EnableDetection;
			if (!flag && !flag2 && !flag3)
			{
				if (_root.activeSelf)
				{
					_root.SetActive(false);
				}
				return;
			}
			if (!EnsureWidgetsFromVanillaTemplate())
			{
				if (_root.activeSelf)
				{
					_root.SetActive(false);
				}
				return;
			}
			if (!_root.activeSelf)
			{
				_root.SetActive(true);
			}
			EnsureIcons();
			ApplyLiveLayout();
			if (_sonar != null)
			{
				_sonar.Root.SetActive(flag);
				if (flag)
				{
					UpdateWidget(_sonar, BdmBlindSonar.HudCooldownFill, BdmBlindSonar.HudUseFill, BdmBlindSonar.IsReady, BdmBlindSonar.IsActive, "Sonar");
				}
			}
			if (_detection != null)
			{
				_detection.Root.SetActive(flag3);
				if (flag3)
				{
					UpdateWidget(_detection, BdmDeafDetection.HudCooldownFill, BdmDeafDetection.HudUseFill, BdmDeafDetection.IsReady, BdmDeafDetection.IsActive, "Detection");
				}
			}
			if (_hook != null)
			{
				_hook.Root.SetActive(flag2);
				if (flag2)
				{
					UpdateWidget(_hook, BdmMuteRescueHook.HudCooldownFill, BdmMuteRescueHook.HudUseFill, BdmMuteRescueHook.IsReady, BdmMuteRescueHook.IsActive, "Lifeline");
				}
			}
			LayoutWidgets(flag, flag3, flag2);
		}

		private static void ApplyLiveLayout()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			float num = (((Object)(object)instance != (Object)null) ? instance.AbilityHudPosX : 0f);
			float num2 = (((Object)(object)instance != (Object)null) ? instance.AbilityHudPosY : 0f);
			float labelY = (((Object)(object)instance != (Object)null) ? instance.AbilityHudLabelOffsetY : 54f);
			float fontSize = (((Object)(object)instance != (Object)null) ? instance.AbilityHudLabelFontSize : 30f);
			if ((Object)(object)_row != (Object)null)
			{
				_row.anchoredPosition = new Vector2(num, num2);
			}
			ApplyLabelStyle(_sonar, labelY, fontSize);
			ApplyLabelStyle(_detection, labelY, fontSize);
			ApplyLabelStyle(_hook, labelY, fontSize);
		}

		private static void ApplyLabelStyle(AbilityWidget widget, float labelY, float fontSize)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)widget?.Label == (Object)null))
			{
				RectTransform rectTransform = ((TMP_Text)widget.Label).rectTransform;
				rectTransform.anchoredPosition = new Vector2(0f, labelY);
				rectTransform.sizeDelta = new Vector2(Mathf.Max(160f, fontSize * 7.5f), Mathf.Max(22f, fontSize + 6f));
				((TMP_Text)widget.Label).fontSize = fontSize;
				BdmGameUiFont.Apply(widget.Label);
			}
		}

		private static Color GetCooldownColor()
		{
			//IL_0018: 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_001d: 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)
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			return ((Object)(object)instance != (Object)null) ? instance.AbilityHudCooldownColor : DefaultCooldownColor;
		}

		private static Color GetUseColor()
		{
			//IL_0018: 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_001d: 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)
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			return ((Object)(object)instance != (Object)null) ? instance.AbilityHudUseColor : DefaultUseColor;
		}

		private static bool EnsureWidgetsFromVanillaTemplate()
		{
			if (_sonar != null && _hook != null && _detection != null)
			{
				return true;
			}
			UI_UseItemProgress val = FindVanillaProgress();
			if ((Object)(object)val == (Object)null || (Object)(object)val.fill == (Object)null || (Object)(object)val.empty == (Object)null)
			{
				if (!_loggedMissingTemplate)
				{
					_loggedMissingTemplate = true;
					BlindDeafMuteChallengePlugin.Instance?.LogDebug("[BlindDeafMute] Ability HUD waiting for vanilla UI_UseItemProgress...");
				}
				return false;
			}
			if (_sonar == null)
			{
				_sonar = CloneDualRingWidget(val, "Sonar");
			}
			if (_detection == null)
			{
				_detection = CloneDualRingWidget(val, "Detection");
			}
			if (_hook == null)
			{
				_hook = CloneDualRingWidget(val, "RescueHook");
			}
			if (_sonar == null || _hook == null || _detection == null)
			{
				return false;
			}
			if (!_loggedCloned)
			{
				_loggedCloned = true;
				BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Ability HUD: dual concentric UI_UseItemProgress rings ready.");
			}
			return true;
		}

		private static UI_UseItemProgress FindVanillaProgress()
		{
			try
			{
				if ((Object)(object)GUIManager.instance != (Object)null && (Object)(object)GUIManager.instance.hudCanvas != (Object)null)
				{
					UI_UseItemProgress componentInChildren = ((Component)GUIManager.instance.hudCanvas).GetComponentInChildren<UI_UseItemProgress>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						return componentInChildren;
					}
				}
			}
			catch
			{
			}
			return Object.FindFirstObjectByType<UI_UseItemProgress>((FindObjectsInactive)1);
		}

		private static AbilityWidget CloneDualRingWidget(UI_UseItemProgress template, string name)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Expected O, but got Unknown
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)template == (Object)null || (Object)(object)_row == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("BDM_" + name);
			val.transform.SetParent((Transform)(object)_row, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = Vector2.zero;
			val2.sizeDelta = new Vector2(120f, 140f);
			CanvasGroup val4 = val.AddComponent<CanvasGroup>();
			val4.blocksRaycasts = false;
			val4.interactable = false;
			if (!TryCloneRingPair(template, val.transform, "Outer", 1f, GetCooldownColor(), out var fill, out var empty, out var _))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			if (!TryCloneRingPair(template, val.transform, "Inner", 0.72f, GetUseColor(), out var fill2, out var empty2, out var cloneRoot2))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			GameObject val5 = new GameObject("BDM_Icon");
			val5.transform.SetParent(val.transform, false);
			RectTransform val6 = val5.AddComponent<RectTransform>();
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val6.anchorMax = val3;
			val6.anchorMin = val3;
			val6.pivot = new Vector2(0.5f, 0.5f);
			val6.sizeDelta = new Vector2(32f, 32f);
			val6.anchoredPosition = Vector2.zero;
			Image val7 = val5.AddComponent<Image>();
			val7.preserveAspect = true;
			((Graphic)val7).raycastTarget = false;
			((Graphic)val7).color = Color.white;
			GameObject val8 = new GameObject("BDM_Label");
			val8.transform.SetParent(val.transform, false);
			RectTransform val9 = val8.AddComponent<RectTransform>();
			val9.anchorMin = new Vector2(0.5f, 0f);
			val9.anchorMax = new Vector2(0.5f, 0f);
			val9.pivot = new Vector2(0.5f, 1f);
			val9.anchoredPosition = new Vector2(0f, 54f);
			val9.sizeDelta = new Vector2(220f, 36f);
			TextMeshProUGUI val10 = val8.AddComponent<TextMeshProUGUI>();
			((Graphic)val10).raycastTarget = false;
			((TMP_Text)val10).enableWordWrapping = false;
			((TMP_Text)val10).overflowMode = (TextOverflowModes)0;
			((TMP_Text)val10).alignment = (TextAlignmentOptions)258;
			((TMP_Text)val10).fontSize = 30f;
			((TMP_Text)val10).fontStyle = (FontStyles)0;
			((Graphic)val10).color = new Color(1f, 1f, 1f, 0.92f);
			((TMP_Text)val10).text = ((name == "RescueHook") ? "Lifeline" : name);
			BdmGameUiFont.Apply(val10);
			return new AbilityWidget
			{
				Root = val,
				OuterFill = fill,
				OuterEmpty = empty,
				InnerFill = fill2,
				InnerEmpty = empty2,
				InnerRoot = cloneRoot2,
				Icon = val7,
				Label = val10,
				Group = val4
			};
		}

		private static bool TryCloneRingPair(UI_UseItemProgress template, Transform parent, string name, float scale, Color fillColor, out Image fill, out Image empty, out GameObject cloneRoot)
		{
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: 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_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Invalid comparison between Unknown and I4
			fill = null;
			empty = null;
			cloneRoot = null;
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent, false);
			((Object)val).name = name;
			val.SetActive(true);
			cloneRoot = val;
			UI_UseItemProgress component = val.GetComponent<UI_UseItemProgress>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			fill = (((Object)(object)component != (Object)null) ? component.fill : null);
			empty = (((Object)(object)component != (Object)null) ? component.empty : null);
			if ((Object)(object)fill == (Object)null || (Object)(object)empty == (Object)null)
			{
				Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if (!((Object)(object)componentsInChildren[i] == (Object)null))
					{
						if ((Object)(object)fill == (Object)null && (int)componentsInChildren[i].type == 3)
						{
							fill = componentsInChildren[i];
						}
						else if ((Object)(object)empty == (Object)null && (Object)(object)componentsInChildren[i] != (Object)(object)fill)
						{
							empty = componentsInChildren[i];
						}
					}
				}
			}
			if ((Object)(object)fill == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				cloneRoot = null;
				return false;
			}
			RectTransform component2 = val.GetComponent<RectTransform>();
			if ((Object)(object)component2 != (Object)null)
			{
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0.5f, 0.5f);
				component2.anchorMax = val2;
				component2.anchorMin = val2;
				component2.pivot = new Vector2(0.5f, 0.5f);
				component2.anchoredPosition = Vector2.zero;
				((Transform)component2).localScale = Vector3.one * scale;
			}
			ConfigureRadial(fill, fillColor);
			if ((Object)(object)empty != (Object)null)
			{
				((Behaviour)empty).enabled = true;
				((Graphic)empty).raycastTarget = false;
			}
			return true;
		}

		private static void ConfigureRadial(Image fill, Color color)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)fill == (Object)null))
			{
				if ((int)fill.type != 3)
				{
					fill.type = (Type)3;
					fill.fillMethod = (FillMethod)4;
					fill.fillOrigin = 2;
					fill.fillClockwise = true;
				}
				((Graphic)fill).color = color;
				((Behaviour)fill).enabled = true;
				((Graphic)fill).raycastTarget = false;
			}
		}

		private static void LayoutWidgets(bool showSonar, bool showDetection, bool showHook)
		{
			List<AbilityWidget> list = new List<AbilityWidget>(3);
			if (showSonar && _sonar != null)
			{
				list.Add(_sonar);
			}
			if (showDetection && _detection != null)
			{
				list.Add(_detection);
			}
			if (showHook && _hook != null)
			{
				list.Add(_hook);
			}
			if (list.Count != 0)
			{
				if (list.Count == 1)
				{
					SetWidgetX(list[0], 0f);
				}
				else if (list.Count == 2)
				{
					float num = 50f;
					SetWidgetX(list[0], 0f - num);
					SetWidgetX(list[1], num);
				}
				else
				{
					SetWidgetX(list[0], -100f);
					SetWidgetX(list[1], 0f);
					SetWidgetX(list[2], 100f);
				}
			}
		}

		private static void SetWidgetX(AbilityWidget widget, float x)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = widget.Root.GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null)
			{
				component.anchoredPosition = new Vector2(x, 24f);
			}
		}

		private static void UpdateWidget(AbilityWidget widget, float cooldownFill, float useFill, bool ready, bool active, string labelText)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			cooldownFill = Mathf.Clamp01(cooldownFill);
			useFill = Mathf.Clamp01(useFill);
			if ((Object)(object)widget.Root != (Object)null)
			{
				Vector3 localScale = widget.Root.transform.localScale;
				if (((Vector3)(ref localScale)).sqrMagnitude < 0.01f)
				{
					widget.Root.transform.localScale = Vector3.one;
				}
			}
			if ((Object)(object)widget.OuterFill != (Object)null)
			{
				ConfigureRadial(widget.OuterFill, GetCooldownColor());
				widget.OuterFill.fillAmount = cooldownFill;
			}
			if ((Object)(object)widget.OuterEmpty != (Object)null)
			{
				((Behaviour)widget.OuterEmpty).enabled = true;
			}
			bool flag = active || useFill > 0.001f;
			if ((Object)(object)widget.InnerRoot != (Object)null)
			{
				widget.InnerRoot.SetActive(flag);
			}
			if (flag && (Object)(object)widget.InnerFill != (Object)null)
			{
				ConfigureRadial(widget.InnerFill, GetUseColor());
				widget.InnerFill.fillAmount = useFill;
			}
			if ((Object)(object)widget.InnerEmpty != (Object)null)
			{
				((Behaviour)widget.InnerEmpty).enabled = flag;
			}
			float a = (ready ? 1f : (active ? 0.95f : Mathf.Lerp(0.35f, 0.9f, cooldownFill)));
			if ((Object)(object)widget.Icon != (Object)null)
			{
				Color color = ((Graphic)widget.Icon).color;
				color.a = a;
				((Graphic)widget.Icon).color = color;
			}
			if ((Object)(object)widget.Group != (Object)null)
			{
				widget.Group.alpha = (ready ? 1f : 0.95f);
			}
			if ((Object)(object)widget.Label != (Object)null)
			{
				if (((TMP_Text)widget.Label).text != labelText)
				{
					((TMP_Text)widget.Label).text = labelText;
				}
				BdmGameUiFont.Apply(widget.Label);
			}
		}

		private static void EnsureIcons()
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			if (_sonar != null && (Object)(object)_sonar.Icon != (Object)null && (Object)(object)_sonarSprite == (Object)null)
			{
				Texture2D val = TryEmojiTex("1f987") ?? TryEmojiTex("1f3a7") ?? TryEmojiTex("1f50a") ?? TryEmojiTex("1f4e3");
				if ((Object)(object)val != (Object)null)
				{
					_sonarSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
					_sonar.Icon.sprite = _sonarSprite;
				}
			}
			if (_detection != null && (Object)(object)_detection.Icon != (Object)null && !_detectionIconTried)
			{
				_detectionIconTried = true;
				Texture2D val2 = TryEmojiTex("1f9f3") ?? TryEmojiTex("1f4bc") ?? TryEmojiTex("1f6aa") ?? TryEmojiTex("1f4e6");
				if ((Object)(object)val2 != (Object)null)
				{
					_detectionSprite = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), 100f);
					_detection.Icon.sprite = _detectionSprite;
				}
			}
			if (_hook != null && (Object)(object)_hook.Icon != (Object)null)
			{
				BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
				int num = (((Object)(object)instance != (Object)null) ? instance.GetEffectiveSettings().RescueHookItemId : 167);
				if (num != _hookIconItemId)
				{
					TryAssignHookIcon(num);
				}
			}
		}

		private static void TryAssignHookIcon(int itemId)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Item val = default(Item);
				if (!ItemDatabase.TryGetItem((ushort)Mathf.Clamp(itemId, 1, 65535), ref val) || (Object)(object)val == (Object)null || val.UIData == null)
				{
					return;
				}
				Texture2D icon = val.UIData.GetIcon();
				if (!((Object)(object)icon == (Object)null))
				{
					if ((Object)(object)_hookSprite != (Object)null)
					{
						Object.Destroy((Object)(object)_hookSprite);
						_hookSprite = null;
					}
					_hookSprite = Sprite.Create(icon, new Rect(0f, 0f, (float)((Texture)icon).width, (float)((Texture)icon).height), new Vector2(0.5f, 0.5f), 100f);
					if ((Object)(object)_hook?.Icon != (Object)null)
					{
						_hook.Icon.sprite = _hookSprite;
					}
					_hookIconItemId = itemId;
				}
			}
			catch
			{
			}
		}

		private static Texture2D TryEmojiTex(string codeKey)
		{
			BdmEmojiCatalog.Entry entry = BdmEmojiCatalog.FindByCodeKey(codeKey);
			return (entry != null) ? BdmEmojiCatalog.GetTexture(entry) : null;
		}
	}
	internal static class BdmAssignmentSyncService
	{
		public const int SchemaVersion = 1;

		public const char PairSeparator = ';';

		public const char KeyValueSeparator = '=';

		internal static bool HasRemoteAssignments { get; private set; }

		internal static Dictionary<int, BlindDeafMuteChallengePlugin.AfflictionType> RemoteAssignments { get; private set; } = new Dictionary<int, BlindDeafMuteChallengePlugin.AfflictionType>();

		internal static void ClearRemoteAssignments()
		{
			HasRemoteAssignments = false;
			RemoteAssignments = new Dictionary<int, BlindDeafMuteChallengePlugin.AfflictionType>();
		}

		internal static void ApplyRemoteSnapshot(string payload)
		{
			if (!PhotonNetwork.IsMasterClient && !string.IsNullOrEmpty(payload))
			{
				if (!TryDeserialize(payload, out var map))
				{
					BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Failed to parse host assignment snapshot.");
					return;
				}
				HasRemoteAssignments = true;
				RemoteAssignments = map;
				BlindDeafMuteChallengePlugin.Instance?.LogAlways($"[BlindDeafMute] Applied host assignment snapshot ({map.Count} players).");
				BlindDeafMuteChallengePlugin.Instance?.ApplyRemoteAssignments(map);
			}
		}

		internal static string Serialize(IReadOnlyDictionary<int, BlindDeafMuteChallengePlugin.AfflictionType> assignments)
		{
			StringBuilder stringBuilder = new StringBuilder(128);
			Append(stringBuilder, "v", 1.ToString(CultureInfo.InvariantCulture));
			if (assignments != null)
			{
				foreach (KeyValuePair<int, BlindDeafMuteChallengePlugin.AfflictionType> assignment in assignments)
				{
					Append(stringBuilder, assignment.Key.ToString(CultureInfo.InvariantCulture), ((int)assignment.Value).ToString(CultureInfo.InvariantCulture));
				}
			}
			return stringBuilder.ToString();
		}

		internal static bool TryDeserialize(string payload, out Dictionary<int, BlindDeafMuteChallengePlugin.AfflictionType> map)
		{
			map = new Dictionary<int, BlindDeafMuteChallengePlugin.AfflictionType>();
			if (string.IsNullOrEmpty(payload))
			{
				return false;
			}
			if (payload.IndexOf('=') < 0 && payload.IndexOf(':') >= 0)
			{
				return TryDeserializeLegacy(payload, out map);
			}
			int result = 0;
			bool flag = false;
			string[] array = payload.Split(new char[1] { ';' });
			foreach (string text in array)
			{
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				int num = text.IndexOf('=');
				if (num > 0)
				{
					string text2 = text.Substring(0, num);
					string s = text.Substring(num + 1);
					int result2;
					int result3;
					if (text2 == "v")
					{
						flag = int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out result);
					}
					else if (int.TryParse(text2, NumberStyles.Integer, CultureInfo.InvariantCulture, out result2) && int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out result3) && Enum.IsDefined(typeof(BlindDeafMuteChallengePlugin.AfflictionType), result3))
					{
						map[result2] = (BlindDeafMuteChallengePlugin.AfflictionType)result3;
					}
				}
			}
			return flag && result == 1;
		}

		private static bool TryDeserializeLegacy(string payload, out Dictionary<int, BlindDeafMuteChallengePlugin.AfflictionType> map)
		{
			map = new Dictionary<int, BlindDeafMuteChallengePlugin.AfflictionType>();
			string[] array = payload.Split(new char[1] { '|' });
			foreach (string text in array)
			{
				string[] array2 = text.Split(new char[1] { ':' });
				if (array2.Length == 2 && int.TryParse(array2[0], out var result))
				{
					BlindDeafMuteChallengePlugin.AfflictionType result3;
					if (int.TryParse(array2[1], out var result2) && Enum.IsDefined(typeof(BlindDeafMuteChallengePlugin.AfflictionType), result2))
					{
						result3 = (BlindDeafMuteChallengePlugin.AfflictionType)result2;
					}
					else if (!Enum.TryParse<BlindDeafMuteChallengePlugin.AfflictionType>(array2[1], ignoreCase: true, out result3))
					{
						continue;
					}
					map[result] = result3;
				}
			}
			return map.Count > 0;
		}

		private static void Append(StringBuilder builder, string key, string value)
		{
			if (builder.Length > 0)
			{
				builder.Append(';');
			}
			builder.Append(key);
			builder.Append('=');
			builder.Append(value ?? string.Empty);
		}
	}
	internal static class BdmGameUiFont
	{
		private static TMP_FontAsset _cached;

		private static int _cachedSceneHandle = -1;

		internal static TMP_FontAsset Get()
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			int num = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle);
			if ((Object)(object)_cached != (Object)null && _cachedSceneHandle == num)
			{
				return _cached;
			}
			_cached = FindGameFont();
			_cachedSceneHandle = num;
			return _cached;
		}

		internal static void Apply(TextMeshProUGUI text)
		{
			if (!((Object)(object)text == (Object)null))
			{
				TMP_FontAsset val = Get();
				if ((Object)(object)val != (Object)null)
				{
					((TMP_Text)text).font = val;
				}
				((TMP_Text)text).fontStyle = (FontStyles)0;
			}
		}

		private static TMP_FontAsset FindGameFont()
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GUIManager instance = GUIManager.instance;
				if ((Object)(object)instance != (Object)null)
				{
					TextMeshProUGUI componentInChildren = ((Component)instance).GetComponentInChildren<TextMeshProUGUI>(true);
					if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((TMP_Text)componentInChildren).font != (Object)null)
					{
						return ((TMP_Text)componentInChildren).font;
					}
				}
			}
			catch
			{
			}
			try
			{
				TextMeshProUGUI val = Object.FindFirstObjectByType<TextMeshProUGUI>((FindObjectsInactive)1);
				if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null)
				{
					return ((TMP_Text)val).font;
				}
			}
			catch
			{
			}
			try
			{
				TextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll<TextMeshProUGUI>();
				foreach (TextMeshProUGUI val2 in array)
				{
					if ((Object)(object)val2 == (Object)null || (Object)(object)((TMP_Text)val2).font == (Object)null)
					{
						continue;
					}
					Scene scene = ((Component)val2).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						scene = ((Component)val2).gameObject.scene;
						if (((Scene)(ref scene)).isLoaded)
						{
							return ((TMP_Text)val2).font;
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}
	}
	internal static class BdmBlindMobility
	{
		[HarmonyPatch(typeof(CharacterMovement), "GetMovementForce")]
		private static class GetMovementForce_Patch
		{
			private static void Postfix(CharacterMovement __instance, ref float __result)
			{
				if (!((Object)(object)__instance == (Object)null) && WantBlindMobility(__instance.character))
				{
					BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
					float num = (((Object)(object)instance != (Object)null) ? Mathf.Clamp(instance.GetEffectiveSettings().BlindRunSpeedMultiplier, 1f, 3f) : 1.5f);
					__result *= num;
				}
			}
		}

		private static Character _climbAppliedTo;

		private static float _savedClimbMod = 1f;

		private static float _savedRopeMod = 1f;

		private static float _savedVineMod = 1f;

		private static bool _haveClimbSaved;

		internal static void Tick()
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)instance != (Object)null) || !instance.IsBlindEffectWanted() || !BdmModAuthorizationService.CanUseSyncedChallenge() || !instance.GetEffectiveSettings().EnableBlindMobility || !((Object)(object)localCharacter != (Object)null) || localCharacter.refs == null)
			{
				RestoreClimb();
			}
			else
			{
				ApplyClimb(localCharacter, instance.GetEffectiveSettings());
			}
		}

		internal static void Shutdown()
		{
			RestoreClimb();
		}

		private static bool WantBlindMobility(Character character)
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)character == (Object)null)
			{
				return false;
			}
			if ((Object)(object)character != (Object)(object)Character.localCharacter)
			{
				return false;
			}
			if (!instance.IsBlindEffectWanted() || !BdmModAuthorizationService.CanUseSyncedChallenge())
			{
				return false;
			}
			return instance.GetEffectiveSettings().EnableBlindMobility;
		}

		private static void ApplyClimb(Character local, BdmSyncedSettings s)
		{
			if ((Object)(object)_climbAppliedTo != (Object)(object)local || !_haveClimbSaved)
			{
				RestoreClimb();
				_savedClimbMod = (((Object)(object)local.refs.climbing != (Object)null) ? local.refs.climbing.climbSpeedMod : 1f);
				_savedRopeMod = (((Object)(object)local.refs.ropeHandling != (Object)null) ? local.refs.ropeHandling.climbSpeedMod : 1f);
				_savedVineMod = (((Object)(object)local.refs.vineClimbing != (Object)null) ? local.refs.vineClimbing.climbSpeedMod : 1f);
				_haveClimbSaved = true;
				_climbAppliedTo = local;
			}
			float num = Mathf.Clamp(s.BlindClimbSpeedMultiplier, 1f, 3f);
			if ((Object)(object)local.refs.climbing != (Object)null)
			{
				local.refs.climbing.climbSpeedMod = _savedClimbMod * num;
			}
			if ((Object)(object)local.refs.ropeHandling != (Object)null)
			{
				local.refs.ropeHandling.climbSpeedMod = _savedRopeMod * num;
			}
			if ((Object)(object)local.refs.vineClimbing != (Object)null)
			{
				local.refs.vineClimbing.climbSpeedMod = _savedVineMod * num;
			}
		}

		private static void RestoreClimb()
		{
			if (!_haveClimbSaved || (Object)(object)_climbAppliedTo == (Object)null)
			{
				_haveClimbSaved = false;
				_climbAppliedTo = null;
				return;
			}
			try
			{
				if ((Object)(object)_climbAppliedTo.refs?.climbing != (Object)null)
				{
					_climbAppliedTo.refs.climbing.climbSpeedMod = _savedClimbMod;
				}
				if ((Object)(object)_climbAppliedTo.refs?.ropeHandling != (Object)null)
				{
					_climbAppliedTo.refs.ropeHandling.climbSpeedMod = _savedRopeMod;
				}
				if ((Object)(object)_climbAppliedTo.refs?.vineClimbing != (Object)null)
				{
					_climbAppliedTo.refs.vineClimbing.climbSpeedMod = _savedVineMod;
				}
			}
			catch
			{
			}
			_haveClimbSaved = false;
			_climbAppliedTo = null;
		}
	}
	internal static class BdmBlindSonar
	{
		private static Coroutine _routine;

		private static float _cooldownStartedAt = -1f;

		private static float _useStartedAt = -1f;

		private static float _useDurationSeconds = 1f;

		private static bool _controllingBlackout;

		internal static bool IsActive => _routine != null;

		internal static bool IsControllingBlackout => _controllingBlackout;

		internal static bool IsOnCooldown => CooldownRemainingSeconds > 0f;

		internal static float CooldownRemainingSeconds
		{
			get
			{
				if (_cooldownStartedAt < 0f)
				{
					return 0f;
				}
				float liveCooldownSeconds = GetLiveCooldownSeconds();
				return Mathf.Max(0f, _cooldownStartedAt + liveCooldownSeconds - Time.unscaledTime);
			}
		}

		internal static bool IsReady => !IsActive && !IsOnCooldown;

		internal static float CooldownDurationSeconds => GetLiveCooldownSeconds();

		internal static float ActiveRemainingSeconds => (!IsActive) ? 0f : Mathf.Max(0f, _useStartedAt + _useDurationSeconds - Time.unscaledTime);

		internal static float HudCooldownFill
		{
			get
			{
				if (!IsOnCooldown && !IsActive)
				{
					return 1f;
				}
				float cooldownDurationSeconds = CooldownDurationSeconds;
				if (cooldownDurationSeconds <= 0.01f || _cooldownStartedAt < 0f)
				{
					return 1f;
				}
				return Mathf.Clamp01(1f - CooldownRemainingSeconds / cooldownDurationSeconds);
			}
		}

		internal static float HudUseFill
		{
			get
			{
				if (!IsActive || _useDurationSeconds <= 0.01f)
				{
					return 0f;
				}
				return Mathf.Clamp01(ActiveRemainingSeconds / _useDurationSeconds);
			}
		}

		internal static void TryActivate()
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (!instance.IsBlindEffectWanted() || !BdmModAuthorizationService.CanUseSyncedChallenge())
			{
				instance.LogAlways("[BlindDeafMute] Sonar is for Blind players only.");
				return;
			}
			BdmSyncedSettings effectiveSettings = instance.GetEffectiveSettings();
			if (!effectiveSettings.EnableSonar)
			{
				instance.LogAlways("[BlindDeafMute] Sonar power is disabled by host.");
				return;
			}
			if (IsActive)
			{
				instance.LogAlways("[BlindDeafMute] Sonar already active.");
				return;
			}
			if (IsOnCooldown)
			{
				instance.LogAlways($"[BlindDeafMute] Sonar on cooldown ({CooldownRemainingSeconds:0}s left).");
				return;
			}
			BdmSyncedSettings bdmSyncedSettings = effectiveSettings;
			int num = Mathf.Clamp(bdmSyncedSettings.SonarPingCount, 1, 10);
			float num2 = Mathf.Max(0.1f, bdmSyncedSettings.SonarVisionSeconds);
			float num3 = Mathf.Max(0f, bdmSyncedSettings.SonarFadeInSeconds);
			float num4 = Mathf.Max(0.1f, bdmSyncedSettings.SonarFadeOutSeconds);
			float num5 = Mathf.Max(0f, bdmSyncedSettings.SonarPingDelay);
			float num6 = Mathf.Max(1f, bdmSyncedSettings.SonarCooldownSeconds);
			_useDurationSeconds = Mathf.Max(0.5f, (float)num * (num3 + num2 + num4 + num5));
			_useStartedAt = Time.unscaledTime;
			_cooldownStartedAt = Time.unscaledTime;
			_routine = ((MonoBehaviour)instance).StartCoroutine(RunSonar(num, num2, num3, num4, num5));
			instance.LogAlways($"[BlindDeafMute] Sonar activated — {num} ping(s), ~{_useDurationSeconds:0.#}s use, cooldown {num6:0}s.");
		}

		internal static void Cancel()
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if (_routine != null && (Object)(object)instance != (Object)null)
			{
				((MonoBehaviour)instance).StopCoroutine(_routine);
				_routine = null;
			}
			_controllingBlackout = false;
			StopCurseFx();
			instance?.RestoreBlackoutAfterSonar();
		}

		private static float GetLiveCooldownSeconds()
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return 300f;
			}
			return Mathf.Max(1f, instance.GetEffectiveSettings().SonarCooldownSeconds);
		}

		private static IEnumerator RunSonar(int pings, float visionSeconds, float fadeInSeconds, float fadeOutSeconds, float pingDelaySeconds)
		{
			BlindDeafMuteChallengePlugin plugin = BlindDeafMuteChallengePlugin.Instance;
			_controllingBlackout = true;
			plugin?.EnsureBlackoutForSonar();
			StartCurseFx();
			for (int i = 0; i < pings; i++)
			{
				if ((Object)(object)plugin == (Object)null)
				{
					break;
				}
				if (!plugin.IsBlindEffectWanted())
				{
					break;
				}
				yield return FadeBlackout(1f, 0f, fadeInSeconds);
				yield return (object)new WaitForSecondsRealtime(visionSeconds);
				yield return FadeBlackout(0f, 1f, fadeOutSeconds);
				if (pingDelaySeconds > 0f)
				{
					yield return (object)new WaitForSecondsRealtime(pingDelaySeconds);
				}
			}
			StopCurseFx();
			_controllingBlackout = false;
			_routine = null;
			plugin?.RestoreBlackoutAfterSonar();
			plugin?.LogAlways("[BlindDeafMute] Sonar finished.");
		}

		private static IEnumerator FadeBlackout(float from, float to, float duration)
		{
			BlindDeafMuteChallengePlugin plugin = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)plugin == (Object)null)
			{
				yield break;
			}
			if (duration <= 0.001f)
			{
				plugin.SetBlackoutAlpha(to);
				yield break;
			}
			float start = Time.unscaledTime;
			while (true)
			{
				float t = Mathf.Clamp01((Time.unscaledTime - start) / duration);
				plugin.SetBlackoutAlpha(Mathf.Lerp(from, to, t));
				if (t >= 1f)
				{
					break;
				}
				yield return null;
			}
			plugin.SetBlackoutAlpha(to);
		}

		private static void StartCurseFx()
		{
			try
			{
				ScreenVFX val = (((Object)(object)GUIManager.instance != (Object)null) ? GUIManager.instance.curseSVFX : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val.renderer == (Object)null)
				{
					BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Sonar: curseSVFX not found.");
					return;
				}
				((Component)val).gameObject.SetActive(true);
				float num = 1f;
				if ((Object)(object)GUIManager.instance != (Object)null && GUIManager.instance.photosensitivity)
				{
					num *= 0.5f;
				}
				val.renderer.material.SetFloat(ScreenVFX.INTENSITY, num);
			}
			catch (Exception ex)
			{
				BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Sonar curse FX start failed: " + ex.Message);
			}
		}

		private static void StopCurseFx()
		{
			try
			{
				ScreenVFX val = (((Object)(object)GUIManager.instance != (Object)null) ? GUIManager.instance.curseSVFX : null);
				if (!((Object)(object)val == (Object)null))
				{
					val.EndFX();
				}
			}
			catch (Exception ex)
			{
				BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Sonar EndFX failed: " + ex.Message);
			}
		}
	}
	internal static class BdmDeafBonusLoot
	{
		private const string MagicConfetti = "BDM_DEAF_CONFETTI_V1";

		private const float SpawnDelaySeconds = 0.15f;

		private const int MaxRerollsPerItem = 24;

		private static bool _hookedEvents;

		private static bool _hookedPhoton;

		private static ParticleSystem _confettiTemplate;

		private static GameObject _confettiTemplateRoot;

		private static SFX_PlayOneShot _successTemplate;

		internal static void Initialize()
		{
			if (!_hookedEvents)
			{
				GlobalEvents.OnLuggageOpened = (Action<Luggage, Character>)Delegate.Combine(GlobalEvents.OnLuggageOpened, new Action<Luggage, Character>(OnLuggageOpened));
				_hookedEvents = true;
				BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Deaf bonus-loot hook ready.");
			}
		}

		internal static void Shutdown()
		{
			if (_hookedEvents)
			{
				GlobalEvents.OnLuggageOpened = (Action<Luggage, Character>)Delegate.Remove(GlobalEvents.OnLuggageOpened, new Action<Luggage, Character>(OnLuggageOpened));
				_hookedEvents = false;
			}
			if (_hookedPhoton && PhotonNetwork.NetworkingClient != null)
			{
				PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent;
				_hookedPhoton = false;
			}
			if ((Object)(object)_confettiTemplateRoot != (Object)null)
			{
				Object.Destroy((Object)(object)_confettiTemplateRoot);
				_confettiTemplateRoot = null;
			}
			_confettiTemplate = null;
			_successTemplate = null;
		}

		internal static void TryWarmConfettiCache()
		{
			CacheConfettiTemplate(forceLog: false);
		}

		internal static void EnsurePhotonHooked()
		{
			if (!_hookedPhoton && PhotonNetwork.NetworkingClient != null)
			{
				PhotonNetwork.NetworkingClient.EventReceived += OnPhotonEvent;
				_hookedPhoton = true;
			}
		}

		private static void OnLuggageOpened(Luggage luggage, Character interactor)
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)luggage == (Object)null || (Object)(object)interactor == (Object)null || !BdmModAuthorizationService.CanUseSyncedChallenge() || !instance.GetEffectiveSettings().EnableDeafBonusLoot || !PhotonNetwork.IsMasterClient || luggage is RespawnChest)
			{
				return;
			}
			int actorNumber = BlindDeafMuteChallengePlugin.GetActorNumber(interactor);
			if (instance.GetAssignedRole(actorNumber) != BlindDeafMuteChallengePlugin.AfflictionType.Deaf)
			{
				return;
			}
			BdmSyncedSettings effectiveSettings = instance.GetEffectiveSettings();
			float num = NormalizeBonusLootChance(effectiveSettings.DeafBonusLootChance);
			if (!(num <= 0f) && !(Random.value > num))
			{
				int count = Mathf.Clamp(effectiveSettings.DeafBonusLootCount, 1, 8);
				ushort[] array = ParseItemIds(effectiveSettings.DeafBonusLootItemIds);
				if (array.Length == 0)
				{
					instance.LogAlways("[BlindDeafMute] Deaf bonus loot skipped — empty/invalid ItemID list.");
				}
				else
				{
					((MonoBehaviour)instance).StartCoroutine(SpawnBonusRoutine(luggage, array, count));
				}
			}
		}

		private static IEnumerator SpawnBonusRoutine(Luggage luggage, ushort[] pool, int count)
		{
			yield return (object)new WaitForSeconds(0.15f);
			if ((Object)(object)luggage == (Object)null || !PhotonNetwork.IsMasterClient)
			{
				yield break;
			}
			BlindDeafMuteChallengePlugin plugin = BlindDeafMuteChallengePlugin.Instance;
			Vector3 basePos = luggage.Center();
			Quaternion baseRot = ((Component)luggage).transform.rotation;
			int spawned = 0;
			for (int i = 0; i < count; i++)
			{
				if (!TryPickValidPrefab(pool, out var prefab, out var pickedId))
				{
					plugin?.LogAlways("[BlindDeafMute] Deaf bonus loot: no valid ItemID left in host list.");
					break;
				}
				Vector3 pos = basePos + baseRot * new Vector3(Random.Range(-0.15f, 0.15f), 0.1f + 0.05f * (float)i, Random.Range(-0.15f, 0.15f));
				GameObject go;
				try
				{
					go = PhotonNetwork.InstantiateItemRoom(((Object)((Component)prefab).gameObject).name, pos, baseRot);
				}
				catch (Exception ex)
				{
					plugin?.LogAlways($"[BlindDeafMute] Deaf bonus spawn failed id={pickedId}: {ex.Message}");
					continue;
				}
				if ((Object)(object)go == (Object)null)
				{
					continue;
				}
				Item item = go.GetComponent<Item>();
				if (!((Object)(object)item == (Object)null))
				{
					try
					{
						((Spawner)luggage).OffsetSpawn(item);
						((Spawner)luggage).InitializePhysics(item);
					}
					catch (Exception ex2)
					{
						Exception ex3 = ex2;
						plugin?.LogDebug("[BlindDeafMute] Deaf bonus Offset/Physics: " + ex3.Message);
					}
					spawned++;
					plugin?.LogAlways($"[BlindDeafMute] Deaf bonus loot spawned id={pickedId} ({((Object)((Component)prefab).gameObject).name}).");
					prefab = null;
				}
			}
			if (spawned > 0)
			{
				Vector3 fxPos = luggage.Center() + Vector3.up * 0.4f;
				plugin?.LogAlways($"[BlindDeafMute] Deaf bonus confetti: requesting FX at {fxPos} (spawned={spawned}).");
				PlayConfettiAt(fxPos);
				BroadcastConfetti(fxPos);
			}
		}

		private static bool TryPickValidPrefab(ushort[] pool, out Item prefab, out ushort pickedId)
		{
			prefab = null;
			pickedId = 0;
			if (pool == null || pool.Length == 0)
			{
				return false;
			}
			int num = Mathf.Min(24, Mathf.Max(8, pool.Length * 3));
			Item val = default(Item);
			for (int i = 0; i < num; i++)
			{
				ushort num2 = pool[Random.Range(0, pool.Length)];
				if (ItemDatabase.TryGetItem(num2, ref val) && !((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					prefab = val;
					pickedId = num2;
					return true;
				}
			}
			return false;
		}

		internal static float NormalizeBonusLootChance(float raw)
		{
			if (float.IsNaN(raw) || float.IsInfinity(raw))
			{
				return 0f;
			}
			if (raw > 1f)
			{
				raw *= 0.01f;
			}
			if (raw < 0f)
			{
				return 0f;
			}
			if (raw > 1f)
			{
				return 1f;
			}
			return raw;
		}

		internal static ushort[] ParseItemIds(string raw)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return Array.Empty<ushort>();
			}
			string[] array = raw.Split(new char[4] { ',', ';', ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
			List<ushort> list = new List<ushort>(array.Length);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0 && ushort.TryParse(text, out var result))
				{
					list.Add(result);
				}
			}
			return list.ToArray();
		}

		internal static string SanitizeItemIdsForSync(string raw)
		{
			ushort[] array = ParseItemIds(raw);
			if (array.Length == 0)
			{
				return string.Empty;
			}
			return string.Join(",", Array.ConvertAll(array, (ushort id) => id.ToString()));
		}

		private static void BroadcastConfetti(Vector3 pos)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_005b: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			EnsurePhotonHooked();
			if (PhotonNetwork.InRoom)
			{
				object[] array = new object[4] { "BDM_DEAF_CONFETTI_V1", pos.x, pos.y, pos.z };
				RaiseEventOptions val = new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				};
				PhotonNetwork.RaiseEvent(BdmEmojiNet.EventCode, (object)array, val, SendOptions.SendReliable);
			}
		}

		private static void OnPhotonEvent(EventData photonEvent)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent == null || photonEvent.Code != BdmEmojiNet.EventCode || !(photonEvent.CustomData is object[] array) || array.Length < 4 || !(array[0] is string a) || !string.Equals(a, "BDM_DEAF_CONFETTI_V1", StringComparison.Ordinal))
			{
				return;
			}
			try
			{
				float num = Convert.ToSingle(array[1]);
				float num2 = Convert.ToSingle(array[2]);
				float num3 = Convert.ToSingle(array[3]);
				PlayConfettiAt(new Vector3(num, num2, num3));
			}
			catch
			{
			}
		}

		internal static void PlayConfettiAt(Vector3 worldPos)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			CacheConfettiTemplate(forceLog: true);
			bool flag = (Object)(object)_confettiTemplate != (Object)null && (Object)(object)_confettiTemplateRoot != (Object)null;
			instance?.LogDebug($"[BlindDeafMute] Confetti PlayConfettiAt pos={worldPos} " + string.Format("templateOk={0} root={1} ", flag, ((Object)(object)_confettiTemplateRoot != (Object)null) ? ((Object)_confettiTemplateRoot).name : "null") + "ps=" + (((Object)(object)_confettiTemplate != (Object)null) ? ((Object)_confettiTemplate).name : "null"));
			if (!flag)
			{
				instance?.LogAlways("[BlindDeafMute] Deaf bonus confetti SKIPPED — no cached ParticleSystem. Visit Airport (or any scene with a BasketballHoop) once so it can be cached, then try again.");
			}
			else if ((Object)(object)instance != (Object)null)
			{
				((MonoBehaviour)instance).StartCoroutine(PlayConfettiRoutine(worldPos));
			}
			else
			{
				PlayConfettiImmediate(worldPos);
			}
		}

		private static IEnumerator PlayConfettiRoutine(Vector3 worldPos)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			BlindDeafMuteChallengePlugin plugin = BlindDeafMuteChallengePlugin.Instance;
			GameObject clone;
			try
			{
				bool templateWasActive = _confettiTemplateRoot.activeSelf;
				_confettiTemplateRoot.SetActive(false);
				clone = Object.Instantiate<GameObject>(_confettiTemplateRoot);
				_confettiTemplateRoot.SetActive(templateWasActive);
				((Object)clone).name = "BDM_DeafBonusConfetti";
				clone.transform.SetParent((Transform)null, true);
				clone.transform.position = worldPos;
				clone.transform.rotation = Quaternion.identity;
				clone.transform.localScale = Vector3.one;
				clone.SetActive(false);
				plugin?.LogDebug($"[BlindDeafMute] Confetti clone created id={((Object)clone).GetInstanceID()} " + $"active={clone.activeSelf} pos={clone.transform.position} " + $"psCount={clone.GetComponentsInChildren<ParticleSystem>(true).Length}");
			}
			catch (Exception ex)
			{
				Exception ex2 = ex;
				plugin?.LogAlways("[BlindDeafMute] Deaf bonus confetti clone failed: " + ex2.Message);
				yield break;
			}
			yield return null;
			try
			{
				if ((Object)(object)clone == (Object)null)
				{
					plugin?.LogAlways("[BlindDeafMute] Confetti clone was destroyed before play.");
					yield break;
				}
				clone.SetActive(true);
				ParticleSystem[] systems = clone.GetComponentsInChildren<ParticleSystem>(true);
				plugin?.LogDebug($"[BlindDeafMute] Confetti activated clone at {clone.transform.position}, systems={systems.Length}");
				for (int i = 0; i < systems.Length; i++)
				{
					ParticleSystem ps = systems[i];
					MainModule main = ps.main;
					plugin?.LogDebug($"[BlindDeafMute] Confetti PS[{i}] name={((Object)((Component)ps).gameObject).name} " + $"playOnAwake={((MainModule)(ref main)).playOnAwake} isPlaying={ps.isPlaying} " + $"renderer={(Object)(object)((Component)ps).GetComponent<ParticleSystemRenderer>() != (Object)null}");
					ps.Clear(true);
					ps.Play(true);
					plugin?.LogDebug($"[BlindDeafMute] Confetti PS[{i}] after Play isPlaying={ps.isPlaying}");
					main = default(MainModule);
				}
				if ((Object)(object)_successTemplate != (Object)null)
				{
					_successTemplate.Play();
					plugin?.LogDebug("[BlindDeafMute] Confetti success SFX Play() called.");
				}
				else
				{
					plugin?.LogDebug("[BlindDeafMute] Confetti success SFX template is null.");
				}
				plugin?.LogAlways($"[BlindDeafMute] Deaf bonus confetti PLAYED at {worldPos} (systems={systems.Length}).");
			}
			catch (Exception ex)
			{
				Exception ex3 = ex;
				plugin?.LogAlways("[BlindDeafMute] Deaf bonus confetti play failed: " + ex3.Message);
			}
			if ((Object)(object)clone != (Object)null)
			{
				Object.Destroy((Object)(object)clone, 6f);
			}
		}

		private static void PlayConfettiImmediate(Vector3 worldPos)
		{
			//IL_001e: 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)
			try
			{
				bool activeSelf = _confettiTemplateRoot.activeSelf;
				_confettiTemplateRoot.SetActive(false);
				GameObject val = Object.Instantiate<GameObject>(_confettiTemplateRoot, worldPos, Quaternion.identity);
				_confettiTemplateRoot.SetActive(activeSelf);
				val.SetActive(true);
				ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].Clear(true);
					componentsInChildren[i].Play(true);
				}
				Object.Destroy((Object)(object)val, 6f);
				if ((Object)(object)_successTemplate != (Object)null)
				{
					_successTemplate.Play();
				}
			}
			catch (Exception ex)
			{
				BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Deaf bonus confetti failed: " + ex.Message);
			}
		}

		private static void CacheConfettiTemplate(bool forceLog)
		{
			if ((Object)(object)_confettiTemplate != (Object)null && (Object)(object)_confettiTemplateRoot != (Object)null)
			{
				if (forceLog)
				{
					BlindDeafMuteChallengePlugin.Instance?.LogDebug("[BlindDeafMute] Confetti cache HIT root=" + ((Object)_confettiTemplateRoot).name);
				}
				return;
			}
			_confettiTemplate = null;
			_confettiTemplateRoot = null;
			BasketballHoop[] array = Object.FindObjectsByType<BasketballHoop>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			int num = ((array != null) ? array.Length : 0);
			BlindDeafMuteChallengePlugin.Instance?.LogDebug($"[BlindDeafMute] Confetti cache MISS — scanning BasketballHoop count={num}");
			if (array == null || array.Length == 0)
			{
				if (forceLog)
				{
					BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Confetti: 0 BasketballHoop in this scene — cannot cache yet.");
				}
				return;
			}
			for (int i = 0; i < array.Length; i++)
			{
				BasketballHoop val = array[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				ParticleSystem val2 = val.confetti;
				string text = "hoop.confetti field";
				if ((Object)(object)val2 == (Object)null)
				{
					Transform val3 = FindChildNamed(((Component)val).transform, "Confetti");
					if ((Object)(object)val3 != (Object)null)
					{
						val2 = ((Component)val3).GetComponent<ParticleSystem>() ?? ((Component)val3).GetComponentInChildren<ParticleSystem>(true);
						text = "child '" + ((Object)val3).name + "'";
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)val).GetComponentInChildren<ParticleSystem>(true);
					text = "GetComponentInChildren<ParticleSystem>";
				}
				BlindDeafMuteChallengePlugin.Instance?.LogDebug($"[BlindDeafMute] Confetti hoop[{i}]='{((Object)val).name}' source={text} " + "ps=" + (((Object)(object)val2 != (Object)null) ? ((Object)((Component)val2).gameObject).name : "null") + " " + $"fieldNull={(Object)(object)val.confetti == (Object)null}");
				if (!((Object)(object)val2 == (Object)null))
				{
					try
					{
						bool activeSelf = ((Component)val2).gameObject.activeSelf;
						((Component)val2).gameObject.SetActive(false);
						GameObject val4 = Object.Instantiate<GameObject>(((Component)val2).gameObject);
						((Component)val2).gameObject.SetActive(activeSelf);
						((Object)val4).name = "BDM_ConfettiTemplate";
						val4.SetActive(false);
						Object.DontDestroyOnLoad((Object)(object)val4);
						_confettiTemplateRoot = val4;
						_confettiTemplate = val4.GetComponent<ParticleSystem>() ?? val4.GetComponentInChildren<ParticleSystem>(true);
						_successTemplate = val.success;
						BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Confetti template CACHED from '" + ((Object)val).name + "' via " + text + " → persistPs=" + (((Object)(object)_confettiTemplate != (Object)null) ? ((Object)_confettiTemplate).name : "null") + ".");
						return;
					}
					catch (Exception ex)
					{
						BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Confetti template cache failed: " + ex.Message);
					}
				}
			}
			if (forceLog)
			{
				BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Confetti: found BasketballHoop(s) but no ParticleSystem to cache.");
			}
		}

		private static Transform FindChildNamed(Transform root, string name)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			if (string.Equals(((Object)root).name, name, StringComparison.OrdinalIgnoreCase))
			{
				return root;
			}
			for (int i = 0; i < root.childCount; i++)
			{
				Transform val = FindChildNamed(root.GetChild(i), name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}
	}
	internal static class BdmDeafDetection
	{
		private struct OutlineEdge
		{
			public LineRenderer Line;

			public Vector3 Anchor;
		}

		private const float WidthReferenceDistance = 8f;

		private const float WidthScaleMin = 0.45f;

		private const float WidthScaleMax = 18f;

		private static Coroutine _routine;

		private static float _cooldownStartedAt = -1f;

		private static float _useStartedAt = -1f;

		private static float _useDurationSeconds = 1f;

		private static GameObject _outlineRoot;

		private static Material _lineMaterial;

		private static readonly List<OutlineEdge> _edges = new List<OutlineEdge>(256);

		internal static bool IsActive => _routine != null;

		internal static bool IsOnCooldown => CooldownRemainingSeconds > 0f;

		internal static float CooldownRemainingSeconds
		{
			get
			{
				if (_cooldownStartedAt < 0f)
				{
					return 0f;
				}
				float liveCooldownSeconds = GetLiveCooldownSeconds();
				return Mathf.Max(0f, _cooldownStartedAt + liveCooldownSeconds - Time.unscaledTime);
			}
		}

		internal static bool IsReady => !IsActive && !IsOnCooldown;

		internal static float CooldownDurationSeconds => GetLiveCooldownSeconds();

		internal static float ActiveRemainingSeconds => (!IsActive) ? 0f : Mathf.Max(0f, _useStartedAt + _useDurationSeconds - Time.unscaledTime);

		internal static float HudCooldownFill
		{
			get
			{
				if (!IsOnCooldown && !IsActive)
				{
					return 1f;
				}
				float cooldownDurationSeconds = CooldownDurationSeconds;
				if (cooldownDurationSeconds <= 0.01f || _cooldownStartedAt < 0f)
				{
					return 1f;
				}
				return Mathf.Clamp01(1f - CooldownRemainingSeconds / cooldownDurationSeconds);
			}
		}

		internal static float HudUseFill
		{
			get
			{
				if (!IsActive || _useDurationSeconds <= 0.01f)
				{
					return 0f;
				}
				return Mathf.Clamp01(ActiveRemainingSeconds / _useDurationSeconds);
			}
		}

		internal static void TryActivate()
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (!instance.IsLocalDeafActive)
			{
				instance.LogAlways("[BlindDeafMute] Detection is for Deaf players only.");
				return;
			}
			BdmSyncedSettings effectiveSettings = instance.GetEffectiveSettings();
			if (!effectiveSettings.EnableDetection)
			{
				instance.LogAlways("[BlindDeafMute] Detection power is disabled by host.");
				return;
			}
			if (IsActive)
			{
				instance.LogAlways("[BlindDeafMute] Detection already active.");
				return;
			}
			if (IsOnCooldown)
			{
				instance.LogAlways($"[BlindDeafMute] Detection on cooldown ({CooldownRemainingSeconds:0}s left).");
				return;
			}
			float num = Mathf.Clamp(effectiveSettings.DetectionDurationSeconds, 0.5f, 120f);
			float num2 = Mathf.Clamp(effectiveSettings.DetectionCooldownSeconds, 1f, 3600f);
			_useDurationSeconds = num;
			_useStartedAt = Time.unscaledTime;
			_cooldownStartedAt = Time.unscaledTime;
			_routine = ((MonoBehaviour)instance).StartCoroutine(RunDetection(num));
			instance.LogAlways($"[BlindDeafMute] Detection activated — {num:0.#}s use, cooldown {num2:0}s.");
		}

		internal static void Cancel()
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if (_routine != null && (Object)(object)instance != (Object)null)
			{
				((MonoBehaviour)instance).StopCoroutine(_routine);
				_routine = null;
			}
			ClearLineRenderers();
		}

		internal static void Shutdown()
		{
			Cancel();
			_cooldownStartedAt = -1f;
			if ((Object)(object)_outlineRoot != (Object)null)
			{
				Object.Destroy((Object)(object)_outlineRoot);
				_outlineRoot = null;
			}
			if ((Object)(object)_lineMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_lineMaterial);
				_lineMaterial = null;
			}
		}

		private static float GetLiveCooldownSeconds()
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return 120f;
			}
			return Mathf.Clamp(instance.GetEffectiveSettings().DetectionCooldownSeconds, 1f, 3600f);
		}

		private static IEnumerator RunDetection(float duration)
		{
			BuildOutlines();
			float end = Time.unscaledTime + duration;
			while (Time.unscaledTime < end)
			{
				if (Time.frameCount % 30 == 0)
				{
					BuildOutlines();
				}
				else
				{
					UpdateOutlineWidths();
				}
				yield return null;
			}
			ClearLineRenderers();
			_routine = null;
			BlindDeafMuteChallengePlugin.Instance?.LogAlways("[BlindDeafMute] Detection finished.");
		}

		private static void BuildOutlines()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			EnsureRoot();
			ClearLineRenderers();
			Color color = (Color)(((Object)(object)BlindDeafMuteChallengePlugin.Instance != (Object)null) ? BlindDeafMuteChallengePlugin.Instance.DetectionOutlineColor : new Color(1f, 0f, 0.988f, 1f));
			Camera camera = GetCamera();
			Vector3 val = (((Object)(object)camera != (Object)null) ? ((Component)camera).transform.position : Vector3.zero);
			try
			{
				if (Luggage.ALL_LUGGAGE == null)
				{
					return;
				}
				for (int i = 0; i < Luggage.ALL_LUGGAGE.Count; i++)
				{
					Luggage val2 = Luggage.ALL_LUGGAGE[i];
					if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeInHierarchy && !(val2 is RespawnChest))
					{
						Bounds luggageBounds = GetLuggageBounds(val2);
						float num = (((Object)(object)camera != (Object)null) ? Vector3.Distance(val, ((Bounds)(ref luggageBounds)).center) : 8f);
						float num2 = Mathf.Clamp((num - 12f) * 0.025f, 0f, 4f);
						((Bounds)(ref luggageBounds)).Expand(0.15f + num2);
						AddBoxOutline(luggageBounds, color, ((Bounds)(ref luggageBounds)).center);
					}
				}
			}
			catch
			{
			}
			UpdateOutlineWidths();
		}

		private static Bounds GetLuggageBounds(Luggage luggage)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] meshRenderers = luggage.meshRenderers;
			bool flag = false;
			Bounds result = default(Bounds);
			((Bounds)(ref result))..ctor(((Component)luggage).transform.position, Vector3.one * 0.8f);
			if (meshRenderers != null)
			{
				foreach (Renderer obj in meshRenderers)
				{
					MeshRenderer val = (MeshRenderer)(object)((obj is MeshRenderer) ? obj : null);
					if (!((Object)(object)val == (Object)null) && ((Renderer)val).enabled)
					{
						if (!flag)
						{
							result = ((Renderer)val).bounds;
							flag = true;
						}
						else
						{
							((Bounds)(ref result)).Encapsulate(((Renderer)val).bounds);
						}
					}
				}
			}
			if (!flag)
			{
				try
				{
					Vector3 val2 = luggage.Center();
					result = new Bounds(val2, Vector3.one * 1.2f);
				}
				catch
				{
					((Bounds)(ref result))..ctor(((Component)luggage).transform.position, Vector3.one * 1.2f);
				}
			}
			return result;
		}

		private static void AddBoxOutline(Bounds bounds, Color color, Vector3 anchor)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_01df: 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_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3 extents = ((Bounds)(ref bounds)).extents;
			Vector3[] array = (Vector3[])(object)new Vector3[8]
			{
				center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z),
				center + new Vector3(0f - extents.x, 0f - extents.y, extents.z),
				center + new Vector3(0f - extents.x, extents.y, 0f - extents.z),
				center + new Vector3(0f - extents.x, extents.y, extents.z),
				center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z),
				center + new Vector3(extents.x, 0f - extents.y, extents.z),
				center + new Vector3(extents.x, extents.y, 0f - extents.z),
				center + new Vector3(extents.x, extents.y, extents.z)
			};
			int[,] array2 = new int[12, 2]
			{
				{ 0, 1 },
				{ 0, 2 },
				{ 0, 4 },
				{ 7, 3 },
				{ 7, 5 },
				{ 7, 6 },
				{ 1, 3 },
				{ 1, 5 },
				{ 2, 3 },
				{ 2, 6 },
				{ 4, 5 },
				{ 4, 6 }
			};
			float num = ComputeWidth(Vector3.Distance(GetCameraPos(), anchor));
			for (int i = 0; i < array2.GetLength(0); i++)
			{
				GameObject val = new GameObject("Edge");
				val.transform.SetParent(_outlineRoot.transform, false);
				LineRenderer val2 = val.AddComponent<LineRenderer>();
				((Renderer)val2).sharedMaterial = GetLineMaterial();
				val2.positionCount = 2;
				val2.useWorldSpace = true;
				val2.widthMultiplier = num;
				val2.startWidth = num;
				val2.endWidth = num;
				val2.startColor = color;
				val2.endColor = color;
				((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val2).receiveShadows = false;
				((Renderer)val2).allowOcclusionWhenDynamic = false;
				val2.SetPosition(0, array[array2[i, 0]]);
				val2.SetPosition(1, array[array2[i, 1]]);
				_edges.Add(new OutlineEdge
				{
					Line = val2,
					Anchor = anchor
				});
			}
		}

		private static void UpdateOutlineWidths()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (_edges.Count == 0)
			{
				return;
			}
			Vector3 cameraPos = GetCameraPos();
			for (int i = 0; i < _edges.Count; i++)
			{
				OutlineEdge outlineEdge = _edges[i];
				if (!((Object)(object)outlineEdge.Line == (Object)null))
				{
					float distance = Vector3.Distance(cameraPos, outlineEdge.Anchor);
					float num = ComputeWidth(distance);
					outlineEdge.Line.widthMultiplier = num;
					outlineEdge.Line.startWidth = num;
					outlineEdge.Line.endWidth = num;
				}
			}
		}

		private static float ComputeWidth(float distance)
		{
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			float num = (((Object)(object)instance != (Object)null) ? instance.DetectionOutlineThickness : 0.06f);
			float num2 = Mathf.Clamp(Mathf.Max(distance, 0.5f) / 8f, 0.45f, 18f);
			return Mathf.Max(0.002f, num * num2);
		}

		private static Camera GetCamera()
		{
			try
			{
				if ((Object)(object)MainCamera.instance != (Object)null && (Object)(object)MainCamera.instance.cam != (Object)null)
				{
					return MainCamera.instance.cam;
				}
			}
			catch
			{
			}
			return Camera.main;
		}

		private static Vector3 GetCameraPos()
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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)
			//IL_0053: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			Camera camera = GetCamera();
			if ((Object)(object)camera != (Object)null)
			{
				return ((Component)camera).transform.position;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter != (Object)null)
			{
				try
				{
					return localCharacter.Head;
				}
				catch
				{
					return ((Component)localCharacter).transform.position;
				}
			}
			return Vector3.zero;
		}

		private static void EnsureRoot()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if (!((Object)(object)_outlineRoot != (Object)null))
			{
				_outlineRoot = new GameObject("BDM_DetectionOutlines");
				Object.DontDestroyOnLoad((Object)(object)_outlineRoot);
			}
		}

		private static void ClearLineRenderers()
		{
			_edges.Clear();
			if (!((Object)(object)_outlineRoot == (Object)null))
			{
				for (int num = _outlineRoot.transform.childCount - 1; num >= 0; num--)
				{
					Object.Destroy((Object)(object)((Component)_outlineRoot.transform.GetChild(num)).gameObject);
				}
			}
		}

		private static Material GetLineMaterial()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_lineMaterial != (Object)null)
			{
				return _lineMaterial;
			}
			Shader val = Shader.Find("Hidden/Internal-Colored");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Sprites/Default");
			}
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Unlit/Color");
			}
			_lineMaterial = new Material(val);
			((Object)_lineMaterial).hideFlags = (HideFlags)61;
			_lineMaterial.SetInt("_ZTest", 8);
			_lineMaterial.SetInt("_ZWrite", 0);
			if (_lineMaterial.HasProperty("_Color"))
			{
				_lineMaterial.SetColor("_Color", Color.white);
			}
			return _lineMaterial;
		}
	}
	internal static class BdmEmojiBubbles
	{
		private sealed class Bubble
		{
			internal GameObject Go;

			internal RectTransform Rect;

			internal RawImage Image;

			internal Character Follow;

			internal int CharacterId;

			internal float BornAt;

			internal float DieAt;

			internal float Size;

			internal Coroutine Routine;
		}

		private sealed class ReactingCue
		{
			internal GameObject Go;

			internal RectTransform Rect;

			internal Character Follow;

			internal int CharacterId;

			internal Coroutine Routine;
		}

		private const float HeadWorldOffsetY = 0.35f;

		private const float ScreenYBoost = 36f;

		private const float StringGap = 4f;

		private const float PopInSeconds = 0.12f;

		private const float FadeOutSeconds = 0.22f;

		private static readonly Dictionary<int, List<Bubble>> _byCharacter = new Dictionary<int, List<Bubble>>(8);

		private static readonly Dictionary<int, ReactingCue> _reacting = new Dictionary<int, ReactingCue>(4);

		private static readonly HashSet<int> _reactingWanted = new HashSet<int>();

		private static readonly Dictionary<int, Character> _reactingFollow = new Dictionary<int, Character>(4);

		private static readonly Dictionary<int, string> _reactingSenderCue = new Dictionary<int, string>(4);

		internal static bool Show(Character character, string codeKey, float durationSeconds)
		{
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Expected O, but got Unknown
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null || string.IsNullOrEmpty(codeKey))
			{
				return false;
			}
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			if ((Object)(object)instance != (Object)null && instance.IsBlindEffectWanted())
			{
				instance.LogDebug("[BlindDeafMute] Emoji bubble skipped — local player is Blind.");
				return false;
			}
			if ((Object)(object)instance != (Object)null && instance.BlockAlphabetEmojis && BdmEmojiCatalog.IsAlphabetCodeKey(codeKey))
			{
				instance.LogDebug("[BlindDeafMute] Alphabet emoji blocked: " + codeKey);
				return false;
			}
			if ((Object)(object)instance != (Object)null && !instance.ShowSkinToneVariants && BdmEmojiCatalog.IsSkinToneVariant(codeKey))
			{
				instance.LogDebug("[BlindDeafMute] Skin-tone emoji blocked: " + codeKey);
				return false;
			}
			GUIManager instance2 = GUIManager.instance;
			if ((Object)(object)instance2 == (Object)null || (Object)(object)instance2.hudCanvas == (Object)null)
			{
				instance?.LogAlways("[BlindDeafMute] Emoji bubble skipped — no HUD canvas.");
				return false;
			}
			BdmEmojiCatalog.EnsureLoaded();
			BdmEmojiCatalog.Entry entry = BdmEmojiCatalog.FindByCodeKey(codeKey);
			Texture2D texture = BdmEmojiCatalog.GetTexture(entry);
			if ((Object)(object)texture == (Object)null)
			{
				instance?.LogAlways("[BlindDeafMute] Emoji bubble missing texture for '" + codeKey + "' (is emojis/ installed?).");
				return false;
			}
			int instanceID = ((Object)character).GetInstanceID();
			float localBubbleSize = GetLocalBubbleSize(instance);
			float num = Mathf.Max(0.5f, durationSeconds);
			bool flag = (Object)(object)instance == (Object)null || instance.AllowEmojiString;
			int num2 = (((Object)(object)instance != (Object)null) ? Mathf.Clamp(instance.MaxEmojiStringLength, 1, 16) : 6);
			if (!_byCharacter.TryGetValue(instanceID, out var value))
			{
				value = new List<Bubble>(num2);
				_byCharacter[instanceID] = value;
			}
			if (!flag)
			{
				ClearGroup(value, restoreReacting: false);
			}
			else
			{
				while (value.Count >= num2)
				{
					DestroyBubble(value[0], value);
				}
			}
			GameObject val = new GameObject("BDM_EmojiBubble", new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(((Component)instance2.hudCanvas).transform, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.zero;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = new Vector2(localBubbleSize * 0.7f, localBubbleSize * 0.7f);
			RawImage val2 = val.AddComponent<RawImage>();
			val2.texture = (Texture)(object)texture;
			((Graphic)val2).raycastTarget = false;
			((Graphic)val2).color = new Color(1f, 1f, 1f, 0f);
			val.transform.SetAsLastSibling();
			float unscaledTime = Time.unscaledTime;
			Bubble bubble = new Bubble
			{
				Go = val,
				Rect = component,
				Image = val2,
				Follow = character,
				CharacterId = instanceID,
				BornAt = unscaledTime,
				DieAt = unscaledTime + num,
				Size = localBubbleSize
			};
			value.Add(bubble);
			HideReactingCue(instanceID);
			for (int i = 0; i < value.Count; i++)
			{
				value[i].DieAt = bubble.DieAt;
			}
			PositionGroup(value, flag);
			MonoBehaviour val3 = (MonoBehaviour)(object)instance;
			if ((Object)(object)val3 != (Object)null)
			{
				bubble.Routine = val3.StartCoroutine(RunBubble(bubble));
			}
			else
			{
				Object.Destroy((Object)(object)val, num);
			}
			instance?.LogDebug("[BlindDeafMute] Emoji bubble shown '" + codeKey + "' on " + character.characterName + ".");
			return true;
		}

		internal static void ClearForCharacter(Character character)
		{
			if (!((Object)(object)character == (Object)null))
			{
				int instanceID = ((Object)character).GetInstanceID();
				if (!_byCharacter.TryGetValue(instanceID, out var value))
				{
					TryRestoreReacting(instanceID);
					return;
				}
				ClearGroup(value, restoreReacting: true);
				_byCharacter.Remove(instanceID);
			}
		}

		internal static void SetReacting(Character character, bool reacting, string senderCueKey = null)
		{
			if ((Object)(object)character == (Object)null)
			{
				return;
			}
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			int instanceID = ((Object)character).GetInstanceID();
			if ((Object)(object)instance != (Object)null && (instance.IsBlindEffectWanted() || !instance.ShowReactingCue))
			{
				ClearReactingWanted(instanceID);
				HideReactingCue(instanceID);
				return;
			}
			if (!reacting)
			{
				ClearReactingWanted(instanceID);
				HideReactingCue(instanceID);
				return;
			}
			string text = BlindDeafMuteChallengePlugin.NormalizeIncomingCueAsset((!string.IsNullOrEmpty(senderCueKey)) ? senderCueKey : (((Object)(object)instance != (Object)null) ? instance.IncomingEmojiCueKey : "1f4ac"));
			_reactingWanted.Add(instanceID);
			_reactingFollow[instanceID] = character;
			_reactingSenderCue[instanceID] = text;
			if (HasActiveBubbles(instanceID))
			{
				HideReactingCue(instanceID);
			}
			else
			{
				ShowReactingCue(character, text);
			}
		}

		private static void ClearReactingWanted(int characterId)
		{
			_reactingWanted.Remove(characterId);
			_reactingFollow.Remove(characterId);
			_reactingSenderCue.Remove(characterId);
		}

		private static bool HasActiveBubbles(int characterId)
		{
			List<Bubble> value;
			return _byCharacter.TryGetValue(characterId, out value) && value.Count > 0;
		}

		private static void ShowReactingCue(Character character, string senderCueKey)
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)character).GetInstanceID();
			if (_reacting.ContainsKey(instanceID))
			{
				return;
			}
			BlindDeafMuteChallengePlugin instance = BlindDeafMuteChallengePlugin.Instance;
			GUIManager instance2 = GUIManager.instance;
			if (!((Object)(object)instance2 == (Object)null) && !((Object)(object)instance2.hudCanvas == (Object)null))
			{
				BdmEmojiCatalog.EnsureLoaded();
				string text = (((Object)(object)instance != (Object)null) ? instance.ResolveIncomingCueDisplayKey(senderCueKey) : BlindDeafMuteChallengePlugin.NormalizeIncomingCueAsset(senderCueKey));
				Texture2D texture = BdmEmojiCatalog.GetTexture(BdmEmojiCatalog.FindByCodeKey(text));
				if ((Object)(object)texture == (Object)null && text != "1f4ac")
				{
					texture = BdmEmojiCatalog.GetTexture(BdmEmojiCatalog.FindByCodeKey("1f4ac"));
				}
				GameObject val = new GameObject("BDM_EmojiReacting", new Type[1] { typeof(RectTransform) });
				RectTransform component = val.GetComponent<RectTransform>();
				((Transform)component).SetParent(((Component)instance2.hudCanvas).transform, false);
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.zero;
				component.pivot = new Vector2(0.5f, 0.5f);
				float num = GetLocalBubbleSize(instance) * 0.5f;
				component.sizeDelta = new Vector2(num, num);
				RawImage val2 = val.AddComponent<RawImage>();
				((Graphic)val2).raycastTarget = false;
				if ((Object)(object)texture != (Object)null)
				{
					val2.texture = (Texture)(object)texture;
					((Graphic)val2).color = Color.white;
				}
				else
				{
					Texture2D val3 = new Texture2D(2, 2, (TextureFormat)4, false);
					val3.SetPixels((Color[])(object)new Color[4]
					{
						Color.white,
						Color.white,
						Color.white,
						Color.white
					});
					val3.Apply(false, true);
					val2.texture = (Texture)(object)val3;
					((Graphic)val2).color = new Color(0.95f, 0.95f, 0.95f, 0.9f);
					component.sizeDelta = new Vector2(num * 1.2f, num * 0.7f);
				}
				ReactingCue reactingCue = new ReactingCue
				{
					Go = val,
					Rect = component,
					Follow = character,
					CharacterId = instanceID
				};
				_reacting[instanceID] = reactingCue;
				if ((Object)(object)instance != (Object)null)
				{
					reactingCue.Routine = ((MonoBehaviour)instance).StartCoroutine(RunReacting(reactingCue));
				}
			}
		}

		private static void HideReactingCue(int characterId)
		{
			if (_reacting.TryGetValue(characterId, out var value))
			{
				_reacting.Remove(characterId);
				if (value.Routine != null && (Object)(object)BlindDeafMuteChallengePlugin.Instance != (Object)null)
				{
					((MonoBehaviour)BlindDeafMuteChallengePlugin.Instance).StopCoroutine(value.Routine);
				}
				if ((Object)(object)value.Go != (Object)null)
				{
					Object.Destroy((Object)(object)value.Go);
				}
			}
		}

		private static void TryRestoreReacting(int characterId)
		{
			if (_reactingWanted.Contains(characterId) && !HasActiveBubbles(characterId) && _reactingFollow.TryGetValue(characterId, out var value) && !((Object)(object)value == (Object)null))
			{
				string value2;
				string senderCueKey = (_reactingSenderCue.TryGetValue(characterId, out value2) ? value2 : "1f4ac");
				ShowReactingCue(value, senderCueKey);
			}
		}

		private static float GetLocalBubbleSize(BlindDeafMuteChallengePlugin plugin)
		{
			float num = (((Object)(object)plugin != (Object)null) ? Mathf.Clamp(plugin.EmojiBubbleSize, 24f, 256f) : 72f);
			return num * BdmEmojiCatalog.UiScale;
		}

		private static IEnumerator RunBubble(Bubble bubble)
		{
			while ((Object)(object)bubble.Go != (Object)null && Time.unscaledTime < bubble.DieAt)
			{
				float now = Time.unscaledTime;
				float age = now - bubble.BornAt;
				float left = bubble.DieAt - now;
				float popT = Mathf.Clamp01(age / 0.12f);
				float scale = Mathf.Lerp(0.7f, 1f, popT);
				float alpha = popT;
				if (left < 0.22f)
				{
					alpha *= Mathf.Clamp01(left / 0.22f);
				}
				if ((Object)(object)bubble.Rect != (Object)null)
				{
					bubble.Rect.sizeDelta = new Vector2(bubble.Size * scale, bubble.Size * scale);
				}
				if ((Object)(object)bubble.Image != (Object)null)
				{
					Color c = ((Graphic)bubble.Image).color;
					c.a = alpha;
					((Graphic)bubble.Image).color = c;
				}
				if (_byCharacter.TryGetValue(bubble.CharacterId, out var group))
				{
					PositionGroup(stringMode: (Object)(object)BlindDeafMuteChallengePlugin.Instance == (Object)null || BlindDeafMuteChallengePlugin.Instance.AllowEmojiString, group: group);
				}
				yield return null;
				group = null;
			}
			if (_byCharacter.TryGetValue(bubble.CharacterId, out var g))
			{
				int characterId = bubble.CharacterId;
				DestroyBubble(bubble, g);
				if (g.Count == 0)
				{
					_byCharacter.Remove(characterId);
					TryRestoreReacting(characterId);
				}
				else
				{
					PositionGroup(stringMode: (Object)(object)BlindDeafMuteChallengePlugin.Instance == (Object)null || BlindDeafMuteChallengePlugin.Instance.AllowEmojiString, group: g);
				}
			}
			else if ((Object)(object)bubble.Go != (Object)null)
			{
				Object.Destroy((Object)(object)bubble.Go);
				TryRestoreReacting(bubble.CharacterId);
			}
		}

		private static IEnumerator RunReacting(ReactingCue cue)
		{
			while ((Object)(object)cue.Go != (Object)null)
			{
				PositionReacting(cue);
				yield return null;
			}
		}

		private static void ClearGroup(List<Bubble> group, bool restoreReacting)
		{
			int num = ((group != null && group.Count > 0) ? group[0].CharacterId : 0);
			for (int num2 = group.Count - 1; num2 >= 0; num2--)
			{
				DestroyBubble(group[num2], group);
			}
			if (restoreReacting && num != 0)
			{
				TryRestoreReacting(num);
			}
		}

		private static void DestroyBubble(Bubble bubble, List<Bubble> group)
		{
			if (bubble != null)
			{
				if (bubble.Routine != null && (Object)(object)BlindDeafMuteChallengePlugin.Instance != (Object)null)
				{
					((MonoBehaviour)BlindDeafMuteChallengePlugin.Instance).StopCoroutine(bubble.Routine);
					bubble.Routine = null;
				}
				if ((Object)(object)bubble.Go != (Object)null)
				{
					Object.Destroy((Object)(object)bubble.Go);
				}
				group.Remove(bubble);
			}
		}

		private static bool TryGetHeadScreen(Character follow, out Vector3 screen)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			screen = default(Vector3);
			if ((Object)(object)follow == (Object)null)
			{
				return false;
			}
			if (!IsWithinViewDistance(follow))
			{
				return false;
			}
			Camera val = null;
			try
			{
				if ((Object)(object)MainCamera.instance != (Object)null && (Object)(object)MainCamera.instance.cam != (Object)null)
				{
					val = MainCamera.instance.cam;
				}
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				val = Camera.main;
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Vector3 val2;
			try
			{
				val2 = follow.Head;
			}
			catch
			{
				val2 = ((Component)follow).transform.position;
			}
			val2.y += 0.35f;
			screen = val.WorldToScreenPoint(val2);
			if (screen.z < 0.1f)
			{
				return false;
			}
			screen.y += 36f;
			return true;
		}

		private static bool IsWithinViewDistance(Character follow)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_