Decompiled source of Sensus v1.0.0

BepInEx/plugins/Auuueser-Sensus/Sensus.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using Microsoft.CodeAnalysis;
using Sensus.Audio;
using Sensus.Captions;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AnimationModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AudioModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.CoreModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UIModule")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Sensus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Sensus")]
[assembly: AssemblyTitle("Sensus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Sensus
{
	internal static class LanguagePolicy
	{
		internal const string ChinesePluginGuid = "Aueser.LCChineseProject";

		internal const string LegacyChinesePluginGuid = "cn.codex.v81testchn";

		internal static bool UseChinese(string preference, IEnumerable<string> loadedPluginGuids)
		{
			if (string.Equals(preference, "Chinese", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (string.Equals(preference, "English", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			foreach (string loadedPluginGuid in loadedPluginGuids)
			{
				if (string.Equals(loadedPluginGuid, "Aueser.LCChineseProject", StringComparison.OrdinalIgnoreCase) || string.Equals(loadedPluginGuid, "cn.codex.v81testchn", StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class LethalConfigIntegration
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static Action<bool> Register(SensusSettings settings, bool chinese)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			//IL_0180: Expected O, but got Unknown
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Expected O, but got Unknown
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Expected O, but got Unknown
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Expected O, but got Unknown
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Expected O, but got Unknown
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Expected O, but got Unknown
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Expected O, but got Unknown
			//IL_02ed: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Expected O, but got Unknown
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Expected O, but got Unknown
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Expected O, but got Unknown
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Expected O, but got Unknown
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Expected O, but got Unknown
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Expected O, but got Unknown
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Expected O, but got Unknown
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Expected O, but got Unknown
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Expected O, but got Unknown
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Expected O, but got Unknown
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Expected O, but got Unknown
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Expected O, but got Unknown
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Expected O, but got Unknown
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Expected O, but got Unknown
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Expected O, but got Unknown
			//IL_048e: Expected O, but got Unknown
			//IL_048e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0498: Expected O, but got Unknown
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Expected O, but got Unknown
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Expected O, but got Unknown
			//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0500: Expected O, but got Unknown
			//IL_0500: Unknown result type (might be due to invalid IL or missing references)
			//IL_050a: Expected O, but got Unknown
			//IL_0511: Unknown result type (might be due to invalid IL or missing references)
			//IL_0539: Expected O, but got Unknown
			//IL_0539: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Expected O, but got Unknown
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Expected O, but got Unknown
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_057c: Expected O, but got Unknown
			LethalConfigManager.SkipAutoGen();
			List<Action<bool>> labels = new List<Action<bool>>();
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.SpokenSubtitles, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Dialogue", "音频对白", "Spoken subtitles", "音频对白字幕", "Independent of event display mode. LC Chinese Project owns dialogue when loaded (including manual English mode). Manage its subtitles in its settings; provider readiness is not verified.", "独立于事件显示模式。安装汉化时对白由 LC-Chinese-Project 管理(含 Sensus 手动英文模式),请在汉化设置中调整。检测到插件不代表已验证字幕服务就绪。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.Enabled, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "General", "常规", "Enabled", "启用提示", "Enable local creature sound captions and peripheral cues.", "启用本地生物声音字幕与周边提示。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new TextDropDownConfigItem(settings.DisplayMode, Describe<TextDropDownOptions>(new TextDropDownOptions(Array.Empty<string>()), "Peripheral", "周边声音", "Display mode", "显示模式", "Captions: subtitles only. Peripheral: indicators only. Hybrid: both. Applies immediately.", "Captions:仅字幕;Peripheral:仅周边提示;Hybrid:字幕与提示同时显示。即时生效。提示旁的名称仍由“显示声音标签”控制。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(settings.RingSize, Describe<FloatSliderOptions>(new FloatSliderOptions(), "Peripheral", "周边声音", "Ring size", "方向环范围", "Move markers closer to or farther from the center without changing hearing range.", "调整标记距画面中心的范围,不改变听域。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(settings.MarkerScale, Describe<FloatSliderOptions>(new FloatSliderOptions(), "Peripheral", "周边声音", "Marker size", "标记大小", "Scale symbols and their sound labels.", "缩放声音图形及名称标签。")));
			ConfigEntry<int> markerCount = settings.MarkerCount;
			IntInputFieldOptions val = new IntInputFieldOptions();
			((BaseRangeOptions<int>)val).Min = 0;
			((BaseRangeOptions<int>)val).Max = int.MaxValue;
			LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(markerCount, Describe<IntInputFieldOptions>(val, "Peripheral", "周边声音", "Maximum markers", "详细标记上限", "0 = unlimited; positive values set a display limit. Large counts may reduce FPS and readability. Screen space and overload protection still apply; excess events rotate by priority.", "0=无上限,正数为显示上限。数量过多可能降低帧率和可读性;仍受屏幕空间与过载保护约束,放不下的事件按优先级轮换。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.MarkerLabels, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Peripheral", "周边声音", "Sound labels", "显示声音标签", "Keep names visible while learning sound symbols.", "学习图形含义时保留声音名称。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.LowMotion, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Peripheral", "周边声音", "Low motion", "低动态模式", "No decorative pulse or smooth movement; directions still update.", "关闭装饰性扩张和平滑移动;方向仍正常更新。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new TextDropDownConfigItem(settings.Language, Describe<TextDropDownOptions>(new TextDropDownOptions(Array.Empty<string>()), "General", "常规", "Language", "语言", "Auto detects LC Chinese Project by GUID only. Changes apply live; reopen the menu to refresh its labels.", "Auto 按汉化插件 GUID 自动切换,不受版本号影响;Chinese/English 可手动覆盖。提示立即切换,重新打开菜单刷新名称。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.Preview, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Preview", "预览", "Show preview", "显示演示字幕", "Close the menu in a round to see a labelled native-style example. Turn off after testing.", "进入游戏回合并关闭菜单后显示原生样式演示字幕。它不代表真实怪物;测试后请关闭。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.UnlocatedIndicators, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Peripheral", "周边声音", "Unlocated indicators", "显示无方向提示", "Optional fixed tray for sounds without a reliable bearing. Off by default.", "为无法可靠定位的声音显示固定提示栏,默认关闭,不影响字幕。")));
			ConfigEntry<int> unlocatedCount = settings.UnlocatedCount;
			IntInputFieldOptions val2 = new IntInputFieldOptions();
			((BaseRangeOptions<int>)val2).Min = 0;
			((BaseRangeOptions<int>)val2).Max = int.MaxValue;
			LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(unlocatedCount, Describe<IntInputFieldOptions>(val2, "Peripheral", "周边声音", "Maximum unlocated", "无方向提示上限", "0 = unlimited; positive values set a display limit. Large counts may reduce FPS and readability. Screen space and overload protection still apply; excess events rotate by priority.", "0=无上限,正数为显示上限。数量过多可能降低帧率和可读性;仍受屏幕空间与过载保护约束,放不下的事件按优先级轮换。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.UnlocatedText, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Peripheral", "周边声音", "Show Unlocated text", "显示“无方向”文字", "Append Unlocated to fixed-tray labels. Off by default; does not toggle indicators.", "在右下角提示名称后显示“无方向”文字,默认关闭;不影响无方向提示本身,即时生效。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(settings.Scale, Describe<FloatSliderOptions>(new FloatSliderOptions(), "Layout", "布局", "Caption scale", "字幕缩放", "Scale the game's native text style, applied immediately.", "缩放游戏原生文字样式,即时生效。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.BottomAligned, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Layout", "布局", "Dock to bottom", "底部等距对齐", "Match bottom and right margins; turn off to use manual vertical position.", "底部与右侧等距;关闭后恢复手动纵向位置,即时生效。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(settings.VerticalPosition, Describe<FloatSliderOptions>(new FloatSliderOptions(), "Layout", "布局", "Vertical position", "纵向位置", "0 is the bottom of the screen; 1 is the top. Applied immediately.", "0 为屏幕底部,1 为顶部;即时生效。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.ShowDirection, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Captions", "字幕", "Show directions", "显示声音方向", "Coarse directions for spatial sounds. Unclear directions are labelled.", "空间声音显示粗略方位;不明确时会标注。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(settings.CaptionDuration, Describe<FloatSliderOptions>(new FloatSliderOptions(), "Captions", "字幕", "Hold seconds", "字幕保留时间", "Retain past sounds with frozen directions. This does not mean the danger ended.", "保留刚才听到的声音,方向冻结;不代表危险解除。")));
			ConfigEntry<int> maxCaptions = settings.MaxCaptions;
			IntInputFieldOptions val3 = new IntInputFieldOptions();
			((BaseRangeOptions<int>)val3).Min = 0;
			((BaseRangeOptions<int>)val3).Max = int.MaxValue;
			LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(maxCaptions, Describe<IntInputFieldOptions>(val3, "Captions", "字幕", "Maximum rows", "最大显示条数", "0 = unlimited; positive values set a display limit. Large counts may reduce FPS and readability. Screen space and overload protection still apply; excess events rotate by priority.", "0=无上限,正数为显示上限。数量过多可能降低帧率和可读性;仍受屏幕空间与过载保护约束,放不下的事件按优先级轮换。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(settings.MinimumGain, Describe<FloatSliderOptions>(new FloatSliderOptions(), "Advanced", "高级", "Audibility threshold", "可感知阈值", "Prototype estimated gain threshold. Lower values include quieter sounds; listening calibration is pending.", "原型的估计音量阈值;越低越容易显示轻声,尚需试听校准。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.Diagnostics, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Advanced", "高级", "Diagnostic counters", "诊断计数", "Write summary counts every ten seconds. Does not record audio or voice.", "每十秒记录汇总计数,不录制声音或语音。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(settings.ShowBackground, Describe<BoolCheckBoxOptions>(new BoolCheckBoxOptions(), "Layout", "布局", "Show backgrounds", "显示声音背景板", "Show solid backgrounds behind captions and peripheral labels. Text and symbols stay visible when off.", "显示字幕和周边标签的纯色背景板;关闭后文字与图形仍显示。即时生效。")));
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(settings.BackgroundOpacity, Describe<FloatSliderOptions>(new FloatSliderOptions(), "Layout", "布局", "Background opacity", "声音背景板不透明度", "0 is transparent; 1 is opaque. Applies to captions and peripheral labels, without changing text opacity.", "0 全透明,1 不透明;同时用于字幕与周边标签,不影响文字透明度。即时生效。")));
			Refresh(chinese);
			return Refresh;
			T Describe<T>(T options, string sectionEn, string sectionZh, string en, string zh, string descriptionEn, string descriptionZh) where T : notnull, BaseOptions
			{
				((BaseOptions)options).RequiresRestart = false;
				Apply(chinese);
				labels.Add(Apply);
				return options;
				void Apply(bool cn)
				{
					((BaseOptions)options).Section = (cn ? sectionZh : sectionEn);
					((BaseOptions)options).Name = (cn ? zh : en);
					((BaseOptions)options).Description = (cn ? descriptionZh : descriptionEn);
				}
			}
			void Refresh(bool cn)
			{
				foreach (Action<bool> item in labels)
				{
					item(cn);
				}
				LethalConfigManager.SetModDescription(cn ? "V81 生物听觉辅助:分类配色与图形、周边声音方向、短字幕与持续反馈。原生 UGUI 风格;逐事件实机与声学校准仍需验证。" : "V81 creature hearing assistance: category colors and shapes, peripheral directions and captions. Native UGUI style; per-event runtime and acoustic validation pending.");
			}
		}
	}
	internal sealed class NativeCaptionPresenter
	{
		private readonly ManualLogSource log;

		private HUDManager? owner;

		private RectTransform? panel;

		private Canvas? canvas;

		private TextMeshProUGUI? header;

		private TextMeshProUGUI? caption;

		private Image? background;

		private float startupRemaining = 4f;

		private float nextDiagnostic;

		private bool firstLiveReported;

		private string lastLoggedState = "";

		private TMP_FontAsset? checkedFont;

		private string measuredText = "";

		private string measuredTitle = "";

		private float measuredWidth;

		private float measuredUnit;

		private float measuredBodyHeight;

		private float measuredTitleHeight;

		private float measuredContentWidth;

		private TMP_FontAsset? measuredFont;

		private readonly PeripheralPresenter peripheral;

		private readonly Vector3[] slotCorners = (Vector3[])(object)new Vector3[4];

		private const string ChinesePreview = "左侧 · 上弦音乐\n右前方 · 枪声";

		private const string EnglishPreview = "Left · Winding music\nFront-right · Gunshot";

		internal string Status { get; private set; } = "waiting-for-hud";

		internal NativeCaptionPresenter(ManualLogSource log)
		{
			this.log = log;
			peripheral = new PeripheralPresenter(log);
		}

		internal void Tick(SensusSettings settings, bool chinese, string liveCaptions, bool captureReady, SoundField field, string spoken = "")
		{
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Expected O, but got Unknown
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0592: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_061c: Unknown result type (might be due to invalid IL or missing references)
			//IL_061e: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_079b: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0905: Unknown result type (might be due to invalid IL or missing references)
			//IL_090c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0923: Unknown result type (might be due to invalid IL or missing references)
			//IL_093c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0941: Unknown result type (might be due to invalid IL or missing references)
			//IL_094c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0951: Unknown result type (might be due to invalid IL or missing references)
			//IL_09af: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_09d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_09e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a07: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a0c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a10: Unknown result type (might be due to invalid IL or missing references)
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)owner != (Object)(object)instance)
			{
				Clear();
				owner = instance;
				startupRemaining = 4f;
				firstLiveReported = false;
			}
			if ((Object)(object)instance == (Object)null)
			{
				SetState("waiting-for-hud", settings);
				return;
			}
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			bool menuOpen = (Object)(object)val != (Object)null && (val.inTerminalMenu || ((Object)(object)val.quickMenuManager != (Object)null && val.quickMenuManager.isMenuOpen));
			CaptionDisplayMode captionDisplayMode = CaptionDisplayPolicy.Select(settings.Enabled.Value, (Object)(object)val != (Object)null && val.isPlayerControlled, (Object)(object)val != (Object)null && val.isPlayerDead, menuOpen, instance.hudHidden, settings.Preview.Value, !string.IsNullOrEmpty(spoken) || !string.IsNullOrEmpty(liveCaptions) || (settings.DisplayMode.Value != "Captions" && field.HasSignals), startup: false);
			if ((uint)(captionDisplayMode - 6) > 2u)
			{
				peripheral.Hide();
				if ((Object)(object)panel != (Object)null)
				{
					((Component)panel).gameObject.SetActive(false);
				}
				if (captionDisplayMode == CaptionDisplayMode.Disabled)
				{
					startupRemaining = 4f;
				}
				SetState(captionDisplayMode.ToString(), settings);
				return;
			}
			if ((Object)(object)panel == (Object)null && !CreatePanel(instance))
			{
				SetState("waiting-for-native-templates", settings);
				return;
			}
			if ((Object)(object)canvas == (Object)null || !((Behaviour)canvas).isActiveAndEnabled)
			{
				SetState("native-canvas-inactive", settings);
				return;
			}
			if ((Object)(object)instance.tipsPanelBody == (Object)null || (Object)(object)instance.tipsPanelHeader == (Object)null)
			{
				SetState("native-font-source-unavailable", settings);
				return;
			}
			bool flag = captionDisplayMode == CaptionDisplayMode.Preview;
			bool flag2 = captionDisplayMode == CaptionDisplayMode.Startup;
			bool flag3 = settings.DisplayMode.Value != "Captions";
			float num = Mathf.Max(14f, ((TMP_Text)instance.tipsPanelBody).fontSize) * settings.Scale.Value * 0.85f;
			RectTransform val2 = (RectTransform)((Component)canvas).transform;
			Rect val3 = CaptionArea(instance, val2, num);
			float yMax = ((Rect)(ref val3)).yMax;
			float yMin = ((Rect)(ref val3)).yMin;
			Rect rect = val2.rect;
			((Rect)(ref val3)).yMax = Mathf.Min(yMax, yMin + ((Rect)(ref rect)).height * 0.48f);
			if (flag3 && !flag2)
			{
				peripheral.Tick(canvas, instance.tipsPanelBody, field, settings, chinese, flag, val3);
			}
			else
			{
				peripheral.Hide();
			}
			peripheral.MeasureUnlocated(val3, Mathf.Max(14f, ((TMP_Text)instance.tipsPanelBody).fontSize) * settings.MarkerScale.Value * 0.85f);
			float num2 = num * 0.5f;
			float num3;
			if (!settings.BottomAligned.Value)
			{
				rect = val2.rect;
				float yMin2 = ((Rect)(ref rect)).yMin;
				rect = val2.rect;
				num3 = yMin2 + ((Rect)(ref rect)).height * settings.VerticalPosition.Value;
			}
			else
			{
				num3 = ((Rect)(ref val3)).yMin;
			}
			float bottom = Mathf.Clamp(num3, ((Rect)(ref val3)).yMin, ((Rect)(ref val3)).yMax - peripheral.UnlocatedHeight);
			PeripheralPresenter peripheralPresenter = peripheral;
			Rect safe = val3;
			rect = val2.rect;
			peripheralPresenter.ArrangeUnlocated(safe, bottom, ((Rect)(ref rect)).center);
			if (settings.DisplayMode.Value == "Peripheral" && spoken.Length == 0)
			{
				((Component)panel).gameObject.SetActive(false);
				SetState("indicators-only", settings);
				return;
			}
			string text = ((!flag) ? ((!flag2) ? ((spoken.Length == 0) ? liveCaptions : (spoken + ((liveCaptions.Length == 0) ? "" : ("\n" + liveCaptions)))) : ((!captureReady) ? (chinese ? "声音采集未就绪,请查看日志" : "Sound capture unavailable; check the log") : (chinese ? "声音字幕已启用" : "Sound captions enabled"))) : (chinese ? "左侧 · 上弦音乐\n右前方 · 枪声" : "Left · Winding music\nFront-right · Gunshot"));
			if (flag && flag3)
			{
				text = (chinese ? "转头查看方向 · 后方低吼每隔数秒消退" : "Turn to see directions · rear growl fades periodically");
			}
			if (!flag && liveCaptions.Length > 0)
			{
				AudioCapture current = AudioCapture.Current;
				if (current != null && current.OmittedCaptions > 0)
				{
					text += (chinese ? $"\n另有 {current.OmittedCaptions} 项 · 轮换显示" : $"\n{current.OmittedCaptions} more · rotating");
				}
			}
			if (string.IsNullOrEmpty(text))
			{
				((Component)panel).gameObject.SetActive(false);
				return;
			}
			string text2 = ((!flag) ? (chinese ? "SENSUS / 声音线索" : "SENSUS / SOUND CUES") : (chinese ? "SENSUS / 界面演示 · 非真实事件" : "SENSUS / UI PREVIEW · NOT LIVE"));
			if (flag && !captureReady)
			{
				text2 += (chinese ? " · 采集未就绪" : " · CAPTURE UNAVAILABLE");
			}
			((Component)panel).gameObject.SetActive(true);
			SyncStyle(header, instance.tipsPanelHeader);
			SyncStyle(caption, instance.tipsPanelBody);
			bool flag4 = flag || flag2;
			((Component)header).gameObject.SetActive(flag4);
			((TMP_Text)header).text = text2;
			((TMP_Text)caption).text = text;
			((TMP_Text)header).fontSize = num * 0.65f;
			((TMP_Text)caption).fontSize = num;
			((Graphic)header).color = new Color(1f, 0.62f, 0.22f, 1f);
			((Graphic)caption).color = new Color(0.96f, 0.96f, 0.92f, 1f);
			((Graphic)background).color = new Color(0.02f, 0.025f, 0.02f, settings.BackgroundOpacity.Value);
			((Component)background).gameObject.SetActive(settings.ShowBackground.Value && settings.BackgroundOpacity.Value > 0f);
			Rect val4 = val3;
			if (peripheral.UnlocatedHeight > 0f)
			{
				((Rect)(ref val4)).yMax = ((Rect)(ref val4)).yMax - (peripheral.UnlocatedHeight + num2);
			}
			AudioCapture current2 = AudioCapture.Current;
			if (current2 != null)
			{
				current2.CaptionScreenBudget = Mathf.Max(1, DisplayCapacity.Rows(((Rect)(ref val4)).height - num * 3f - ((spoken.Length > 0) ? (num * 4f) : 0f), num * 3f));
			}
			float num4 = Mathf.Min(num * (float)(flag4 ? 18 : 14), ((Rect)(ref val4)).width);
			if (num4 <= num * 3f)
			{
				((Component)panel).gameObject.SetActive(false);
				SetState("native-canvas-layout-pending", settings);
				return;
			}
			float num5 = num * (flag3 ? 0.4f : 0.7f);
			string text3 = (flag4 ? text2 : "");
			if (measuredText != text || measuredTitle != text3 || measuredWidth != num4 - num5 * 2f || measuredUnit != num || (Object)(object)measuredFont != (Object)(object)((TMP_Text)caption).font)
			{
				measuredText = text;
				measuredTitle = text3;
				measuredWidth = num4 - num5 * 2f;
				measuredUnit = num;
				measuredFont = ((TMP_Text)caption).font;
				Vector2 val5 = (flag4 ? ((TMP_Text)header).GetPreferredValues(text2, measuredWidth, float.PositiveInfinity) : Vector2.zero);
				Vector2 preferredValues = ((TMP_Text)caption).GetPreferredValues(text, measuredWidth, float.PositiveInfinity);
				measuredTitleHeight = val5.y;
				measuredBodyHeight = preferredValues.y;
				measuredContentWidth = Mathf.Max(val5.x, preferredValues.x);
			}
			if (((Rect)(ref val4)).height < num5 * 2f + num * 2f)
			{
				((Component)panel).gameObject.SetActive(false);
				SetState("native-canvas-layout-pending", settings);
				return;
			}
			float num6 = Mathf.Min(measuredTitleHeight, ((Rect)(ref val4)).height * 0.3f);
			float num7 = (flag4 ? (num * 0.3f) : 0f);
			float num8 = Mathf.Min(Mathf.Max(num * 1.2f, measuredBodyHeight), ((Rect)(ref val4)).height - num5 * 2f - num6 - num7);
			((TMP_Text)caption).enableAutoSizing = measuredBodyHeight > num8;
			((TMP_Text)caption).fontSizeMin = num * 0.55f;
			((TMP_Text)caption).fontSizeMax = num;
			float num9 = num5 * 2f + num6 + num7 + num8;
			RectTransform? obj = panel;
			RectTransform? obj2 = panel;
			Vector2 val6 = default(Vector2);
			((Vector2)(ref val6))..ctor(0f, 0f);
			obj2.anchorMax = val6;
			obj.anchorMin = val6;
			panel.pivot = new Vector2(1f, 0.5f);
			float num10;
			if (!settings.BottomAligned.Value)
			{
				rect = val2.rect;
				float yMin3 = ((Rect)(ref rect)).yMin;
				rect = val2.rect;
				num10 = yMin3 + ((Rect)(ref rect)).height * settings.VerticalPosition.Value;
			}
			else
			{
				num10 = ((Rect)(ref val4)).yMin + num9 * 0.5f;
			}
			float num11 = Mathf.Clamp(num10, ((Rect)(ref val4)).yMin + num9 * 0.5f, ((Rect)(ref val4)).yMax - num9 * 0.5f);
			RectTransform? obj3 = panel;
			float xMax = ((Rect)(ref val4)).xMax;
			rect = val2.rect;
			float num12 = xMax - ((Rect)(ref rect)).xMin;
			rect = val2.rect;
			obj3.anchoredPosition = new Vector2(num12, num11 - ((Rect)(ref rect)).yMin);
			panel.sizeDelta = new Vector2(num4, num9);
			PeripheralPresenter peripheralPresenter2 = peripheral;
			Rect safe2 = val3;
			float bottom2 = num11 + num9 * 0.5f + num2;
			rect = val2.rect;
			peripheralPresenter2.ArrangeUnlocated(safe2, bottom2, ((Rect)(ref rect)).center);
			Place(((TMP_Text)header).rectTransform, num5, num5, num4 - 2f * num5, num6);
			Place(((TMP_Text)caption).rectTransform, num5, num5 + num6 + num7, num4 - 2f * num5, num8);
			if (chinese && (Object)(object)((TMP_Text)caption).font != (Object)null && (Object)(object)checkedFont != (Object)(object)((TMP_Text)caption).font)
			{
				checkedFont = ((TMP_Text)caption).font;
				uint[] array = default(uint[]);
				if (!((TMP_Text)caption).font.HasCharacters("左侧 · 上弦音乐\n右前方 · 枪声" + text2, ref array, true, true))
				{
					log.LogWarning((object)"Sensus native font is missing Chinese glyphs; check LC Chinese Project font support or select English.");
				}
			}
			SetState($"visible-{captionDisplayMode}", settings);
			if (flag2)
			{
				startupRemaining = Mathf.Max(0f, startupRemaining - Time.unscaledDeltaTime);
			}
			if (captionDisplayMode == CaptionDisplayMode.Live && !firstLiveReported)
			{
				firstLiveReported = true;
				log.LogInfo((object)"First live sound caption submitted to the Sensus panel. Visual confirmation is still required.");
			}
			if (settings.Diagnostics.Value && Time.unscaledTime >= nextDiagnostic)
			{
				nextDiagnostic = Time.unscaledTime + 10f;
				log.LogInfo((object)$"UI: state={Status}, active={((Component)panel).gameObject.activeInHierarchy}, canvas={((Behaviour)canvas).isActiveAndEnabled}, alpha={caption.canvasRenderer.GetInheritedAlpha():F2}, glyphs={((TMP_Text)caption).textInfo.characterCount}, size={num4:F0}x{num9:F0}.");
			}
		}

		private bool CreatePanel(HUDManager hud)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_0103: 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_0138: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hud.tipsPanelBody == (Object)null || (Object)(object)hud.tipsPanelHeader == (Object)null || (Object)(object)hud.HUDContainer == (Object)null)
			{
				return false;
			}
			Canvas componentInParent = hud.HUDContainer.GetComponentInParent<Canvas>();
			canvas = ((componentInParent != null) ? componentInParent.rootCanvas : null);
			Image componentInParent2 = ((Component)hud.tipsPanelBody).GetComponentInParent<Image>();
			if ((Object)(object)canvas == (Object)null || (Object)(object)componentInParent2 == (Object)null)
			{
				return false;
			}
			GameObject val = new GameObject("SensusCaptionPanel", new Type[2]
			{
				typeof(RectTransform),
				typeof(CanvasGroup)
			});
			val.SetActive(false);
			val.transform.SetParent(((Component)canvas).transform, false);
			panel = val.GetComponent<RectTransform>();
			CanvasGroup component = val.GetComponent<CanvasGroup>();
			component.alpha = 1f;
			component.interactable = false;
			component.blocksRaycasts = false;
			background = NativeUiTemplates.CloneImage(componentInParent2, (Transform)(object)panel, "Background");
			((Graphic)background).rectTransform.anchorMin = Vector2.zero;
			((Graphic)background).rectTransform.anchorMax = Vector2.one;
			RectTransform rectTransform = ((Graphic)background).rectTransform;
			Vector2 offsetMin = (((Graphic)background).rectTransform.offsetMax = Vector2.zero);
			rectTransform.offsetMin = offsetMin;
			header = NativeUiTemplates.CloneText(hud.tipsPanelHeader, (Transform)(object)panel, "Heading");
			caption = NativeUiTemplates.CloneText(hud.tipsPanelBody, (Transform)(object)panel, "CaptionRows");
			TextMeshProUGUI? obj = header;
			TextMeshProUGUI? obj2 = caption;
			TextAlignmentOptions alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj).alignment = alignment;
			TextMeshProUGUI? obj3 = header;
			TextMeshProUGUI? obj4 = caption;
			TextOverflowModes overflowMode = (TextOverflowModes)1;
			((TMP_Text)obj4).overflowMode = (TextOverflowModes)1;
			((TMP_Text)obj3).overflowMode = overflowMode;
			log.LogInfo((object)("Sensus UI created from native UGUI templates under Canvas '" + ((Object)canvas).name + "'; independent panel, original controls retained."));
			return true;
		}

		private Rect CaptionArea(HUDManager hud, RectTransform canvasRect, float unit)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_0196: Unknown result type (might be due to invalid IL or missing references)
			Rect val = canvasRect.rect;
			Camera val2 = (((int)canvas.renderMode == 0) ? null : canvas.worldCamera);
			Rect safeArea = Screen.safeArea;
			Vector2 val3 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, ((Rect)(ref safeArea)).min, val2, ref val3))
			{
				safeArea = Screen.safeArea;
				Vector2 val4 = default(Vector2);
				if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, ((Rect)(ref safeArea)).max, val2, ref val4))
				{
					val = Rect.MinMaxRect(Mathf.Max(((Rect)(ref val)).xMin, val3.x), Mathf.Max(((Rect)(ref val)).yMin, val3.y), Mathf.Min(((Rect)(ref val)).xMax, val4.x), Mathf.Min(((Rect)(ref val)).yMax, val4.y));
				}
			}
			float num = Mathf.Max(10f, unit * 0.6f);
			Rect result = Rect.MinMaxRect(((Rect)(ref val)).xMin + num, ((Rect)(ref val)).yMin + num, ((Rect)(ref val)).xMax - num, ((Rect)(ref val)).yMax - num);
			float num2 = Mathf.Max(((Rect)(ref result)).xMin, ((Rect)(ref result)).xMax - ((Rect)(ref val)).width * 0.32f);
			float num3 = float.NegativeInfinity;
			float num4 = float.NegativeInfinity;
			if (hud.itemSlotIconFrames != null)
			{
				Image[] itemSlotIconFrames = hud.itemSlotIconFrames;
				foreach (Image val5 in itemSlotIconFrames)
				{
					if (!((Object)(object)val5 == (Object)null) && ((Component)val5).gameObject.activeInHierarchy)
					{
						((Graphic)val5).rectTransform.GetWorldCorners(slotCorners);
						Vector3[] array = slotCorners;
						foreach (Vector3 val6 in array)
						{
							Vector3 val7 = ((Transform)canvasRect).InverseTransformPoint(val6);
							num3 = Mathf.Max(num3, val7.x);
							num4 = Mathf.Max(num4, val7.y);
						}
					}
				}
			}
			if (num3 + num > num2)
			{
				if (((Rect)(ref result)).xMax - num3 - num >= unit * 7f)
				{
					num2 = num3 + num;
				}
				else
				{
					((Rect)(ref result)).yMin = Mathf.Max(((Rect)(ref result)).yMin, num4 + num);
				}
			}
			((Rect)(ref result)).xMin = num2;
			return result;
		}

		private static void SyncStyle(TextMeshProUGUI copy, TextMeshProUGUI template)
		{
			if ((Object)(object)((TMP_Text)copy).font != (Object)(object)((TMP_Text)template).font)
			{
				((TMP_Text)copy).font = ((TMP_Text)template).font;
			}
			if ((Object)(object)((TMP_Text)copy).fontSharedMaterial != (Object)(object)((TMP_Text)template).fontSharedMaterial)
			{
				((TMP_Text)copy).fontSharedMaterial = ((TMP_Text)template).fontSharedMaterial;
			}
			copy.canvasRenderer.SetAlpha(1f);
			((TMP_Text)copy).alpha = 1f;
		}

		private static void Place(RectTransform rect, float left, float top, float width, float height)
		{
			//IL_0013: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			rect.anchorMax = val;
			rect.anchorMin = val;
			rect.pivot = new Vector2(0f, 1f);
			rect.anchoredPosition = new Vector2(left, 0f - top);
			rect.sizeDelta = new Vector2(width, height);
		}

		private void SetState(string state, SensusSettings settings)
		{
			Status = state;
			if (state == lastLoggedState)
			{
				return;
			}
			if (!settings.Diagnostics.Value)
			{
				switch (state)
				{
				case "visible-Preview":
				case "visible-Startup":
				case "waiting-for-native-templates":
					goto IL_0057;
				}
				if (!state.StartsWith("native-"))
				{
					goto IL_0072;
				}
			}
			goto IL_0057;
			IL_0072:
			lastLoggedState = state;
			return;
			IL_0057:
			log.LogInfo((object)("Sensus UI state: " + state + "."));
			goto IL_0072;
		}

		internal void Clear()
		{
			peripheral.Clear();
			if ((Object)(object)panel != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)panel).gameObject);
			}
			panel = null;
			canvas = null;
			background = null;
			header = (caption = null);
			checkedFont = null;
			measuredFont = null;
			measuredText = (measuredTitle = "");
			owner = null;
		}
	}
	internal static class NativeUiTemplates
	{
		internal static TextMeshProUGUI CloneText(TextMeshProUGUI template, Transform parent, string name)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = Object.Instantiate<TextMeshProUGUI>(template, parent, false);
			Clean(((Component)val).gameObject, (Component)(object)val);
			((Object)val).name = name;
			((Behaviour)val).enabled = true;
			((Graphic)val).raycastTarget = false;
			((MaskableGraphic)val).maskable = false;
			((TMP_Text)val).enableAutoSizing = false;
			((TMP_Text)val).enableVertexGradient = false;
			((TMP_Text)val).enableWordWrapping = true;
			((TMP_Text)val).overflowMode = (TextOverflowModes)0;
			((TMP_Text)val).margin = Vector4.zero;
			((TMP_Text)val).maxVisibleCharacters = int.MaxValue;
			((TMP_Text)val).maxVisibleWords = int.MaxValue;
			((TMP_Text)val).maxVisibleLines = int.MaxValue;
			((TMP_Text)val).firstVisibleCharacter = 0;
			((TMP_Text)val).alpha = 1f;
			val.canvasRenderer.SetAlpha(1f);
			val.canvasRenderer.cull = false;
			((TMP_Text)val).text = "";
			((Component)val).gameObject.SetActive(true);
			ResetTransform(((TMP_Text)val).rectTransform);
			return val;
		}

		internal static Image CloneImage(Image template, Transform parent, string name)
		{
			Image val = Object.Instantiate<Image>(template, parent, false);
			Clean(((Component)val).gameObject, (Component)(object)val);
			((Object)val).name = name;
			((Behaviour)val).enabled = true;
			((Graphic)val).raycastTarget = false;
			((MaskableGraphic)val).maskable = false;
			val.overrideSprite = null;
			val.sprite = null;
			((Graphic)val).material = null;
			val.type = (Type)0;
			val.preserveAspect = false;
			((Graphic)val).canvasRenderer.SetAlpha(1f);
			((Graphic)val).canvasRenderer.cull = false;
			((Component)val).gameObject.SetActive(true);
			ResetTransform(((Graphic)val).rectTransform);
			return val;
		}

		private static void Clean(GameObject copy, Component keep)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			Component[] components = copy.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)keep) && !(val is RectTransform) && !(val is CanvasRenderer))
				{
					Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
					if (val2 != null)
					{
						val2.enabled = false;
					}
					CanvasGroup val3 = (CanvasGroup)(object)((val is CanvasGroup) ? val : null);
					if (val3 != null)
					{
						val3.alpha = 1f;
						val3.blocksRaycasts = false;
					}
					Button val4 = (Button)(object)((val is Button) ? val : null);
					if (val4 != null)
					{
						val4.onClick = new ButtonClickedEvent();
					}
					Object.Destroy((Object)(object)val);
				}
			}
			for (int j = 0; j < copy.transform.childCount; j++)
			{
				GameObject gameObject = ((Component)copy.transform.GetChild(j)).gameObject;
				gameObject.SetActive(false);
				Object.Destroy((Object)(object)gameObject);
			}
		}

		private static void ResetTransform(RectTransform rect)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			((Transform)rect).localPosition = Vector3.zero;
			((Transform)rect).localRotation = Quaternion.identity;
			((Transform)rect).localScale = Vector3.one;
		}
	}
	internal sealed class PeripheralPresenter
	{
		private sealed class Marker
		{
			internal RectTransform Root;

			internal SoundMarkerGraphic Graphic;

			internal TextMeshProUGUI Label;

			internal Image Backing;

			internal int Id;

			internal float Angle;

			internal float Sector;

			internal bool Initialized;

			internal Vector2 Position;

			internal float OrbitAngle;

			internal float OrbitOffset;

			internal float DisplayOffset;

			internal float OffsetVelocity;

			internal Cue LabelCue = (Cue)(-1);

			internal bool LabelChinese;

			internal bool LabelRear;

			internal bool LabelUnlocatedText;

			internal float LabelUnit;

			internal TMP_FontAsset? LabelFont;

			internal string TrayText = "";

			internal float TrayWidth = -1f;

			internal float TrayUnit;

			internal float NaturalWidth;

			internal float TextHeight;

			internal TMP_FontAsset? TrayFont;
		}

		private RectTransform? root;

		private readonly List<Marker> markers = new List<Marker>();

		private readonly List<Marker> overflow = new List<Marker>();

		private readonly List<Marker> tray = new List<Marker>();

		private readonly float[] placed = new float[64];

		private int placedCount;

		private readonly SoundField demo = new SoundField();

		private int positionCount;

		private bool previewing;

		private float previewYaw;

		private float previewStart;

		private readonly ManualLogSource log;

		private bool firstRealMarker;

		private float trayWidth;

		private float trayRowHeight;

		private float trayGap;

		private float trayUnit;

		private int trayCount;

		internal float UnlocatedHeight
		{
			get
			{
				if (trayCount != 0)
				{
					return (float)trayCount * trayRowHeight + (float)(trayCount - 1) * trayGap;
				}
				return 0f;
			}
		}

		internal PeripheralPresenter(ManualLogSource log)
		{
			this.log = log;
		}

		internal void Tick(Canvas canvas, TextMeshProUGUI template, SoundField field, SensusSettings settings, bool chinese, bool preview, Rect fullSafe)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_006b: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Expected O, but got Unknown
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Expected O, but got Unknown
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e21: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e53: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e58: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e61: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e71: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e8d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ea5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0eb5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ed1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ee9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f25: Unknown result type (might be due to invalid IL or missing references)
			//IL_076e: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0972: Unknown result type (might be due to invalid IL or missing references)
			//IL_0985: Unknown result type (might be due to invalid IL or missing references)
			//IL_094c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0962: Unknown result type (might be due to invalid IL or missing references)
			//IL_09fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_087c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0881: Unknown result type (might be due to invalid IL or missing references)
			//IL_088f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b13: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d29: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d30: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d7c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c00: Unknown result type (might be due to invalid IL or missing references)
			//IL_0beb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c6a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c82: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ca0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				GameObject val = new GameObject("SensusPeripheralSounds", new Type[2]
				{
					typeof(RectTransform),
					typeof(CanvasGroup)
				});
				val.SetActive(false);
				val.transform.SetParent(((Component)canvas).transform, false);
				root = val.GetComponent<RectTransform>();
				root.anchorMin = Vector2.zero;
				root.anchorMax = Vector2.one;
				RectTransform? obj = root;
				Vector2 offsetMin = (root.offsetMax = Vector2.zero);
				obj.offsetMin = offsetMin;
				CanvasGroup component = val.GetComponent<CanvasGroup>();
				component.blocksRaycasts = false;
				component.interactable = false;
				Image componentInParent = ((Component)template).GetComponentInParent<Image>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					Clear();
					return;
				}
				for (int i = 0; i < 8; i++)
				{
					overflow.Add(Create(template, componentInParent, "AdditionalSoundDirection", root));
				}
				log.LogInfo((object)"Sensus peripheral UGUI created: pooled sound symbols, native labels and critical overflow arcs.");
			}
			((Component)root).gameObject.SetActive(true);
			if (((Transform)root).GetSiblingIndex() != ((Transform)root).parent.childCount - 1)
			{
				((Transform)root).SetAsLastSibling();
			}
			Camera val2 = GameNetworkManager.Instance?.localPlayerController?.gameplayCamera;
			float yaw = (((Object)(object)val2 != (Object)null) ? ((Component)val2).transform.eulerAngles.y : 0f);
			float unscaledTime = Time.unscaledTime;
			if (preview != previewing)
			{
				foreach (Marker marker3 in markers)
				{
					marker3.Initialized = false;
				}
			}
			if (preview)
			{
				if (!previewing)
				{
					previewStart = unscaledTime;
					previewYaw = yaw;
					demo.Clear();
				}
				demo.Observe(-1, Cue.Music, unscaledTime, previewYaw - 90f, known: true, continuous: true, 0.2f, localMovement: false, WindingEnvelope.At((unscaledTime - previewStart) % 43f), (unscaledTime - previewStart) % 43f);
				demo.Observe(-2, Cue.Reload, unscaledTime, previewYaw + 90f, known: true, continuous: true, 0.5f);
				if ((unscaledTime - previewStart) % 8f < 5f)
				{
					demo.Observe(-3, Cue.Growl, unscaledTime, previewYaw + 180f, known: true, continuous: true, 0.1f);
				}
				field = demo;
			}
			previewing = preview;
			float num = Mathf.Max(14f, ((TMP_Text)template).fontSize) * settings.MarkerScale.Value;
			Rect rect = ((RectTransform)((Component)canvas).transform).rect;
			Rect val3 = rect;
			Camera val4 = (((int)canvas.renderMode == 0) ? null : canvas.worldCamera);
			RectTransform val5 = (RectTransform)((Component)canvas).transform;
			Rect safeArea = Screen.safeArea;
			Vector2 val6 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val5, ((Rect)(ref safeArea)).min, val4, ref val6))
			{
				RectTransform val7 = (RectTransform)((Component)canvas).transform;
				safeArea = Screen.safeArea;
				Vector2 val8 = default(Vector2);
				if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val7, ((Rect)(ref safeArea)).max, val4, ref val8))
				{
					val3 = Rect.MinMaxRect(Mathf.Max(((Rect)(ref rect)).xMin, val6.x), Mathf.Max(((Rect)(ref rect)).yMin, val6.y), Mathf.Min(((Rect)(ref rect)).xMax, val8.x), Mathf.Min(((Rect)(ref rect)).yMax, val8.y));
				}
			}
			float num2 = num * 0.5f;
			float num3 = Mathf.Max(1f, Mathf.Min(((Rect)(ref rect)).width * 0.5f * settings.RingSize.Value, Mathf.Min(((Rect)(ref rect)).center.x - ((Rect)(ref val3)).xMin, ((Rect)(ref val3)).xMax - ((Rect)(ref rect)).center.x) - num * 3.75f - num2));
			float num4 = Mathf.Max(1f, Mathf.Min(((Rect)(ref rect)).height * 0.5f * settings.RingSize.Value, Mathf.Min(((Rect)(ref rect)).center.y - ((Rect)(ref val3)).yMin, ((Rect)(ref val3)).yMax - ((Rect)(ref rect)).center.y) - num * 5.1f - num2));
			positionCount = DisplayCapacity.Rows(MathF.PI * 2f * Mathf.Min(num3, num4), num * 8.6f);
			int num5 = DisplayCapacity.Resolve(settings.MarkerCount.Value, positionCount);
			int available = DisplayCapacity.Rows(((Rect)(ref fullSafe)).height * 0.45f, num * 3.3f * 0.85f);
			int num6 = (settings.UnlocatedIndicators.Value ? DisplayCapacity.Resolve(settings.UnlocatedCount.Value, available) : 0);
			field.Update(unscaledTime, num5, yaw, num6);
			Image componentInParent2 = ((Component)template).GetComponentInParent<Image>();
			if ((Object)(object)componentInParent2 == (Object)null)
			{
				return;
			}
			Grow(markers, field.Visible.Count, template, componentInParent2, "Sound");
			Grow(tray, field.Unlocated.Count, template, componentInParent2, "UnlocatedSound");
			field.Update(unscaledTime, Mathf.Min(num5, markers.Count), yaw, Mathf.Min(num6, tray.Count));
			Match(markers, field.Visible);
			Match(tray, field.Unlocated);
			placedCount = 0;
			for (int j = 0; j < markers.Count + tray.Count; j++)
			{
				bool flag = j >= markers.Count;
				int num7 = (flag ? (j - markers.Count) : j);
				Marker marker = (flag ? tray[num7] : markers[num7]);
				IReadOnlyList<SoundField.Signal> readOnlyList = (flag ? field.Unlocated : field.Visible);
				if ((flag && !settings.UnlocatedIndicators.Value) || num7 >= readOnlyList.Count || (!flag && !settings.ShowDirection.Value))
				{
					((Component)marker.Root).gameObject.SetActive(false);
					marker.Initialized = false;
					continue;
				}
				SoundField.Signal signal = readOnlyList[num7];
				if (flag && !SoundField.CanUnlocate(signal))
				{
					((Component)marker.Root).gameObject.SetActive(false);
					continue;
				}
				if (!flag && !preview && !firstRealMarker && SoundField.IsLive(signal, unscaledTime))
				{
					firstRealMarker = true;
					log.LogInfo((object)"First real audible direction submitted to the Sensus peripheral UI; visual confirmation is still required.");
				}
				float num8 = SoundField.Relative(signal.Bearing, yaw);
				bool flag2 = !marker.Initialized || marker.Id != signal.Id;
				if (flag2)
				{
					marker.Id = signal.Id;
					marker.Initialized = true;
					marker.Sector = (float)CueText.DirectionIndex(num8) * 45f;
					marker.Angle = num8;
				}
				if (SoundField.IsLive(signal, unscaledTime))
				{
					marker.Sector = SoundField.SectorAngle(num8, marker.Sector);
					marker.Angle = IndicatorDetail.Follow(marker.Angle, num8, Time.unscaledDeltaTime, settings.LowMotion.Value);
				}
				bool flag3 = false;
				Place(marker, rect, marker.Angle, 0, num, settings.RingSize.Value);
				if (!flag)
				{
					float gap = 360f / (float)Mathf.Max(1, positionCount);
					if (flag2)
					{
						marker.OrbitOffset = 0f;
						marker.OffsetVelocity = 0f;
					}
					marker.OrbitOffset = StableOrbit.Offset(signal.Bearing, marker.OrbitOffset, placed, placedCount, gap);
					if (flag2)
					{
						marker.DisplayOffset = marker.OrbitOffset;
					}
					else
					{
						marker.DisplayOffset = StableOrbit.Ease(marker.DisplayOffset, marker.OrbitOffset, ref marker.OffsetVelocity, Time.unscaledDeltaTime, settings.LowMotion.Value);
					}
					float num9 = marker.Angle + marker.DisplayOffset;
					marker.OrbitAngle = (flag2 ? num9 : IndicatorDetail.Follow(marker.OrbitAngle, num9, Time.unscaledDeltaTime, settings.LowMotion.Value));
					marker.Position = Orbit(marker.OrbitAngle, num3, num4);
					marker.Root.anchoredPosition = marker.Position;
					placed[placedCount++] = signal.Bearing + marker.OrbitOffset;
					((Transform)marker.Root).SetAsLastSibling();
				}
				float num10 = SoundField.Alpha(signal, unscaledTime);
				Color color = SoundMarkerGraphic.Tint(signal.Cue, num10);
				float num11 = WindingEnvelope.Urgency(signal.WindingSeconds);
				if (signal.Cue == Cue.Music && signal.WindingSeconds >= 0f)
				{
					((Color)(ref color))..ctor(1f, 0.8f - 0.55f * num11, 0.25f - 0.03f * num11, num10);
				}
				if (signal.Cue == Cue.Music)
				{
					((Graphic)marker.Graphic).color = Color.white;
					((Graphic)marker.Graphic).canvasRenderer.SetColor(color);
				}
				else
				{
					((Graphic)marker.Graphic).color = color;
					((Graphic)marker.Graphic).canvasRenderer.SetColor(Color.white);
				}
				marker.Graphic.Set(flag ? 0f : marker.Angle, signal.Cue, signal.Strength, flag3, !flag);
				((TMP_Text)marker.Label).font = ((TMP_Text)template).font;
				((TMP_Text)marker.Label).fontSharedMaterial = ((TMP_Text)template).fontSharedMaterial;
				((Graphic)marker.Label).color = new Color(0.96f, 0.96f, 0.92f, num10);
				bool flag4 = !flag && CueText.DirectionIndex(marker.Angle) == 4;
				bool flag5 = flag && settings.UnlocatedText.Value;
				bool num12 = marker.LabelCue != signal.Cue || marker.LabelChinese != chinese || marker.LabelRear != flag4 || marker.LabelUnit != num || (Object)(object)marker.LabelFont != (Object)(object)((TMP_Text)template).font || marker.LabelUnlocatedText != flag5;
				bool flag6 = settings.MarkerLabels.Value && !flag3;
				((Component)marker.Label).gameObject.SetActive(flag6);
				((Component)marker.Backing).gameObject.SetActive(flag6 && settings.ShowBackground.Value && settings.BackgroundOpacity.Value > 0f);
				((Graphic)marker.Backing).color = new Color(0.015f, 0.02f, 0.015f, settings.BackgroundOpacity.Value * num10);
				if (num12)
				{
					((TMP_Text)marker.Label).enableAutoSizing = false;
					((TMP_Text)marker.Label).fontSize = num * 0.8f;
					((TMP_Text)marker.Label).text = IndicatorDetail.Label(signal.Cue, chinese, flag4, flag5);
					marker.LabelCue = signal.Cue;
					marker.LabelChinese = chinese;
					marker.LabelRear = flag4;
					marker.LabelUnit = num;
					marker.LabelFont = ((TMP_Text)template).font;
					marker.LabelUnlocatedText = flag5;
					float num13 = (flag ? Mathf.Min(num * 8f, ((Rect)(ref rect)).width * 0.27f) : (num * 6.5f));
					Vector2 preferredValues = ((TMP_Text)marker.Label).GetPreferredValues(((TMP_Text)marker.Label).text, num13, float.PositiveInfinity);
					float num14 = (flag ? preferredValues.y : Mathf.Min(preferredValues.y, num * 3.2f));
					((TMP_Text)marker.Label).enableWordWrapping = true;
					((TMP_Text)marker.Label).enableAutoSizing = !flag;
					((TMP_Text)marker.Label).fontSizeMin = num * 0.55f;
					((TMP_Text)marker.Label).fontSizeMax = num * 0.8f;
					((TMP_Text)marker.Label).overflowMode = (TextOverflowModes)1;
					((TMP_Text)marker.Label).rectTransform.sizeDelta = new Vector2(num13, num14);
					((Graphic)marker.Backing).rectTransform.sizeDelta = new Vector2(Mathf.Min(num13, preferredValues.x) + num * 0.5f, num14 + num * 0.35f);
				}
				float age = unscaledTime - signal.Started;
				float num15 = CueVisual.OnsetScale(signal.Cue, age, settings.LowMotion.Value);
				bool flag7 = SoundField.IsLive(signal, unscaledTime);
				if (signal.Cue == Cue.Music)
				{
					num15 = ((settings.LowMotion.Value || !flag7) ? 1f : (1f + (0.1f + 0.22f * num11) * signal.MusicEnvelope));
				}
				((Transform)((Graphic)marker.Graphic).rectTransform).localScale = Vector3.one * num15;
				((Transform)((Graphic)marker.Graphic).rectTransform).localRotation = Quaternion.Euler(0f, 0f, (signal.Cue == Cue.Music) ? WindingEnvelope.Shake(signal.WindingSeconds, flag7, settings.LowMotion.Value) : 0f);
			}
			for (int k = 0; k < overflow.Count; k++)
			{
				Marker marker2 = overflow[k];
				bool flag8 = settings.ShowDirection.Value && ((Rect)(ref val3)).width > num * 3f && ((Rect)(ref val3)).height > num * 3f && (field.OverflowDirections & (1 << k)) != 0;
				((Component)marker2.Root).gameObject.SetActive(flag8);
				if (flag8)
				{
					Place(marker2, rect, k * 45, 0, num, Mathf.Min(0.88f, settings.RingSize.Value + 0.06f));
					Vector2 anchoredPosition = marker2.Root.anchoredPosition;
					marker2.Root.anchoredPosition = new Vector2(Mathf.Clamp(anchoredPosition.x, ((Rect)(ref val3)).xMin - ((Rect)(ref rect)).center.x + num * 1.5f, ((Rect)(ref val3)).xMax - ((Rect)(ref rect)).center.x - num * 1.5f), Mathf.Clamp(anchoredPosition.y, ((Rect)(ref val3)).yMin - ((Rect)(ref rect)).center.y + num * 1.5f, ((Rect)(ref val3)).yMax - ((Rect)(ref rect)).center.y - num * 1.5f));
					((Component)marker2.Label).gameObject.SetActive(false);
					((Component)marker2.Backing).gameObject.SetActive(false);
					((Graphic)marker2.Graphic).color = SoundMarkerGraphic.Tint(Cue.Gunshot, 0.8f);
					marker2.Graphic.Set(k * 45, Cue.Gunshot, 1, arcOnly: true);
				}
			}
		}

		internal void MeasureUnlocated(Rect safe, float unit)
		{
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			trayCount = 0;
			trayUnit = unit;
			trayGap = unit * 0.35f;
			if ((Object)(object)root == (Object)null || !((Component)root).gameObject.activeSelf)
			{
				return;
			}
			trayWidth = unit * 2.8f;
			for (int i = 0; i < tray.Count; i++)
			{
				Marker marker = tray[i];
				if (((Component)marker.Root).gameObject.activeSelf)
				{
					trayCount++;
					((TMP_Text)marker.Label).enableAutoSizing = false;
					((TMP_Text)marker.Label).fontSize = unit * 0.8f;
					if (marker.TrayText != ((TMP_Text)marker.Label).text || (Object)(object)marker.TrayFont != (Object)(object)((TMP_Text)marker.Label).font || marker.TrayUnit != unit)
					{
						marker.TrayText = ((TMP_Text)marker.Label).text;
						marker.TrayFont = ((TMP_Text)marker.Label).font;
						marker.TrayUnit = unit;
						marker.TrayWidth = -1f;
						marker.NaturalWidth = ((TMP_Text)marker.Label).GetPreferredValues(((TMP_Text)marker.Label).text, float.PositiveInfinity, float.PositiveInfinity).x;
					}
					if (((Component)marker.Label).gameObject.activeSelf)
					{
						trayWidth = Mathf.Max(trayWidth, marker.NaturalWidth + unit * 3.2f);
					}
				}
			}
			trayWidth = Mathf.Min(trayWidth, ((Rect)(ref safe)).width);
			float num = Mathf.Max(1f, trayWidth - unit * 3.2f);
			trayRowHeight = unit * 2.6f;
			for (int j = 0; j < tray.Count; j++)
			{
				Marker marker2 = tray[j];
				if (((Component)marker2.Root).gameObject.activeSelf && ((Component)marker2.Label).gameObject.activeSelf)
				{
					if (marker2.TrayWidth != num)
					{
						marker2.TrayWidth = num;
						marker2.TextHeight = ((TMP_Text)marker2.Label).GetPreferredValues(((TMP_Text)marker2.Label).text, num, float.PositiveInfinity).y;
					}
					trayRowHeight = Mathf.Max(trayRowHeight, Mathf.Min(marker2.TextHeight, unit * 2.4f) + unit * 0.8f);
				}
			}
			if (trayCount > 0)
			{
				trayRowHeight = Mathf.Min(trayRowHeight, Mathf.Max(1f, (((Rect)(ref safe)).height * 0.45f - (float)(trayCount - 1) * trayGap) / (float)trayCount));
			}
		}

		internal void ArrangeUnlocated(Rect safe, float bottom, Vector2 canvasCenter)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: 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_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(((Rect)(ref safe)).yMax, Mathf.Max(((Rect)(ref safe)).yMin, bottom) + UnlocatedHeight);
			int num2 = 0;
			Vector2 val = default(Vector2);
			for (int i = 0; i < tray.Count; i++)
			{
				Marker marker = tray[i];
				if (((Component)marker.Root).gameObject.activeSelf)
				{
					marker.Root.pivot = new Vector2(1f, 0.5f);
					marker.Root.anchoredPosition = new Vector2(((Rect)(ref safe)).xMax, num - trayRowHeight * 0.5f - (float)num2++ * (trayRowHeight + trayGap)) - canvasCenter;
					marker.Root.sizeDelta = new Vector2(trayWidth, trayRowHeight);
					float num3 = Mathf.Min(trayUnit * 2.2f, trayRowHeight * 0.85f);
					RectTransform rectTransform = ((Graphic)marker.Graphic).rectTransform;
					((Vector2)(ref val))..ctor(0f, 0.5f);
					rectTransform.anchorMax = val;
					rectTransform.anchorMin = val;
					rectTransform.anchoredPosition = new Vector2(trayUnit * 0.4f + num3 * 0.5f, 0f);
					rectTransform.sizeDelta = new Vector2(num3, num3);
					RectTransform rectTransform2 = ((TMP_Text)marker.Label).rectTransform;
					((Vector2)(ref val))..ctor(0f, 0.5f);
					rectTransform2.anchorMax = val;
					rectTransform2.anchorMin = val;
					rectTransform2.pivot = new Vector2(0f, 0.5f);
					rectTransform2.anchoredPosition = new Vector2(trayUnit * 2.8f, 0f);
					rectTransform2.sizeDelta = new Vector2(Mathf.Max(1f, trayWidth - trayUnit * 3.2f), Mathf.Max(1f, trayRowHeight - trayUnit * 0.8f));
					((TMP_Text)marker.Label).alignment = (TextAlignmentOptions)514;
					((TMP_Text)marker.Label).overflowMode = (TextOverflowModes)1;
					((TMP_Text)marker.Label).enableAutoSizing = true;
					((TMP_Text)marker.Label).fontSizeMin = trayUnit * 0.55f;
					((TMP_Text)marker.Label).fontSizeMax = trayUnit * 0.8f;
					RectTransform rectTransform3 = ((Graphic)marker.Backing).rectTransform;
					if (((Transform)rectTransform3).GetSiblingIndex() != 0)
					{
						((Transform)rectTransform3).SetAsFirstSibling();
					}
					rectTransform3.anchorMin = Vector2.zero;
					rectTransform3.anchorMax = Vector2.one;
					rectTransform3.pivot = new Vector2(0.5f, 0.5f);
					val = (rectTransform3.offsetMin = (rectTransform3.offsetMax = Vector2.zero));
				}
			}
		}

		private static Vector2 Orbit(float angle, float rx, float ry)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(IndicatorDetail.OrbitX(angle, rx), IndicatorDetail.OrbitY(angle, ry));
		}

		private static void Match(List<Marker> pool, IReadOnlyList<SoundField.Signal> signals)
		{
			for (int i = 0; i < signals.Count && i < pool.Count; i++)
			{
				if (pool[i].Id == signals[i].Id)
				{
					continue;
				}
				for (int j = i + 1; j < pool.Count; j++)
				{
					if (pool[j].Id == signals[i].Id)
					{
						Marker value = pool[i];
						pool[i] = pool[j];
						pool[j] = value;
						break;
					}
				}
			}
		}

		private void Grow(List<Marker> pool, int count, TextMeshProUGUI template, Image imageTemplate, string name)
		{
			int num = Mathf.Min(count, pool.Count + 4);
			while (pool.Count < num)
			{
				pool.Add(Create(template, imageTemplate, name, root));
			}
		}

		private static Marker Create(TextMeshProUGUI template, Image imageTemplate, string name, RectTransform parent)
		{
			//IL_0014: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.SetActive(false);
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			component.anchorMax = val2;
			component.anchorMin = val2;
			GameObject val3 = new GameObject("DirectionAndSound", new Type[1] { typeof(RectTransform) });
			val3.transform.SetParent((Transform)(object)component, false);
			SoundMarkerGraphic soundMarkerGraphic = val3.AddComponent<SoundMarkerGraphic>();
			((Graphic)soundMarkerGraphic).raycastTarget = false;
			((MaskableGraphic)soundMarkerGraphic).maskable = false;
			Image backing = NativeUiTemplates.CloneImage(imageTemplate, (Transform)(object)component, "LabelContrast");
			TextMeshProUGUI val4 = NativeUiTemplates.CloneText(template, (Transform)(object)component, "SoundLabel");
			((TMP_Text)val4).alignment = (TextAlignmentOptions)258;
			return new Marker
			{
				Root = component,
				Graphic = soundMarkerGraphic,
				Label = val4,
				Backing = backing
			};
		}

		private static void Place(Marker marker, Rect rect, float angle, int lane, float unit, float radius)
		{
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: 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_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: 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_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			((Component)marker.Root).gameObject.SetActive(true);
			float num = angle * (MathF.PI / 180f);
			float num2 = Mathf.Max(unit * 3f, ((Rect)(ref rect)).width * 0.5f * radius - (float)lane * unit * 4.8f);
			float num3 = Mathf.Max(unit * 3f, ((Rect)(ref rect)).height * 0.5f * radius - (float)lane * unit * 3.8f);
			float num4 = Mathf.Max(0f, ((Rect)(ref rect)).width * 0.5f - unit * 4.75f - 8f);
			float num5 = (0f - ((Rect)(ref rect)).height) * 0.5f + unit * 4.2f + 8f;
			float num6 = Mathf.Max(num5, ((Rect)(ref rect)).height * 0.5f - unit * 1.5f - 8f);
			marker.Root.anchoredPosition = new Vector2(Mathf.Clamp(Mathf.Sin(num) * num2, 0f - num4, num4), Mathf.Clamp(Mathf.Cos(num) * num3, num5, num6));
			marker.Root.sizeDelta = new Vector2(unit * 9f, unit * 4f);
			((Graphic)marker.Graphic).rectTransform.sizeDelta = new Vector2(unit * 2.8f, unit * 2.8f);
			RectTransform rectTransform = ((Graphic)marker.Graphic).rectTransform;
			RectTransform rectTransform2 = ((Graphic)marker.Graphic).rectTransform;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			rectTransform2.anchorMax = val;
			rectTransform.anchorMin = val;
			((Graphic)marker.Graphic).rectTransform.pivot = new Vector2(0.5f, 0.5f);
			((Graphic)marker.Graphic).rectTransform.anchoredPosition = Vector2.zero;
			RectTransform rectTransform3 = ((TMP_Text)marker.Label).rectTransform;
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			rectTransform3.anchorMax = val;
			rectTransform3.anchorMin = val;
			rectTransform3.pivot = new Vector2(0.5f, 1f);
			rectTransform3.anchoredPosition = new Vector2(0f, (0f - unit) * 1.4f);
			RectTransform rectTransform4 = ((Graphic)marker.Backing).rectTransform;
			val = (rectTransform4.anchorMin = (rectTransform4.anchorMax = rectTransform3.anchorMin));
			rectTransform4.pivot = rectTransform3.pivot;
			rectTransform4.anchoredPosition = rectTransform3.anchoredPosition + new Vector2(0f, unit * 0.15f);
		}

		internal void Hide()
		{
			trayCount = 0;
			if ((Object)(object)root != (Object)null)
			{
				((Component)root).gameObject.SetActive(false);
			}
			previewing = false;
		}

		internal void Clear()
		{
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)root).gameObject);
			}
			root = null;
			markers.Clear();
			tray.Clear();
			overflow.Clear();
			demo.Clear();
			previewing = false;
			firstRealMarker = false;
		}
	}
	[BepInPlugin("Auuueser.Sensus", "Sensus", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "Auuueser.Sensus";

		public const string PluginVersion = "1.0.0";

		private SensusSettings settings;

		private NativeCaptionPresenter presenter;

		private Action<bool>? updateConfigLanguage;

		private bool chinese;

		private int settingsDirty = 1;

		private bool reportedPresentationFailure;

		private bool reportedCaptureFailure;

		private AudioCapture capture;

		private readonly Harmony harmony = new Harmony("Auuueser.Sensus");

		private bool firstFrame = true;

		private bool shuttingDown;

		private long measuredTicks;

		private long worstTicks;

		private int measuredFrames;

		private float reportPerformanceAt;

		private void Awake()
		{
			settings = new SensusSettings(((BaseUnityPlugin)this).Config);
			presenter = new NativeCaptionPresenter(((BaseUnityPlugin)this).Logger);
			capture = new AudioCapture(settings, ((BaseUnityPlugin)this).Logger);
			try
			{
				if (!RuntimeBaseline.Matches())
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Game assembly differs from the audited V81 baseline; sound capture stays disabled. Update the audit before enabling new game versions.");
				}
				else
				{
					PlaybackHooks.Install(harmony, ((BaseUnityPlugin)this).Logger);
					capture.Ready = true;
				}
			}
			catch (Exception arg)
			{
				harmony.UnpatchSelf();
				((BaseUnityPlugin)this).Logger.LogError((object)$"Playback observers were not installed; capture stays disabled: {arg}");
			}
			chinese = LanguagePolicy.UseChinese(settings.Language.Value, Chainloader.PluginInfos.Keys);
			((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
			if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig"))
			{
				try
				{
					updateConfigLanguage = LethalConfigIntegration.Register(settings, chinese);
				}
				catch (Exception arg2)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)$"LethalConfig registration failed; CFG remains available: {arg2}");
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Sensus {0} loaded; language={1}; sound capture ready={2}. V81 creature audio adapters; per-event live validation pending.", "1.0.0", chinese ? "Chinese" : "English", capture.Ready));
			Application.quitting += Shutdown;
			RuntimeFramePump.Install(harmony, this, ((BaseUnityPlugin)this).Logger);
		}

		private void OnSettingChanged(object sender, SettingChangedEventArgs e)
		{
			Interlocked.Exchange(ref settingsDirty, 1);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal void TickFrame()
		{
			if (firstFrame)
			{
				firstFrame = false;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Sensus first frame entered: settingsReady={settings != null}, presenterReady={presenter != null}.");
			}
			if (settings == null || presenter == null)
			{
				return;
			}
			if (Interlocked.Exchange(ref settingsDirty, 0) != 0)
			{
				reportedPresentationFailure = false;
				reportedCaptureFailure = false;
				chinese = LanguagePolicy.UseChinese(settings.Language.Value, Chainloader.PluginInfos.Keys);
				try
				{
					updateConfigLanguage?.Invoke(chinese);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not refresh config labels: " + ex.Message));
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Settings applied: enabled={0}, preview={1}, language={2}, scale={3}, position={4}.", settings.Enabled.Value, settings.Preview.Value, chinese ? "Chinese" : "English", settings.Scale.Value, settings.VerticalPosition.Value));
			}
			long num = (settings.Diagnostics.Value ? Stopwatch.GetTimestamp() : 0);
			if (!reportedCaptureFailure)
			{
				try
				{
					capture.Tick(chinese);
				}
				catch (Exception arg)
				{
					reportedCaptureFailure = true;
					((BaseUnityPlugin)this).Logger.LogError((object)$"Sound capture stopped until a setting changes; UI preview remains available: {arg}");
				}
			}
			if (reportedPresentationFailure)
			{
				return;
			}
			try
			{
				presenter.Tick(settings, chinese, reportedCaptureFailure ? "" : capture.Text, capture.Ready && !reportedCaptureFailure, capture.Field, reportedCaptureFailure ? "" : capture.SpokenText);
			}
			catch (Exception arg2)
			{
				presenter.Clear();
				if (!reportedPresentationFailure)
				{
					reportedPresentationFailure = true;
					((BaseUnityPlugin)this).Logger.LogError((object)$"Caption presentation stopped until a setting changes: {arg2}");
				}
			}
			if (num != 0L)
			{
				long num2 = Stopwatch.GetTimestamp() - num;
				measuredTicks += num2;
				worstTicks = Math.Max(worstTicks, num2);
				measuredFrames++;
				if (Time.unscaledTime >= reportPerformanceAt)
				{
					reportPerformanceAt = Time.unscaledTime + 10f;
					double num3 = 1000.0 / (double)Stopwatch.Frequency;
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Sensus frame work: frames={measuredFrames}, mean={(double)measuredTicks * num3 / (double)measuredFrames:F3}ms, max={(double)worstTicks * num3:F3}ms, registeredSources={AudioRegistry.SourceCount}; excludes native render/audio and playback callbacks.");
					measuredTicks = (worstTicks = 0L);
					measuredFrames = 0;
				}
			}
		}

		private void OnDestroy()
		{
			if (!shuttingDown)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Sensus plugin component destroyed before application quit; preserving sound observers, settings and native UI frame pump.");
			}
		}

		private void Shutdown()
		{
			if (!shuttingDown)
			{
				shuttingDown = true;
				Application.quitting -= Shutdown;
				RuntimeFramePump.Detach(this);
				((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged;
				presenter?.Clear();
				capture?.Dispose();
				harmony.UnpatchSelf();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Sensus runtime shut down on application quit.");
			}
		}
	}
	internal static class RuntimeFramePump
	{
		private static Plugin? owner;

		private static ManualLogSource? log;

		private static int lastFrame = -1;

		private static bool failed;

		internal static void Install(Harmony harmony, Plugin plugin, ManualLogSource logger)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			owner = plugin;
			log = logger;
			lastFrame = -1;
			failed = false;
			HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(RuntimeFramePump), "Pump", (Type[])null, (Type[])null));
			harmony.Patch((MethodBase)AccessTools.Method(typeof(MenuManager), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(HUDManager), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			logger.LogInfo((object)"Sensus frame pump installed on native menu and HUD updates.");
		}

		private static void Pump()
		{
			if (owner == null || log == null || failed || lastFrame == Time.frameCount)
			{
				return;
			}
			lastFrame = Time.frameCount;
			try
			{
				owner.TickFrame();
			}
			catch (Exception arg)
			{
				failed = true;
				log.LogError((object)$"Sensus frame entry failed: {arg}");
			}
		}

		internal static void Detach(Plugin plugin)
		{
			if (owner == plugin)
			{
				owner = null;
				log = null;
			}
		}
	}
	internal sealed class SensusSettings
	{
		internal const string CountHelpEn = "0 = unlimited; positive values set a display limit. Large counts may reduce FPS and readability. Screen space and overload protection still apply; excess events rotate by priority.";

		internal const string CountHelpZh = "0=无上限,正数为显示上限。数量过多可能降低帧率和可读性;仍受屏幕空间与过载保护约束,放不下的事件按优先级轮换。";

		internal const string CountHelp = "0 = unlimited; positive values set a display limit. Large counts may reduce FPS and readability. Screen space and overload protection still apply; excess events rotate by priority. / 0=无上限,正数为显示上限。数量过多可能降低帧率和可读性;仍受屏幕空间与过载保护约束,放不下的事件按优先级轮换。";

		internal ConfigEntry<bool> SpokenSubtitles { get; }

		internal ConfigEntry<bool> Enabled { get; }

		internal ConfigEntry<string> Language { get; }

		internal ConfigEntry<bool> Preview { get; }

		internal ConfigEntry<bool> UnlocatedIndicators { get; }

		internal ConfigEntry<bool> UnlocatedText { get; }

		internal ConfigEntry<float> Scale { get; }

		internal ConfigEntry<bool> BottomAligned { get; }

		internal ConfigEntry<float> VerticalPosition { get; }

		internal ConfigEntry<bool> ShowDirection { get; }

		internal ConfigEntry<float> CaptionDuration { get; }

		internal ConfigEntry<int> MaxCaptions { get; }

		internal ConfigEntry<float> MinimumGain { get; }

		internal ConfigEntry<bool> Diagnostics { get; }

		internal ConfigEntry<float> BackgroundOpacity { get; }

		internal ConfigEntry<bool> ShowBackground { get; }

		internal ConfigEntry<string> DisplayMode { get; }

		internal ConfigEntry<float> RingSize { get; }

		internal ConfigEntry<float> MarkerScale { get; }

		internal ConfigEntry<int> MarkerCount { get; }

		internal ConfigEntry<int> UnlocatedCount { get; }

		internal ConfigEntry<bool> MarkerLabels { get; }

		internal ConfigEntry<bool> LowMotion { get; }

		internal SensusSettings(ConfigFile config)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Expected O, but got Unknown
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Expected O, but got Unknown
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Expected O, but got Unknown
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Expected O, but got Unknown
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Expected O, but got Unknown
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Expected O, but got Unknown
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Expected O, but got Unknown
			SpokenSubtitles = config.Bind<bool>("Dialogue", "Enabled", true, "Timed spoken subtitles, independent of event display mode. With LC Chinese Project loaded, dialogue is managed there; Sensus does not change its settings or claim it is ready. / 音频对白字幕,独立于事件显示模式;安装 LC-Chinese-Project 时交由汉化管理,不修改其设置,也不保证其字幕服务已就绪。");
			DisplayMode = config.Bind<string>("Peripheral", "DisplayMode", "Hybrid", new ConfigDescription("Hybrid: captions and indicators. Captions: subtitles only. Peripheral: indicators only. / Hybrid:字幕与提示;Captions:仅字幕;Peripheral:仅周边提示。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Hybrid", "Captions", "Peripheral" }), Array.Empty<object>()));
			RingSize = config.Bind<float>("Peripheral", "RingSize", 0.65f, new ConfigDescription("Direction marker distance from screen center, as a fraction of half the screen. / 周边标记距中心的范围,占屏幕半径比例。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.45f, 0.82f), Array.Empty<object>()));
			MarkerScale = config.Bind<float>("Peripheral", "MarkerScale", 1f, new ConfigDescription("Size of direction symbols and their labels. / 方向图形与标签大小。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.75f, 1.75f), Array.Empty<object>()));
			MarkerCount = config.Bind<int>("Peripheral", "MaximumMarkers", 10, new ConfigDescription("0 = unlimited; positive values set a display limit. Large counts may reduce FPS and readability. Screen space and overload protection still apply; excess events rotate by priority. / 0=无上限,正数为显示上限。数量过多可能降低帧率和可读性;仍受屏幕空间与过载保护约束,放不下的事件按优先级轮换。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, int.MaxValue), Array.Empty<object>()));
			UnlocatedCount = config.Bind<int>("Peripheral", "MaximumUnlocated", 3, new ConfigDescription("0 = unlimited; positive values set a display limit. Large counts may reduce FPS and readability. Screen space and overload protection still apply; excess events rotate by priority. / 0=无上限,正数为显示上限。数量过多可能降低帧率和可读性;仍受屏幕空间与过载保护约束,放不下的事件按优先级轮换。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, int.MaxValue), Array.Empty<object>()));
			MarkerLabels = config.Bind<bool>("Peripheral", "ShowLabels", true, "Show sound names beside direction symbols. / 在方向图形旁显示声音名称。");
			LowMotion = config.Bind<bool>("Peripheral", "LowMotion", false, "Disable decorative pulses and smooth transitions. / 关闭装饰性扩张与平滑过渡,保留方向变化。");
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable sound captions and preview. / 启用声音字幕与预览。");
			Language = config.Bind<string>("General", "Language", "Auto", new ConfigDescription("Auto detects LC Chinese Project by GUID, independent of version. English / Chinese override it. / Auto 按 GUID 检测汉化,不比较版本;English 强制英文,Chinese 强制中文。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Auto", "English", "Chinese" }), Array.Empty<object>()));
			Preview = config.Bind<bool>("Preview", "ShowPreview", false, "Show a labelled demonstration after closing menus. This is not a detected monster. / 关闭菜单后显示标注为演示的字幕,不代表检测到怪物;测试完请关闭。");
			UnlocatedIndicators = config.Bind<bool>("Peripheral", "ShowUnlocated", false, "Show a fixed tray for genuinely unlocated sounds. Off by default; captions remain available. / 显示无法定位声音的固定提示栏,默认关闭;字幕仍可用。");
			UnlocatedText = config.Bind<bool>("Peripheral", "ShowUnlocatedText", false, "Append Unlocated to names in the fixed tray. Does not enable the tray itself. / 在右下角提示名称后显示“无方向”,默认关闭;不影响提示本身的开关。");
			Scale = config.Bind<float>("Layout", "CaptionScale", 1f, new ConfigDescription("Scale the native text style. / 原生字幕样式缩放。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.75f, 2f), Array.Empty<object>()));
			BottomAligned = config.Bind<bool>("Layout", "BottomAligned", true, "Align bottom and right margins; disable to use manual vertical position. / 底部与右侧等距,关闭后使用手动纵向位置。");
			VerticalPosition = config.Bind<float>("Layout", "VerticalPosition", 0.24f, new ConfigDescription("Vertical screen position: 0 bottom, 1 top. / 屏幕纵向位置:0 底部,1 顶部。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 0.85f), Array.Empty<object>()));
			ShowDirection = config.Bind<bool>("Captions", "ShowDirection", true, "Show coarse directions for spatial sounds. / 为空间声音显示粗略方向。");
			CaptionDuration = config.Bind<float>("Captions", "HoldSeconds", 2.5f, new ConfigDescription("How long to retain a heard event after it becomes inaudible. / 停止听见后保留字幕的秒数。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), Array.Empty<object>()));
			MaxCaptions = config.Bind<int>("Captions", "MaxRows", 5, new ConfigDescription("0 = unlimited; positive values set a display limit. Large counts may reduce FPS and readability. Screen space and overload protection still apply; excess events rotate by priority. / 0=无上限,正数为显示上限。数量过多可能降低帧率和可读性;仍受屏幕空间与过载保护约束,放不下的事件按优先级轮换。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, int.MaxValue), Array.Empty<object>()));
			MinimumGain = config.Bind<float>("Advanced", "MinimumEstimatedGain", 0.015f, new ConfigDescription("Prototype audibility threshold; requires listening calibration. / 原型可感知