Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Sensus v1.0.0
BepInEx/plugins/Auuueser-Sensus/Sensus.dll
Decompiled 5 hours ago
The result has been truncated due to the large size, download it to view full contents!
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. / 原型可感知