Decompiled source of SilksongTrueAim v1.0.3
BepInEx/Plugins/TrueAim/TrueAim.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using HutongGames.PlayMaker; using InControl; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; using UnityExplorer.CacheObject; using UnityExplorer.CacheObject.Views; using UniverseLib.Utility; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("TrueAim")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c6044e4fea45ea190d41ab56f6874704e73c7e81")] [assembly: AssemblyProduct("TrueAim")] [assembly: AssemblyTitle("TrueAim")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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; } } } internal sealed class ConfigurationManagerAttributes { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; } namespace SilksongTrueAim { public enum ZoneType { Horizontal, DiagonalDown, DiagonalUp } public struct ActionZone { public string name; public float startAngle; public float endAngle; public Color color; public ZoneType type; public ActionZone(string n, float start, float end, Color c, ZoneType t) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) name = n; startAngle = start; endAngle = end; color = c; type = t; } public bool ContainsAngle(float angle) { angle = (angle % 360f + 360f) % 360f; if (startAngle <= endAngle) { if (angle >= startAngle) { return angle <= endAngle; } return false; } if (!(angle >= startAngle)) { return angle <= endAngle; } return true; } } public static class EasingCurves { public static float EaseOutExpo(float t, float strength = 10f) { if (t != 1f) { return 1f - Mathf.Pow(2f, (0f - strength) * t); } return 1f; } public static float EaseInExpo(float t, float strength = 10f) { if (t != 0f) { return Mathf.Pow(2f, strength * (t - 1f)); } return 0f; } public static float EaseInOutExpo(float t, float strength = 10f) { if (t == 0f) { return 0f; } if (t == 1f) { return 1f; } if (!(t < 0.5f)) { return (2f - Mathf.Pow(2f, (0f - strength) * (2f * t - 1f))) / 2f; } return Mathf.Pow(2f, strength * (2f * t - 1f)) / 2f; } public static float EaseOutCubic(float t) { return 1f - Mathf.Pow(1f - t, 3f); } public static float EaseInCubic(float t) { return t * t * t; } public static float EaseInOutCubic(float t) { if (!(t < 0.5f)) { return 1f - Mathf.Pow(-2f * t + 2f, 3f) / 2f; } return 4f * t * t * t; } public static float EaseOutQuart(float t) { return 1f - Mathf.Pow(1f - t, 4f); } public static float EaseOutQuint(float t) { return 1f - Mathf.Pow(1f - t, 5f); } public static float EaseOutCirc(float t) { return Mathf.Sqrt(1f - Mathf.Pow(t - 1f, 2f)); } public static float EaseInCirc(float t) { return 1f - Mathf.Sqrt(1f - Mathf.Pow(t, 2f)); } public static float EaseOutBack(float t, float overshoot = 1.70158f) { float num = overshoot + 1f; return 1f + num * Mathf.Pow(t - 1f, 3f) + overshoot * Mathf.Pow(t - 1f, 2f); } public static float EaseInBack(float t, float overshoot = 1.70158f) { return (overshoot + 1f) * t * t * t - overshoot * t * t; } public static float EaseOutElastic(float t, float oscillations = 3f, float springiness = 10f) { if (t == 0f) { return 0f; } if (t == 1f) { return 1f; } float num = (float)Math.PI * 2f / oscillations; return Mathf.Pow(2f, (0f - springiness) * t) * Mathf.Sin((t * 10f - 0.75f) * num) + 1f; } public static float EaseOutSine(float t) { return Mathf.Sin(t * (float)Math.PI / 2f); } public static float EaseInOutSine(float t) { return (0f - (Mathf.Cos((float)Math.PI * t) - 1f)) / 2f; } public static float EaseOutQuad(float t) { return 1f - (1f - t) * (1f - t); } public static float EaseInOutQuad(float t) { if (!(t < 0.5f)) { return 1f - Mathf.Pow(-2f * t + 2f, 2f) / 2f; } return 2f * t * t; } } public class AttackDetector { private TrueAimPlugin plugin; private ManualLogSource? Logger; private FieldInfo? wallSlashingField; private FieldInfo? attackCooldownField; private FieldInfo? nailChargeTimerField; private PlayMakerFSM? nailArtsFSM; private string previousSprintState = ""; private string previousCrestState = ""; private string previousNailArtsState = ""; private bool previousAttacking; private bool wasNailCharging; private Action<float, float, string> onAttackDetected; public PlayMakerFSM? NailArtsFSM => nailArtsFSM; public AttackDetector(ManualLogSource logger, Action<float, float, string> attackCallback, TrueAimPlugin pluginRef) { Logger = logger; onAttackDetected = attackCallback; if ((Object)(object)pluginRef != (Object)null) { plugin = pluginRef; } CacheReflectionFields(); } private void CacheReflectionFields() { try { wallSlashingField = typeof(HeroController).GetField("wallSlashing", BindingFlags.Instance | BindingFlags.NonPublic); attackCooldownField = typeof(HeroController).GetField("attack_cooldown", BindingFlags.Instance | BindingFlags.NonPublic); nailChargeTimerField = typeof(HeroController).GetField("nailChargeTimer", BindingFlags.Instance | BindingFlags.NonPublic); if (wallSlashingField != null && attackCooldownField != null && nailChargeTimerField != null) { ManualLogSource? logger = Logger; if (logger != null) { logger.LogInfo((object)Localization.Get("attack_detection_cached")); } } else { ManualLogSource? logger2 = Logger; if (logger2 != null) { logger2.LogError((object)"Failed to cache some reflection fields"); } } } catch (Exception ex) { ManualLogSource? logger3 = Logger; if (logger3 != null) { logger3.LogError((object)("Reflection cache error: " + ex.Message)); } } } public void Update(HeroController hero, bool effectsEnabled) { if ((Object)(object)hero == (Object)null || !((Component)hero).gameObject.activeInHierarchy) { ManualLogSource? logger = Logger; if (logger != null) { logger.LogWarning((object)"HeroController is null or inactive, skipping update"); } return; } try { if ((Object)(object)nailArtsFSM == (Object)null || !((Component)nailArtsFSM).gameObject.activeInHierarchy) { PlayMakerFSM[] components = ((Component)hero).GetComponents<PlayMakerFSM>(); if (components != null) { nailArtsFSM = Array.Find(components, (PlayMakerFSM fsm) => (Object)(object)fsm != (Object)null && fsm.FsmName == "Nail Arts"); if ((Object)(object)nailArtsFSM != (Object)null) { plugin.VerboseLogger.LogDebug(Localization.Get("found_nail_arts_fsm")); } } } if ((Object)(object)hero.sprintFSM != (Object)null) { MonitorSprintFSM(hero); } if ((Object)(object)hero.crestAttacksFSM != (Object)null) { MonitorCrestFSM(hero); } if ((Object)(object)nailArtsFSM != (Object)null) { MonitorNailArtsFSM(); } DetectCStateAttacks(hero, plugin.AttackEffectToggle); TrackChargeState(hero); } catch (Exception ex) { ManualLogSource? logger2 = Logger; if (logger2 != null) { logger2.LogError((object)("AttackDetector.Update error: " + ex.Message + "\n" + ex.StackTrace)); } } } private void DetectCStateAttacks(HeroController hero, bool effectsEnabled) { bool attacking = hero.cState.attacking; bool upAttacking = hero.cState.upAttacking; bool downAttacking = hero.cState.downAttacking; bool downSpikeAntic = hero.cState.downSpikeAntic; bool isScrewDownAttacking = hero.cState.isScrewDownAttacking; bool parryAttack = hero.cState.parryAttack; bool whipLashing = hero.cState.whipLashing; bool flag = wallSlashingField != null && (bool)wallSlashingField.GetValue(hero); bool isToolThrowing = hero.cState.isToolThrowing; bool flag2 = attacking || upAttacking || downAttacking || downSpikeAntic || isScrewDownAttacking || parryAttack || whipLashing || flag || isToolThrowing; if (flag2 && !previousAttacking) { string text = (parryAttack ? "Parry" : (whipLashing ? "Whip" : (flag ? "Wall" : (downAttacking ? "Down" : (isScrewDownAttacking ? "Screw" : (downSpikeAntic ? "Downspike" : (upAttacking ? "Up" : (isToolThrowing ? "Tool" : "Normal")))))))); plugin.VerboseLogger.LogDebug("\ud83c\udfaf " + text + " attack detected"); if (effectsEnabled) { float arg = 1f; float arg2 = 1f; if (downSpikeAntic || isScrewDownAttacking) { arg = 1.2f; arg2 = 1.2f; } else if (parryAttack) { arg = 1.5f; arg2 = 1.5f; } else if (whipLashing) { arg = 0.9f; arg2 = 0.9f; } else if (isToolThrowing) { arg = 0.8f; arg2 = 0.8f; } onAttackDetected(arg, arg2, text); } } previousAttacking = flag2; } private void MonitorSprintFSM(HeroController hero) { if (!((Object)(object)hero.sprintFSM == (Object)null)) { string activeStateName = hero.sprintFSM.ActiveStateName; if (activeStateName != previousSprintState && !string.IsNullOrEmpty(activeStateName)) { CheckSprintAttackStates(activeStateName); previousSprintState = activeStateName; } } } private void CheckSprintAttackStates(string stateName) { if (!plugin.AttackEffectToggle || stateName == null) { return; } switch (stateName.Length) { case 12: switch (stateName[0]) { case 'A': if (stateName == "Attack Antic") { onAttackDetected(1.4f, 1.4f, "Dash Stab"); } break; case 'R': if (stateName == "Reaper Antic") { onAttackDetected(1.6f, 1.6f, "Reaper Sprint"); } break; } break; case 18: switch (stateName[0]) { case 'W': if (stateName == "Wanderer Attacking") { onAttackDetected(1.4f, 1.4f, "Wanderer Sprint"); } break; case 'D': if (stateName == "Drill Charge Start") { onAttackDetected(1.6f, 1.6f, "Architect Sprint Drill"); } break; } break; case 16: if (stateName == "RecoilStab Antic") { onAttackDetected(1.4f, 1.4f, "Recoil Stab"); } break; case 13: if (stateName == "Warrior Antic") { onAttackDetected(1.6f, 1.6f, "Warrior"); } break; case 15: if (stateName == "Drill Attack Ch") { onAttackDetected(1.8f, 1.8f, "Architect Sprint Drill Charged"); } break; case 11: if (stateName == "Shaman Leap") { onAttackDetected(1.5f, 1.5f, "Shaman Sprint"); } break; case 14: case 17: break; } } private void MonitorCrestFSM(HeroController hero) { if (!((Object)(object)hero.crestAttacksFSM == (Object)null)) { string activeStateName = hero.crestAttacksFSM.ActiveStateName; if (activeStateName != previousCrestState && !string.IsNullOrEmpty(activeStateName)) { CheckCrestAttackStates(activeStateName); previousCrestState = activeStateName; } } } private void CheckCrestAttackStates(string stateName) { if (plugin.AttackEffectToggle) { switch (stateName) { case "SpinBall Antic": onAttackDetected(1.6f, 1.6f, "Beast Crest Spin"); break; case "Rpr Downslash Antic": onAttackDetected(1.6f, 1.6f, "Reaper Downslash"); break; case "Witch Downslash Antic": onAttackDetected(1.5f, 1.5f, "Witch Downslash"); break; case "Shaman Downslash Antic": onAttackDetected(1.5f, 1.5f, "Shaman Downslash"); break; case "ToolM Antic": onAttackDetected(1.6f, 1.6f, "Toolmaster Drill"); break; } } } private void MonitorNailArtsFSM() { if (!((Object)(object)nailArtsFSM == (Object)null)) { string activeStateName = nailArtsFSM.ActiveStateName; if (activeStateName != previousNailArtsState && !string.IsNullOrEmpty(activeStateName)) { plugin.VerboseLogger.LogDebug("⚔\ufe0f Nail Arts: " + previousNailArtsState + " → " + activeStateName); CheckNailArtsStates(activeStateName); previousNailArtsState = activeStateName; } } } private void CheckNailArtsStates(string stateName) { if (!plugin.AttackEffectToggle || stateName == null) { return; } switch (stateName.Length) { case 5: if (stateName == "Antic") { onAttackDetected(1.5f, 1.5f, "Charged Attack"); } break; case 9: if (stateName == "Antic Rpr") { onAttackDetected(1.6f, 1.7f, "Reaper Charged"); } break; case 12: if (stateName == "Wander Antic") { onAttackDetected(1.5f, 1.6f, "Wanderer Charged"); } break; case 14: if (stateName == "Warrior2 Antic") { onAttackDetected(1.5f, 1.6f, "Beast Charged"); } break; case 7: if (stateName == "Do Spin") { onAttackDetected(1.4f, 1.5f, "Witch Spin"); } break; case 11: if (stateName == "Antic Drill") { onAttackDetected(1.5f, 1.6f, "Toolmaster Charged"); } break; case 10: if (stateName == "Antic Wrrr") { onAttackDetected(1.7f, 1.8f, "Warrior Charged"); } break; case 6: case 8: case 13: break; } } private void TrackChargeState(HeroController hero) { bool nailCharging = hero.cState.nailCharging; if (nailCharging && !wasNailCharging) { plugin.VerboseLogger.LogDebug("\ud83d\udd0b Nail charging STARTED"); } else if (!nailCharging && wasNailCharging) { plugin.VerboseLogger.LogDebug("⚡ Nail charge RELEASED"); } wasNailCharging = nailCharging; } public float GetAttackCooldown(HeroController hero) { if (!(attackCooldownField != null)) { return 0.35f; } return (float)attackCooldownField.GetValue(hero); } public float GetChargeTime(HeroController hero) { if (!(nailChargeTimerField != null)) { return 0f; } return (float)nailChargeTimerField.GetValue(hero); } public bool GetWallSlashing(HeroController hero) { if (wallSlashingField != null) { return (bool)wallSlashingField.GetValue(hero); } return false; } } public static class ColorPresets { public struct ZonePalette { public Color Primary; public Color Secondary; public Color Tertiary; public ZonePalette(float r1, float g1, float b1, float r2, float g2, float b2, float r3, float g3, float b3) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Primary = new Color(r1, g1, b1, 1f); Secondary = new Color(r2, g2, b2, 1f); Tertiary = new Color(r3, g3, b3, 1f); } } public static readonly Dictionary<string, ZonePalette> Presets = new Dictionary<string, ZonePalette> { ["Silk (Default)"] = new ZonePalette(1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f), ["Monochrome"] = new ZonePalette(0.8f, 0.8f, 0.8f, 1f, 1f, 1f, 0.6f, 0.6f, 0.6f), ["Ember"] = new ZonePalette(1f, 0.7f, 0.2f, 1f, 0.4f, 0.1f, 1f, 0.85f, 0.5f), ["Bilewater"] = new ZonePalette(0.8f, 1f, 0.2f, 0.6f, 0.85f, 0.2f, 0.9f, 1f, 0.6f), ["Mount Fay"] = new ZonePalette(0.85f, 0.95f, 1f, 0.6f, 0.8f, 0.95f, 0.95f, 0.98f, 1f), ["Abyss"] = new ZonePalette(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f), ["Crimson"] = new ZonePalette(1f, 0.2f, 0.25f, 0.65f, 0.05f, 0.08f, 1f, 0.4f, 0.45f), ["Red Maiden"] = new ZonePalette(0.545f, 0.141f, 0.22f, 0.33f, 0f, 0.14f, 1f, 1f, 1f), ["Ocean"] = new ZonePalette(0f, 0.6f, 0.85f, 0f, 0.35f, 0.65f, 0.3f, 0.8f, 0.9f), ["Jade"] = new ZonePalette(0.2f, 0.7f, 0.4f, 0.15f, 0.5f, 0.3f, 0.5f, 0.85f, 0.6f), ["Teal"] = new ZonePalette(0.2f, 0.9f, 0.8f, 0.15f, 0.65f, 0.6f, 0.5f, 1f, 0.9f), ["Neon"] = new ZonePalette(0f, 1f, 1f, 1f, 0f, 1f, 1f, 1f, 0f), ["Cinderlight"] = new ZonePalette(0.949f, 0.361f, 0.098f, 0.373f, 0.067f, 0.239f, 1f, 0.851f, 0.78f), ["Verdigris"] = new ZonePalette(0.184f, 0.639f, 0.604f, 0.478f, 0.306f, 0.114f, 0.749f, 0.906f, 0.839f), ["Eclipse"] = new ZonePalette(0.043f, 0.043f, 0.078f, 0.765f, 0.58f, 0.133f, 0.29f, 0.435f, 0.682f), ["Wispfire"] = new ZonePalette(0.914f, 0.953f, 1f, 1f, 0.478f, 0.682f, 0.718f, 0.612f, 1f), ["Moth Silk"] = new ZonePalette(0.941f, 0.929f, 0.902f, 0.812f, 0.902f, 0.788f, 0.549f, 0.494f, 0.416f), ["Glassheart"] = new ZonePalette(0.247f, 0.82f, 1f, 1f, 0.357f, 0.541f, 0.682f, 0.878f, 1f), ["Iron Bloom"] = new ZonePalette(0.494f, 0.557f, 0.639f, 0.898f, 0.322f, 0.18f, 1f, 0.82f, 0.329f), ["Shroudglow"] = new ZonePalette(0f, 0.24f, 0.3f, 0.718f, 0.976f, 0.294f, 0.42f, 0.878f, 1f) }; private static readonly Dictionary<string, ZonePalette> SpoilerPresets = new Dictionary<string, ZonePalette> { ["Shade"] = new ZonePalette(0.25f, 0.15f, 0.35f, 0.15f, 0.1f, 0.2f, 0.3f, 0.25f, 0.45f) }; public static string[] GetPresetNames(bool includeSpoilers = false) { List<string> list = Presets.Keys.ToList(); if (includeSpoilers) { list.AddRange(SpoilerPresets.Keys); } return list.ToArray(); } public static ZonePalette GetPreset(string name) { if (Presets.TryGetValue(name, out var value)) { return value; } if (SpoilerPresets.TryGetValue(name, out value)) { return value; } return Presets["Silk (Default)"]; } public static bool PresetExists(string name) { if (!Presets.ContainsKey(name)) { return SpoilerPresets.ContainsKey(name); } return true; } public static bool IsSpoilerPreset(string name) { return SpoilerPresets.ContainsKey(name); } public static string GetLocalizedPresetName(string internalName) { return Localization.Get("preset_" + internalName.ToLower().Replace(" ", "_").Replace("(", "") .Replace(")", "")); } public static string GetInternalPresetName(string localizedName) { foreach (string key in Presets.Keys) { if (GetLocalizedPresetName(key) == localizedName) { return key; } } return localizedName; } } public static class ConfigLocalizedLanguagePilot { private static Vector2 _scrollPos; public static ConfigEntry<Localization.Language> BindLocalizedLanguageDropdown(ConfigFile cfg, string section, string key, Localization.Language defaultLanguage) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown Localization.Language[] allLanguages = Enum.GetValues(typeof(Localization.Language)).Cast<Localization.Language>().ToArray(); return cfg.Bind<Localization.Language>(section, key, defaultLanguage, new ConfigDescription(Localization.Get("config_language"), (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = delegate(ConfigEntryBase entryBase) { Draw(entryBase, allLanguages); } } })); } private static void Draw(ConfigEntryBase entryBase, Localization.Language[] allLanguages) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<Localization.Language> val = (ConfigEntry<Localization.Language>)(object)entryBase; string[] array = allLanguages.Select((Localization.Language lang) => Localization.GetLanguageDisplayName(lang)).ToArray(); int num = Array.IndexOf(allLanguages, val.Value); if (num < 0) { num = 0; } GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.Get("setting_language"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }); _scrollPos = GUILayout.BeginScrollView(_scrollPos, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(120f), GUILayout.Width(280f) }); int num2 = GUILayout.SelectionGrid(num, array, 2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) }); GUILayout.EndScrollView(); GUILayout.EndVertical(); if (num2 != num && num2 >= 0 && num2 < allLanguages.Length) { val.Value = allLanguages[num2]; } } } public static class ConfigLocalizedPresetPilot { private static Vector2 _scrollPos; public static ConfigEntry<string> BindLocalizedPresetDropdown(ConfigFile cfg, string section, string key, string defaultInternalPreset, Func<string[]> getOrderedInternalNames) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown Func<string[]> getOrderedInternalNames2 = getOrderedInternalNames; if (!ColorPresets.PresetExists(defaultInternalPreset)) { defaultInternalPreset = "Silk (Default)"; } return cfg.Bind<string>(section, key, defaultInternalPreset, new ConfigDescription(Localization.Get("config_color_preset"), (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = delegate(ConfigEntryBase entryBase) { Draw(entryBase, getOrderedInternalNames2); } } })); } private static void Draw(ConfigEntryBase entryBase, Func<string[]> getOrderedInternalNames) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<string> val = (ConfigEntry<string>)(object)entryBase; string[] array = getOrderedInternalNames?.Invoke() ?? ColorPresets.GetPresetNames(); string[] array2 = array.Select(ColorPresets.GetLocalizedPresetName).ToArray(); int num = Array.IndexOf(array, val.Value); if (num < 0) { num = 0; } GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.Get("setting_color_preset"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }); _scrollPos = GUILayout.BeginScrollView(_scrollPos, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(140f), GUILayout.Width(280f) }); int num2 = GUILayout.SelectionGrid(num, array2, 2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) }); GUILayout.EndScrollView(); GUILayout.EndVertical(); if (num2 != num && num2 >= 0 && num2 < array.Length) { val.Value = array[num2]; } } } public class DebugOverlay { private ManualLogSource? Logger; private bool showDebugOverlay; private TrueAimPlugin plugin; public DebugOverlay(TrueAimPlugin plugin, ManualLogSource logger) { this.plugin = plugin; Logger = logger; } public void OnGUI() { if (showDebugOverlay) { HeroController instance = HeroController.instance; if (!((Object)(object)instance == (Object)null)) { RenderDebugUI(instance); } } } public void Toggle() { showDebugOverlay = !showDebugOverlay; ManualLogSource? logger = Logger; if (logger != null) { logger.LogInfo((object)(showDebugOverlay ? Localization.Get("debug_overlay_on") : Localization.Get("debug_overlay_off"))); } } public bool IsActive() { return showDebugOverlay; } private void RenderDebugUI(HeroController hero) { //IL_0040: 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_0063: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) float num = 1920f; float num2 = (float)Screen.width / num; num2 = Mathf.Clamp(num2, 0.5f, 2f); GUIStyle val = CreateBoxStyle((int)(16f * num2), (int)(10f * num2)); GUIStyle val2 = CreateLabelStyle((int)(14f * num2), Color.white); GUIStyle headerStyle = CreateHeaderStyle((int)(18f * num2)); GUIStyle stateStyle = new GUIStyle(val2); float num3 = 420f * num2; float num4 = 960f * num2; float num5 = (float)Screen.width - num3 - 10f; float num6 = 10f * num2; int num7 = (int)(num5 + 10f * num2); int num8 = (int)(25f * num2); int sectionGap = (int)(15f * num2); int num9 = (int)(380f * num2); GUI.Box(new Rect(num5, num6, num3, num4), "TRUE AIM DEBUG", val); int y = (int)(num6 + 40f * num2); RenderConfigSection(hero, num7, ref y, num8, sectionGap, num9, headerStyle, val2); RenderHeroStateSection(hero, num7, ref y, num8, sectionGap, num9, headerStyle, val2, stateStyle); RenderEffectsSection(hero, num7, ref y, num8, sectionGap, num9, headerStyle, val2, stateStyle); RenderChargeSection(hero, num7, ref y, num8, sectionGap, num9, headerStyle, val2, stateStyle); RenderControllerSection(hero, num7, ref y, num8, sectionGap, num9, headerStyle, val2); RenderFSMSection(hero, num7, ref y, num8, num9, headerStyle, val2, stateStyle); int num10 = (int)(num6 + num4 - 35f * num2); GUI.Label(new Rect((float)num7, (float)num10, (float)num9, (float)num8), "F11: Toggle | F9: Log FSMs | F12: Scan All", val2); } private void RenderConfigSection(HeroController hero, int leftMargin, ref int y, int lineHeight, int sectionGap, int labelWidth, GUIStyle headerStyle, GUIStyle labelStyle) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "=== CONFIG ===", headerStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Effects Toggle: {plugin.AttackEffectToggle}", labelStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Show Guide: {plugin.ShowInputGuide}", labelStyle); y += lineHeight + sectionGap; } private void RenderHeroStateSection(HeroController hero, int leftMargin, ref int y, int lineHeight, int sectionGap, int labelWidth, GUIStyle headerStyle, GUIStyle labelStyle, GUIStyle stateStyle) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "=== HERO STATE ===", headerStyle); y += lineHeight; stateStyle.normal.textColor = (hero.cState.nailCharging ? Color.yellow : Color.white); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Nail Charging: {hero.cState.nailCharging}", stateStyle); y += lineHeight; stateStyle.normal.textColor = (hero.cState.attacking ? Color.red : Color.white); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Attacking: {hero.cState.attacking}", stateStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Up Attack: {hero.cState.upAttacking}", labelStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Down Attack: {hero.cState.downAttacking}", labelStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Tool Throwing: {hero.cState.isToolThrowing}", labelStyle); y += lineHeight; bool wallSlashing = plugin.GetWallSlashing(hero); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Wall Slashing: {wallSlashing}", labelStyle); y += lineHeight + sectionGap; } private void RenderEffectsSection(HeroController hero, int leftMargin, ref int y, int lineHeight, int sectionGap, int labelWidth, GUIStyle headerStyle, GUIStyle labelStyle, GUIStyle stateStyle) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "=== EFFECTS ===", headerStyle); y += lineHeight; stateStyle.normal.textColor = ((plugin.AttackFlashTimer > 0f) ? Color.green : Color.gray); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Flash Timer: {plugin.AttackFlashTimer:F3}s", stateStyle); y += lineHeight; stateStyle.normal.textColor = ((plugin.AttackCooldownTimer > 0f) ? Color.cyan : Color.gray); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Cooldown Timer: {plugin.AttackCooldownTimer:F3}s", stateStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Flash Multiplier: {plugin.BaseFlashMultiplier:F2}x", labelStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Pulse Multiplier: {plugin.BasePulseMultiplier:F2}x", labelStyle); y += lineHeight + sectionGap; } private void RenderChargeSection(HeroController hero, int leftMargin, ref int y, int lineHeight, int sectionGap, int labelWidth, GUIStyle headerStyle, GUIStyle labelStyle, GUIStyle stateStyle) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "=== CHARGE ===", headerStyle); y += lineHeight; float chargeTime = plugin.GetChargeTime(hero); float nAIL_CHARGE_TIME = hero.NAIL_CHARGE_TIME; float num = Mathf.Clamp01(chargeTime / nAIL_CHARGE_TIME); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Charge Time: {chargeTime:F2}s / {nAIL_CHARGE_TIME:F2}s", labelStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Progress: {num:P0}", labelStyle); y += lineHeight; stateStyle.normal.textColor = ((plugin.ChargeSwellMultiplier > 1.01f) ? Color.magenta : Color.gray); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Swell Multiplier: {plugin.ChargeSwellMultiplier:F2}x", stateStyle); y += lineHeight + sectionGap; } private void RenderControllerSection(HeroController hero, int leftMargin, ref int y, int lineHeight, int sectionGap, int labelWidth, GUIStyle headerStyle, GUIStyle labelStyle) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "=== CONTROLLER ===", headerStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), $"Actor: {hero.hero_state}", labelStyle); y += lineHeight; GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "Flags: " + GetCStateDescription(hero.cState), labelStyle); y += lineHeight + sectionGap; } private void RenderFSMSection(HeroController hero, int leftMargin, ref int y, int lineHeight, int labelWidth, GUIStyle headerStyle, GUIStyle labelStyle, GUIStyle stateStyle) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "=== FSM ===", headerStyle); y += lineHeight; if ((Object)(object)hero.sprintFSM != (Object)null) { stateStyle.normal.textColor = ((hero.sprintFSM.ActiveStateName == "Attack Antic") ? Color.red : Color.white); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "Sprint: " + hero.sprintFSM.ActiveStateName, stateStyle); y += lineHeight; } if ((Object)(object)hero.crestAttacksFSM != (Object)null) { stateStyle.normal.textColor = (hero.crestAttacksFSM.ActiveStateName.Contains("Antic") ? Color.red : Color.white); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "Crest: " + hero.crestAttacksFSM.ActiveStateName, stateStyle); y += lineHeight; } if ((Object)(object)hero.toolsFSM != (Object)null) { stateStyle.normal.textColor = ((hero.toolsFSM.ActiveStateName != "Idle") ? Color.cyan : Color.white); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "Tools: " + hero.toolsFSM.ActiveStateName, stateStyle); y += lineHeight; } if ((Object)(object)plugin.NailArtsFSM != (Object)null) { stateStyle.normal.textColor = ((plugin.NailArtsFSM.ActiveStateName != "Inactive") ? Color.magenta : Color.white); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "NailArts: " + plugin.NailArtsFSM.ActiveStateName, stateStyle); y += lineHeight; } if ((Object)(object)hero.superJumpFSM != (Object)null) { stateStyle.normal.textColor = ((hero.superJumpFSM.ActiveStateName != "Idle" && hero.superJumpFSM.ActiveStateName != "Inactive") ? Color.green : Color.white); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "SuperJump: " + hero.superJumpFSM.ActiveStateName, stateStyle); y += lineHeight; } if ((Object)(object)hero.wallScrambleFSM != (Object)null) { stateStyle.normal.textColor = ((hero.wallScrambleFSM.ActiveStateName != "Idle") ? Color.yellow : Color.white); GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "WallScramble: " + hero.wallScrambleFSM.ActiveStateName, stateStyle); y += lineHeight; } if ((Object)(object)hero.harpoonDashFSM != (Object)null) { GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "Harpoon: " + hero.harpoonDashFSM.ActiveStateName, labelStyle); y += lineHeight; } if ((Object)(object)hero.bellBindFSM != (Object)null) { GUI.Label(new Rect((float)leftMargin, (float)y, (float)labelWidth, (float)lineHeight), "Bell: " + hero.bellBindFSM.ActiveStateName, labelStyle); y += lineHeight; } } private string GetCStateDescription(HeroControllerStates cState) { List<string> list = new List<string>(); if (cState.onGround) { list.Add("Ground"); } if (cState.jumping) { list.Add("Jump"); } if (cState.falling) { list.Add("Fall"); } if (cState.dashing) { list.Add("Dash"); } if (cState.wallSliding) { list.Add("WallSlide"); } if (cState.wallClinging) { list.Add("WallCling"); } if (cState.attacking) { list.Add("Attack"); } if (cState.upAttacking) { list.Add("UpAtk"); } if (cState.downAttacking) { list.Add("DownAtk"); } if (cState.nailCharging) { list.Add("Charge"); } if (cState.invulnerable) { list.Add("Invuln"); } if (cState.recoiling) { list.Add("Recoil"); } if (cState.parrying) { list.Add("Parry"); } if (list.Count <= 0) { return "None"; } return string.Join(", ", list); } private GUIStyle CreateBoxStyle(int fontSize, int padding) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0036: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.box) { fontSize = fontSize }; val.normal.textColor = Color.white; val.padding = new RectOffset(padding, padding, padding, padding); return val; } private GUIStyle CreateLabelStyle(int fontSize, Color color) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = fontSize }; val.normal.textColor = color; return val; } private GUIStyle CreateHeaderStyle(int fontSize) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = fontSize, fontStyle = (FontStyle)1 }; val.normal.textColor = Color.yellow; return val; } } public class GameplayHandler { private ManualLogSource? Logger; private TrueAimPlugin plugin; private string lastKnownCrestID = ""; private bool lastKnownLongclawEquipped; private float cachedRadius = 2.5f; private Type? gameplayType; private PropertyInfo? longNeedleToolProperty; private PropertyInfo? longNeedleMultiplierProperty; private bool hasTriedReflectionSetup; private static readonly Dictionary<string, float> CrestRadiusMap = new Dictionary<string, float> { { "Hunter", 2.95f }, { "Reaper", 3.75f }, { "Wanderer", 3.1f }, { "Warrior", 3.2f }, { "Witch", 4f }, { "Toolmaster", 4.1f }, { "Spell", 5.6f } }; public GameplayHandler(ManualLogSource logger, TrueAimPlugin pluginRef) { Logger = logger; plugin = pluginRef; } private void EnsureReflectionSetup() { if (hasTriedReflectionSetup) { return; } hasTriedReflectionSetup = true; try { gameplayType = Type.GetType("GlobalSettings.Gameplay, Assembly-CSharp"); if (gameplayType != null) { longNeedleToolProperty = gameplayType.GetProperty("LongNeedleTool", BindingFlags.Static | BindingFlags.Public); longNeedleMultiplierProperty = gameplayType.GetProperty("LongNeedleMultiplier", BindingFlags.Static | BindingFlags.Public); if (longNeedleToolProperty != null) { ManualLogSource? logger = Logger; if (logger != null) { logger.LogInfo((object)"✅ Longclaw detection initialized"); } } } else { ManualLogSource? logger2 = Logger; if (logger2 != null) { logger2.LogWarning((object)"⚠\ufe0f GlobalSettings.Gameplay not found"); } } } catch (Exception ex) { ManualLogSource? logger3 = Logger; if (logger3 != null) { logger3.LogError((object)("Reflection setup failed: " + ex.Message)); } } } private bool IsLongclawEquipped(HeroController hero) { if ((Object)(object)hero == (Object)null) { return false; } EnsureReflectionSetup(); if (longNeedleToolProperty == null) { return false; } try { object value = longNeedleToolProperty.GetValue(null); if (value == null) { return false; } PropertyInfo property = value.GetType().GetProperty("IsEquipped"); if (property == null) { return false; } return (bool)property.GetValue(value); } catch { return false; } } private float GetLongNeedleMultiplier() { //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_002a: Unknown result type (might be due to invalid IL or missing references) if (longNeedleMultiplierProperty != null) { try { object value = longNeedleMultiplierProperty.GetValue(null); if (value is Vector2) { Vector2 val = (Vector2)value; return val.x; } } catch { } } return 1.25f; } private void UpdateCachedRadius(string crestID, bool hasLongNeedle) { string text = crestID.Split(new char[1] { '_' })[0]; float value; float num = (CrestRadiusMap.TryGetValue(text, out value) ? value : 2.5f); if (hasLongNeedle) { float longNeedleMultiplier = GetLongNeedleMultiplier(); cachedRadius = num * longNeedleMultiplier; ManualLogSource? logger = Logger; if (logger != null) { logger.LogInfo((object)$"\ud83d\udccf {text} + Longclaw: {cachedRadius:F2} (base={num:F2}, mult={longNeedleMultiplier:F2})"); } } else { cachedRadius = num; ManualLogSource? logger2 = Logger; if (logger2 != null) { logger2.LogInfo((object)$"\ud83d\udccf {text}: {cachedRadius:F2}"); } } } public bool TryGetUpdatedRadius(HeroController hero, out float newRadius) { if ((Object)(object)hero == (Object)null || hero.playerData == null) { newRadius = cachedRadius; return false; } string currentCrestID = hero.playerData.CurrentCrestID; bool flag = IsLongclawEquipped(hero); if (currentCrestID != lastKnownCrestID || flag != lastKnownLongclawEquipped) { ManualLogSource? logger = Logger; if (logger != null) { logger.LogInfo((object)("⚔\ufe0f Loadout: " + currentCrestID + (flag ? " + Longclaw" : ""))); } UpdateCachedRadius(currentCrestID, flag); lastKnownCrestID = currentCrestID; lastKnownLongclawEquipped = flag; newRadius = cachedRadius; return true; } newRadius = cachedRadius; return false; } public void ForceRefresh(HeroController hero) { lastKnownCrestID = ""; lastKnownLongclawEquipped = false; TryGetUpdatedRadius(hero, out var _); } private bool IsHunterCrestEquipped() { HeroController instance = HeroController.instance; if ((Object)(object)instance == (Object)null || instance.playerData == null) { return false; } string currentCrestID = instance.playerData.CurrentCrestID; if (!(currentCrestID == "Hunter") && !(currentCrestID == "Hunter_v2")) { return currentCrestID == "Hunter_v3"; } return true; } } public class HaloRenderer { private GameObject haloObject; private LineRenderer indicatorRenderer; private GameObject arrowheadObject; private MeshRenderer arrowheadRenderer; private MeshFilter arrowheadFilter; private List<LineRenderer> segmentBaseRenderers = new List<LineRenderer>(); private List<LineRenderer> segmentFillRenderers = new List<LineRenderer>(); private static Material? _sharedSpriteMat; private float radius; private List<ActionZone> zones = new List<ActionZone>(); private bool isAnimating; private float animationProgress = 1f; private bool targetVisible = true; private const float ANIMATION_DURATION = 0.25f; private const float SHRINK_SCALE = 0.6f; private float currentActiveOpacity = 1f; public bool IsCreated { get { if ((Object)(object)haloObject != (Object)null && segmentBaseRenderers != null && segmentBaseRenderers.Count > 0 && segmentFillRenderers != null && segmentFillRenderers.Count > 0) { return (Object)(object)indicatorRenderer != (Object)null; } return false; } } public void Create(float haloRadius, List<ActionZone> actionZones) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)haloObject != (Object)null)) { radius = haloRadius; zones = actionZones; haloObject = new GameObject("TrueAimHalo"); Object.DontDestroyOnLoad((Object)(object)haloObject); haloObject.layer = LayerMask.NameToLayer("UI"); haloObject.transform.localScale = Vector3.one; CreateSegments(actionZones); CreateIndicator(); } } private void CreateSegments(List<ActionZone> zones) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) foreach (ActionZone zone in zones) { GameObject val = new GameObject("Segment_" + zone.name + "_Base"); val.transform.SetParent(haloObject.transform); LineRenderer val2 = val.AddComponent<LineRenderer>(); val2.useWorldSpace = false; val2.alignment = (LineAlignment)0; SetupLineRenderer(val2, zone.color, 0.08f); DrawArc(val2, zone.startAngle, zone.endAngle, radius); segmentBaseRenderers.Add(val2); GameObject val3 = new GameObject("Segment_" + zone.name + "_Fill"); val3.transform.SetParent(haloObject.transform); LineRenderer val4 = val3.AddComponent<LineRenderer>(); val4.useWorldSpace = false; val4.alignment = (LineAlignment)0; SetupLineRenderer(val4, zone.color, 0.2f); ((Renderer)val4).enabled = false; segmentFillRenderers.Add(val4); } } private void CreateIndicator() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("InputIndicator"); val.transform.SetParent(haloObject.transform); indicatorRenderer = val.AddComponent<LineRenderer>(); SetupLineRenderer(indicatorRenderer, Color.white, 0.08f); indicatorRenderer.positionCount = 2; ((Renderer)indicatorRenderer).enabled = false; indicatorRenderer.startWidth = 0.08f; indicatorRenderer.endWidth = 0.08f; arrowheadObject = new GameObject("Arrowhead"); arrowheadObject.transform.SetParent(haloObject.transform); arrowheadFilter = arrowheadObject.AddComponent<MeshFilter>(); arrowheadRenderer = arrowheadObject.AddComponent<MeshRenderer>(); ((Renderer)arrowheadRenderer).material = (Material)(((object)_sharedSpriteMat) ?? ((object)new Material(Shader.Find("Sprites/Default")))); ((Renderer)arrowheadRenderer).sortingOrder = 32767; CreateArrowheadMesh(); arrowheadObject.SetActive(false); } private void CreateArrowheadMesh() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0025: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) Mesh val = new Mesh(); float num = 0.2f; float num2 = 0.2f; Vector3[] vertices = (Vector3[])(object)new Vector3[3] { new Vector3(num, 0f, 0f), new Vector3(0f, num2 / 2f, 0f), new Vector3(0f, (0f - num2) / 2f, 0f) }; int[] triangles = new int[3] { 0, 1, 2 }; Vector2[] uv = (Vector2[])(object)new Vector2[3] { new Vector2(1f, 0.5f), new Vector2(0f, 1f), new Vector2(0f, 0f) }; val.vertices = vertices; val.triangles = triangles; val.uv = uv; val.RecalculateNormals(); arrowheadFilter.mesh = val; } public void UpdateRadius(float newRadius) { if (!IsCreated || Mathf.Abs(radius - newRadius) < 0.01f) { return; } radius = newRadius; for (int i = 0; i < segmentBaseRenderers.Count && i < zones.Count; i++) { if ((Object)(object)segmentBaseRenderers[i] != (Object)null) { DrawArc(segmentBaseRenderers[i], zones[i].startAngle, zones[i].endAngle, radius); } } } public void UpdatePosition(Vector3 position) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)haloObject != (Object)null) { haloObject.transform.position = new Vector3(position.x, position.y, -0.1f); } if (isAnimating) { UpdateAnimation(); } } public void UpdateSegmentHighlights(int activeSegment, List<ActionZone> zones, float activeOpacity, float inactiveOpacity, float flashIntensity, float fillProgress, float pulseIntensity, float swellMultiplier = 1f) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) currentActiveOpacity = activeOpacity; for (int i = 0; i < segmentBaseRenderers.Count && i < zones.Count; i++) { LineRenderer val = segmentBaseRenderers[i]; LineRenderer val2 = segmentFillRenderers[i]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { continue; } Color color = zones[i].color; if (i == activeSegment) { ((Renderer)val).enabled = true; Color val3 = color * 1.2f; val3.a = activeOpacity; if (flashIntensity > 0f) { val3 = Color.Lerp(val3, Color.white, flashIntensity * 0.6f); } float num = pulseIntensity * 0.3f; DrawArc(val, zones[i].startAngle, zones[i].endAngle, radius + num); val.startColor = val3; val.endColor = val3; ((Renderer)val2).enabled = true; Color val4 = color; val4.a = activeOpacity * 0.4f; if (flashIntensity > 0f) { val4 = Color.Lerp(val4, Color.white, flashIntensity * 0.6f); } if (fillProgress >= 0.99f) { val4.a = activeOpacity; } float num2 = 0.2f + pulseIntensity * 0.15f; num2 = (val2.startWidth = num2 * swellMultiplier); val2.endWidth = num2; float num4 = 0.14f + pulseIntensity * 0.3f; num4 *= swellMultiplier; DrawPartialArcOffset(val2, zones[i], fillProgress, num4); val2.startColor = val4; val2.endColor = val4; } else { ((Renderer)val).enabled = true; color.a = inactiveOpacity; DrawArc(val, zones[i].startAngle, zones[i].endAngle, radius); val.startColor = color; val.endColor = color; ((Renderer)val2).enabled = false; } } } public void UpdateIndicator(Vector2 input, int activeSegment, List<ActionZone> zones, float currentRadius, float startOffset, float activeOpacity) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)indicatorRenderer == (Object)null) && !((Object)(object)arrowheadObject == (Object)null)) { if (((Vector2)(ref input)).magnitude > 0.1f) { ((Renderer)indicatorRenderer).enabled = true; arrowheadObject.SetActive(true); float num = Mathf.Atan2(input.y, input.x); float num2 = num * 57.29578f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Cos(num) * currentRadius * startOffset, Mathf.Sin(num) * currentRadius * startOffset, 0f); float num3 = currentRadius - 0.32f; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Mathf.Cos(num) * num3, Mathf.Sin(num) * num3, 0f); indicatorRenderer.SetPosition(0, val); indicatorRenderer.SetPosition(1, val2); Vector3 localPosition = default(Vector3); ((Vector3)(ref localPosition))..ctor(Mathf.Cos(num) * (currentRadius - 0.28f), Mathf.Sin(num) * (currentRadius - 0.28f), 0f); arrowheadObject.transform.localPosition = localPosition; arrowheadObject.transform.localRotation = Quaternion.Euler(0f, 0f, num2); Color startColor; Color val3 = (startColor = ((activeSegment >= 0 && activeSegment < zones.Count) ? zones[activeSegment].color : Color.white)); startColor.a = activeOpacity * 0.3f; Color endColor = val3; endColor.a = activeOpacity; indicatorRenderer.startColor = startColor; indicatorRenderer.endColor = endColor; Color color = val3; color.a = activeOpacity; ((Renderer)arrowheadRenderer).material.color = color; } else { ((Renderer)indicatorRenderer).enabled = false; arrowheadObject.SetActive(false); } } } public void SetActive(bool active, bool animated = false) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)haloObject == (Object)null) { return; } targetVisible = active; if (animated) { isAnimating = true; if (active) { haloObject.SetActive(true); animationProgress = 0f; haloObject.transform.localScale = Vector3.one * 0.6f; ApplyGlobalAlpha(0f); } else { animationProgress = 1f; haloObject.transform.localScale = Vector3.one; } } else { isAnimating = false; animationProgress = (active ? 1f : 0f); haloObject.SetActive(active); haloObject.transform.localScale = Vector3.one; if (active) { ApplyGlobalAlpha(1f); } } } public void ResetAnimationState() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) isAnimating = false; animationProgress = (targetVisible ? 1f : 0f); if ((Object)(object)haloObject != (Object)null) { haloObject.SetActive(targetVisible); haloObject.transform.localScale = Vector3.one; if (targetVisible) { ApplyGlobalAlpha(1f); } } } public void Destroy() { if ((Object)(object)haloObject != (Object)null) { Object.Destroy((Object)(object)haloObject); haloObject = null; indicatorRenderer = null; arrowheadObject = null; arrowheadRenderer = null; arrowheadFilter = null; segmentBaseRenderers?.Clear(); segmentFillRenderers?.Clear(); if ((Object)(object)_sharedSpriteMat != (Object)null) { Object.Destroy((Object)(object)_sharedSpriteMat); _sharedSpriteMat = null; } } } public bool IsAnimating() { return isAnimating; } private void UpdateAnimation() { if (targetVisible) { animationProgress += Time.deltaTime / 0.25f; if (animationProgress >= 1f) { animationProgress = 1f; isAnimating = false; } } else { animationProgress -= Time.deltaTime / 0.25f; if (animationProgress <= 0f) { animationProgress = 0f; isAnimating = false; if ((Object)(object)haloObject != (Object)null) { haloObject.SetActive(false); } } } float num = EasingCurves.EaseOutExpo(animationProgress); ApplyGlobalAlpha(num); ApplyGlobalScale(num); } private void ApplyGlobalAlpha(float multiplier) { //IL_001b: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < segmentBaseRenderers.Count; i++) { LineRenderer val = segmentBaseRenderers[i]; if (!((Object)(object)val == (Object)null)) { Color startColor = val.startColor; startColor.a *= multiplier; val.startColor = startColor; val.endColor = startColor; } } for (int j = 0; j < segmentFillRenderers.Count; j++) { LineRenderer val2 = segmentFillRenderers[j]; if (!((Object)(object)val2 == (Object)null)) { Color startColor2 = val2.startColor; startColor2.a *= multiplier; val2.startColor = startColor2; val2.endColor = startColor2; } } if ((Object)(object)indicatorRenderer != (Object)null && ((Renderer)indicatorRenderer).enabled) { Color startColor3 = indicatorRenderer.startColor; Color endColor = indicatorRenderer.endColor; startColor3.a *= multiplier; endColor.a *= multiplier; indicatorRenderer.startColor = startColor3; indicatorRenderer.endColor = endColor; } if ((Object)(object)arrowheadRenderer != (Object)null && arrowheadObject.activeSelf) { Color color = ((Renderer)arrowheadRenderer).material.color; color.a *= multiplier; ((Renderer)arrowheadRenderer).material.color = color; } } private void ApplyGlobalScale(float easedProgress) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)haloObject != (Object)null) { float num = ((!targetVisible) ? Mathf.Lerp(0.6f, 1f, easedProgress) : Mathf.Lerp(0.6f, 1f, easedProgress)); haloObject.transform.localScale = Vector3.one * num; } } private void SetupLineRenderer(LineRenderer lr, Color color, float width) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if ((Object)(object)_sharedSpriteMat == (Object)null) { _sharedSpriteMat = new Material(Shader.Find("Sprites/Default")) { hideFlags = (HideFlags)32 }; } ((Renderer)lr).material = _sharedSpriteMat; lr.startColor = color; lr.endColor = color; lr.startWidth = width; lr.endWidth = width; lr.useWorldSpace = false; ((Renderer)lr).sortingOrder = 32767; } private void DrawCircle(LineRenderer lr, float circleRadius) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) int num = 64; lr.positionCount = num + 1; for (int i = 0; i <= num; i++) { float num2 = (float)i / (float)num * 2f * (float)Math.PI; lr.SetPosition(i, new Vector3(Mathf.Cos(num2) * circleRadius, Mathf.Sin(num2) * circleRadius, 0f)); } } private void DrawArc(LineRenderer lr, float startAngle, float endAngle, float arcRadius) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) startAngle = (startAngle % 360f + 360f) % 360f; endAngle = (endAngle % 360f + 360f) % 360f; float num = ((startAngle <= endAngle) ? (endAngle - startAngle) : (360f - startAngle + endAngle)); int num2 = Mathf.Max(64, (int)(num / 1f)); lr.positionCount = num2 + 1; for (int i = 0; i <= num2; i++) { float num3 = (float)i / (float)num2; float num4 = (startAngle + num * num3) * ((float)Math.PI / 180f); lr.SetPosition(i, new Vector3(Mathf.Cos(num4) * arcRadius, Mathf.Sin(num4) * arcRadius, 0f)); } } private void DrawPartialArcOffset(LineRenderer lr, ActionZone zone, float fillProgress, float radiusOffset) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) float num = (zone.startAngle % 360f + 360f) % 360f; float num2 = (zone.endAngle % 360f + 360f) % 360f; float num3 = ((num <= num2) ? (num2 - num) : (360f - num + num2)); float num4 = num + num3 / 2f; float num5 = num3 / 2f * fillProgress; float num6 = num4 - num5; float num7 = num4 + num5; int num8 = Mathf.Max(32, (int)(num3 * fillProgress / 1f)); lr.positionCount = num8 + 1; float num9 = radius + radiusOffset; for (int i = 0; i <= num8; i++) { float num10 = (float)i / (float)num8; float num11 = Mathf.Lerp(num6, num7, num10) * ((float)Math.PI / 180f); lr.SetPosition(i, new Vector3(Mathf.Cos(num11) * num9, Mathf.Sin(num11) * num9, 0f)); } } public bool IsActive() { if ((Object)(object)haloObject != (Object)null) { return haloObject.activeSelf; } return false; } public void DebugState() { Debug.Log((object)$"Halo State: Created={IsCreated}, Active={IsActive()}, Animating={isAnimating}, Progress={animationProgress}, TargetVisible={targetVisible}"); } public void DebugAnimationState() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)haloObject == (Object)null) { Debug.Log((object)"HaloObject is null"); return; } Debug.Log((object)("Animation State: " + $"Active: {haloObject.activeSelf}, " + $"Animating: {isAnimating}, " + $"Progress: {animationProgress:F2}, " + $"TargetVisible: {targetVisible}, " + $"Scale: {haloObject.transform.localScale}")); } } [BepInPlugin("com.trueaim.silksong", "Silksong True Aim", "1.0.2")] public static class Localization { public enum Language { English, SimplifiedChinese, Japanese, Korean, Spanish, French, German, Russian } private static Language currentLanguage = Language.English; private static readonly Dictionary<string, Dictionary<Language, string>> strings = new Dictionary<string, Dictionary<Language, string>> { ["plugin_loaded"] = new Dictionary<Language, string> { [Language.English] = "Plugin {0} loaded!", [Language.SimplifiedChinese] = "插件 {0} 已加载!", [Language.Japanese] = "プラグイン {0} をロードしました!", [Language.Korean] = "플러그인 {0} 로드 완료!", [Language.Spanish] = "¡Plugin {0} cargado!", [Language.French] = "Plugin {0} chargé !", [Language.German] = "Plugin {0} geladen!", [Language.Russian] = "Плагин {0} загружен!" }, ["press_key_toggle"] = new Dictionary<Language, string> { [Language.English] = "Press {0} to toggle True Aim", [Language.SimplifiedChinese] = "按 {0} 切换真准", [Language.Japanese] = "{0} を押してTrue Aimを切り替え", [Language.Korean] = "{0} 키로 True Aim 전환", [Language.Spanish] = "Pulsa {0} para activar/desactivar True Aim", [Language.French] = "Appuyez sur {0} pour activer/désactiver True Aim", [Language.German] = "Drücke {0} um True Aim umzuschalten", [Language.Russian] = "Нажмите {0} для переключения True Aim" }, ["category_general"] = new Dictionary<Language, string> { [Language.English] = "General", [Language.SimplifiedChinese] = "常规", [Language.Japanese] = "一般", [Language.Korean] = "일반", [Language.Spanish] = "General", [Language.French] = "Général", [Language.German] = "Allgemein", [Language.Russian] = "Общие" }, ["category_visual"] = new Dictionary<Language, string> { [Language.English] = "Visual", [Language.SimplifiedChinese] = "视觉效果", [Language.Japanese] = "ビジュアル", [Language.Korean] = "시각 효과", [Language.Spanish] = "Visual", [Language.French] = "Visuel", [Language.German] = "Visuell", [Language.Russian] = "Визуальные" }, ["category_controls"] = new Dictionary<Language, string> { [Language.English] = "Controls", [Language.SimplifiedChinese] = "控制", [Language.Japanese] = "操作", [Language.Korean] = "조작", [Language.Spanish] = "Controles", [Language.French] = "Contrôles", [Language.German] = "Steuerung", [Language.Russian] = "Управление" }, ["category_gameplay"] = new Dictionary<Language, string> { [Language.English] = "Gameplay", [Language.SimplifiedChinese] = "游戏性", [Language.Japanese] = "ゲームプレイ", [Language.Korean] = "게임플레이", [Language.Spanish] = "Jugabilidad", [Language.French] = "Gameplay", [Language.German] = "Gameplay", [Language.Russian] = "Геймплей" }, ["category_colors"] = new Dictionary<Language, string> { [Language.English] = "Colors", [Language.SimplifiedChinese] = "颜色自定义", [Language.Japanese] = "色設定", [Language.Korean] = "색상 커스터마이징", [Language.Spanish] = "Colores", [Language.French] = "Couleurs", [Language.German] = "Farben", [Language.Russian] = "Цвета" }, ["category_debug"] = new Dictionary<Language, string> { [Language.English] = "Debug", [Language.SimplifiedChinese] = "调试", [Language.Japanese] = "デバッグ", [Language.Korean] = "디버그", [Language.Spanish] = "Depuración", [Language.French] = "Débogage", [Language.German] = "Debug", [Language.Russian] = "Отладка" }, ["setting_language"] = new Dictionary<Language, string> { [Language.English] = "Language", [Language.SimplifiedChinese] = "语言选项", [Language.Japanese] = "言語", [Language.Korean] = "언어 설정", [Language.Spanish] = "Idioma", [Language.French] = "Langue", [Language.German] = "Sprache", [Language.Russian] = "Язык" }, ["setting_show_guide"] = new Dictionary<Language, string> { [Language.English] = "Show Input Guide Toggle", [Language.SimplifiedChinese] = "显示输入指引开关", [Language.Japanese] = "入力ガイド表示切替", [Language.Korean] = "입력 가이드 표시 토글", [Language.Spanish] = "Mostrar Guía de Entrada", [Language.French] = "Afficher le Guide d'Entrée", [Language.German] = "Eingabehilfe Anzeigen", [Language.Russian] = "Показать Гид Ввода" }, ["setting_halo_radius"] = new Dictionary<Language, string> { [Language.English] = "Halo Radius", [Language.SimplifiedChinese] = "光环半径", [Language.Japanese] = "ハロー半径", [Language.Korean] = "후광 반경", [Language.Spanish] = "Radio del Halo", [Language.French] = "Rayon du Halo", [Language.German] = "Halo-Radius", [Language.Russian] = "Радиус Ореола" }, ["setting_active_opacity"] = new Dictionary<Language, string> { [Language.English] = "Active Zone Opacity", [Language.SimplifiedChinese] = "激活区域不透明度", [Language.Japanese] = "アクティブゾーン不透明度", [Language.Korean] = "활성 구역 불투명도", [Language.Spanish] = "Opacidad de Zona Activa", [Language.French] = "Opacité de Zone Active", [Language.German] = "Aktive Zonen-Deckkraft", [Language.Russian] = "Непрозрачность Активной Зоны" }, ["setting_inactive_opacity"] = new Dictionary<Language, string> { [Language.English] = "Inactive Zone Opacity", [Language.SimplifiedChinese] = "未激活区域不透明度", [Language.Japanese] = "非アクティブゾーン不透明度", [Language.Korean] = "비활성 구역 불투명도", [Language.Spanish] = "Opacidad de Zona Inactiva", [Language.French] = "Opacité de Zone Inactive", [Language.German] = "Inaktive Zonen-Deckkraft", [Language.Russian] = "Непрозрачность Неактивной Зоны" }, ["setting_indicator_offset"] = new Dictionary<Language, string> { [Language.English] = "Indicator Start Offset", [Language.SimplifiedChinese] = "指示器起始偏移值", [Language.Japanese] = "インジケーター開始オフセット", [Language.Korean] = "표시기 시작 오프셋", [Language.Spanish] = "Desplazamiento del Indicador", [Language.French] = "Décalage de l'Indicateur", [Language.German] = "Indikator-Startversatz", [Language.Russian] = "Смещение Индикатора" }, ["setting_adaptive_halo"] = new Dictionary<Language, string> { [Language.English] = "Adaptive Halo Radius Toggle", [Language.SimplifiedChinese] = "自适应光环半径开关", [Language.Japanese] = "適応ハロー半径切替", [Language.Korean] = "적응형 후광 반경 토글", [Language.Spanish] = "Radio de Halo Adaptativo", [Language.French] = "Rayon de Halo Adaptatif", [Language.German] = "Adaptiver Halo-Radius", [Language.Russian] = "Адаптивный Радиус Ореола" }, ["setting_attack_effects"] = new Dictionary<Language, string> { [Language.English] = "Attack Visual Effects Toggle", [Language.SimplifiedChinese] = "攻击视觉特效开关", [Language.Japanese] = "攻撃ビジュアルエフェクト切替", [Language.Korean] = "공격 시각 효과 토글", [Language.Spanish] = "Efectos Visuales de Ataque", [Language.French] = "Effets Visuels d'Attaque", [Language.German] = "Angriffs-Visuelle Effekte", [Language.Russian] = "Визуальные Эффекты Атаки" }, ["setting_show_facing"] = new Dictionary<Language, string> { [Language.English] = "Always Show Facing Arc Zone Toggle", [Language.SimplifiedChinese] = "总是显示面向弧形区域开关", [Language.Japanese] = "向いている方向の弧を常に表示", [Language.Korean] = "향하는 방향 호 항상 표시", [Language.Spanish] = "Mostrar Siempre Zona de Arco Frontal", [Language.French] = "Toujours Afficher la Zone d'Arc Frontal", [Language.German] = "Blickrichtungs-Bogen Immer Anzeigen", [Language.Russian] = "Всегда Показывать Дугу Направления" }, ["setting_attack_persist"] = new Dictionary<Language, string> { [Language.English] = "Attack Zone Persist Time", [Language.SimplifiedChinese] = "攻击区域保持时长", [Language.Japanese] = "攻撃ゾーン持続時間", [Language.Korean] = "공격 구역 지속 시간", [Language.Spanish] = "Tiempo de Persistencia de Zona", [Language.French] = "Durée de Persistance de Zone", [Language.German] = "Angriffszonen-Anzeigedauer", [Language.Russian] = "Время Сохранения Зоны Атаки" }, ["setting_toggle_key"] = new Dictionary<Language, string> { [Language.English] = "Toggle Key", [Language.SimplifiedChinese] = "切换键", [Language.Japanese] = "切替キー", [Language.Korean] = "전환 키", [Language.Spanish] = "Tecla de Activación", [Language.French] = "Touche de Basculement", [Language.German] = "Umschalttaste", [Language.Russian] = "Клавиша Переключения" }, ["setting_toggle_key_alt"] = new Dictionary<Language, string> { [Language.English] = "Secondary Toggle Key", [Language.SimplifiedChinese] = "备用切换键", [Language.Japanese] = "サブ切替キー", [Language.Korean] = "보조 전환 키", [Language.Spanish] = "Tecla Alternativa", [Language.French] = "Touche Alternative", [Language.German] = "Alternative Umschalttaste", [Language.Russian] = "Дополнительная Клавиша" }, ["setting_input_hold"] = new Dictionary<Language, string> { [Language.English] = "Input Hold Duration", [Language.SimplifiedChinese] = "输入保持时长", [Language.Japanese] = "入力保持時間", [Language.Korean] = "입력 유지 시간", [Language.Spanish] = "Duración de Retención", [Language.French] = "Durée de Maintien", [Language.German] = "Eingabe-Haltedauer", [Language.Russian] = "Длительность Удержания" }, ["setting_color_primary"] = new Dictionary<Language, string> { [Language.English] = "Primary (Horizontal)", [Language.SimplifiedChinese] = "主要颜色(水平)", [Language.Japanese] = "プライマリ(水平)", [Language.Korean] = "주 색상(수평)", [Language.Spanish] = "Primario (Horizontal)", [Language.French] = "Primaire (Horizontal)", [Language.German] = "Primär (Horizontal)", [Language.Russian] = "Основной (Горизонталь)" }, ["setting_color_secondary"] = new Dictionary<Language, string> { [Language.English] = "Secondary (Down)", [Language.SimplifiedChinese] = "次要颜色(向下)", [Language.Japanese] = "セカンダリ(下)", [Language.Korean] = "보조 색상(하)", [Language.Spanish] = "Secundario (Abajo)", [Language.French] = "Secondaire (Bas)", [Language.German] = "Sekundär (Unten)", [Language.Russian] = "Вторичный (Вниз)" }, ["setting_color_tertiary"] = new Dictionary<Language, string> { [Language.English] = "Tertiary (Up)", [Language.SimplifiedChinese] = "第三颜色(向上)", [Language.Japanese] = "ターシャリ(上)", [Language.Korean] = "3차 색상(상)", [Language.Spanish] = "Terciario (Arriba)", [Language.French] = "Tertiaire (Haut)", [Language.German] = "Tertiär (Oben)", [Language.Russian] = "Третичный (Вверх)" }, ["setting_color_preset"] = new Dictionary<Language, string> { [Language.English] = "Color Preset", [Language.SimplifiedChinese] = "颜色预设", [Language.Japanese] = "カラープリセット", [Language.Korean] = "색상 프리셋", [Language.Spanish] = "Preset de Color", [Language.French] = "Préréglage de Couleur", [Language.German] = "Farbvoreinstellung", [Language.Russian] = "Цветовая Предустановка" }, ["setting_developer_mode"] = new Dictionary<Language, string> { [Language.English] = "Developer Mode", [Language.SimplifiedChinese] = "开发者模式", [Language.Japanese] = "開発者モード", [Language.Korean] = "개발자 모드", [Language.Spanish] = "Modo Desarrollador", [Language.French] = "Mode Développeur", [Language.German] = "Entwicklermodus", [Language.Russian] = "Режим Разработчика" }, ["setting_verbose_logging"] = new Dictionary<Language, string> { [Language.English] = "Verbose Logging", [Language.SimplifiedChinese] = "详细日志", [Language.Japanese] = "詳細ログ", [Language.Korean] = "상세 로그", [Language.Spanish] = "Registro Detallado", [Language.French] = "Journalisation Détaillée", [Language.German] = "Ausführliche Protokollierung", [Language.Russian] = "Подробное Логирование" }, ["true_aim_on"] = new Dictionary<Language, string> { [Language.English] = "True Aim Overlay: ON", [Language.SimplifiedChinese] = "真准显示:开启", [Language.Japanese] = "True Aimオーバーレイ:ON", [Language.Korean] = "True Aim 오버레이: 켜짐", [Language.Spanish] = "Overlay True Aim: ACTIVADO", [Language.French] = "Overlay True Aim: ACTIVÉ", [Language.German] = "True Aim Overlay: AN", [Language.Russian] = "Оверлей True Aim: ВКЛ" }, ["true_aim_off"] = new Dictionary<Language, string> { [Language.English] = "True Aim Overlay: OFF", [Language.SimplifiedChinese] = "真准显示:关闭", [Language.Japanese] = "True Aimオーバーレイ:OFF", [Language.Korean] = "True Aim 오버레이: 꺼짐", [Language.Spanish] = "Overlay True Aim: DESACTIVADO", [Language.French] = "Overlay True Aim: DÉSACTIVÉ", [Language.German] = "True Aim Overlay: AUS", [Language.Russian] = "Оверлей True Aim: ВЫКЛ" }, ["attack_effects_on"] = new Dictionary<Language, string> { [Language.English] = "True Aim Attack Effects: ON", [Language.SimplifiedChinese] = "真准攻击特效:开启", [Language.Japanese] = "True Aim攻撃エフェクト:ON", [Language.Korean] = "True Aim 공격 효과: 켜짐", [Language.Spanish] = "Efectos de Ataque: ACTIVADO", [Language.French] = "Effets d'Attaque: ACTIVÉ", [Language.German] = "Angriffseffekte: AN", [Language.Russian] = "Эффекты Атаки: ВКЛ" }, ["attack_effects_off"] = new Dictionary<Language, string> { [Language.English] = "True Aim Attack Effects: OFF", [Language.SimplifiedChinese] = "真准攻击特效:关闭", [Language.Japanese] = "True Aim攻撃エフェクト:OFF", [Language.Korean] = "True Aim 공격 효과: 꺼짐", [Language.Spanish] = "Efectos de Ataque: DESACTIVADO", [Language.French] = "Effets d'Attaque: DÉSACTIVÉ", [Language.German] = "Angriffseffekte: AUS", [Language.Russian] = "Эффекты Атаки: ВЫКЛ" }, ["debug_overlay_on"] = new Dictionary<Language, string> { [Language.English] = "Debug Overlay: ON", [Language.SimplifiedChinese] = "调试面板:开启", [Language.Japanese] = "デバッグオーバーレイ:ON", [Language.Korean] = "디버그 오버레이: 켜짐", [Language.Spanish] = "Overlay de Depuración: ACTIVADO", [Language.French] = "Overlay de Débogage: ACTIVÉ", [Language.German] = "Debug-Overlay: AN", [Language.Russian] = "Отладочный Оверлей: ВКЛ" }, ["debug_overlay_off"] = new Dictionary<Language, string> { [Language.English] = "Debug Overlay: OFF", [Language.SimplifiedChinese] = "调试面板:关闭", [Language.Japanese] = "デバッグオーバーレイ:OFF", [Language.Korean] = "디버그 오버레이: 꺼짐", [Language.Spanish] = "Overlay de Depuración: DESACTIVADO", [Language.French] = "Overlay de Débogage: DÉSACTIVÉ", [Language.German] = "Debug-Overlay: AUS", [Language.Russian] = "Отладочный Оверлей: ВЫКЛ" }, ["found_nail_arts_fsm"] = new Dictionary<Language, string> { [Language.English] = "Found Nail Arts FSM!", [Language.SimplifiedChinese] = "已找到钉刺技能状态机!", [Language.Japanese] = "ネイルアーツFSMを発見!", [Language.Korean] = "네일 아츠 FSM 발견!", [Language.Spanish] = "¡FSM de Artes de Aguja encontrado!", [Language.French] = "FSM des Arts de l'Aiguille trouvé !", [Language.German] = "Nagel-Künste FSM gefunden!", [Language.Russian] = "FSM Искусств Иглы найден!" }, ["attack_detection_cached"] = new Dictionary<Language, string> { [Language.English] = "Attack detection fields cached via reflection", [Language.SimplifiedChinese] = "已通过反射缓存攻击检测字段", [Language.Japanese] = "リフレクションで攻撃検出フィールドをキャッシュ", [Language.Korean] = "리플렉션으로 공격 감지 필드 캐시됨", [Language.Spanish] = "Campos de detección de ataque almacenados por reflexión", [Language.French] = "Champs de détection d'attaque mis en cache par réflexion", [Language.German] = "Angriffserkennungsfelder via Reflection gecacht", [Language.Russian] = "Поля обнаружения атак кэшированы через рефлексию" }, ["zones_initialized"] = new Dictionary<Language, string> { [Language.English] = "Initialized {0} zones with configured colors", [Language.SimplifiedChinese] = "已初始化 {0} 个区域并配置颜色", [Language.Japanese] = "{0}個のゾーンを色設定付きで初期化", [Language.Korean] = "{0}개 구역을 색상과 함께 초기화", [Language.Spanish] = "Inicializadas {0} zonas con colores configurados", [Language.French] = "{0} zones initialisées avec couleurs configurées", [Language.German] = "{0} Zonen mit konfigurierten Farben initialisiert", [Language.Russian] = "Инициализировано {0} зон с настроенными цветами" }, ["config_developer_mode"] = new Dictionary<Language, string> { [Language.English] = "Enable developer debug tools (F9, F11, F12, logging). Hidden feature for development.", [Language.SimplifiedChinese] = "启用开发者调试工具(F9, F11, F12, 日志记录)。开发用隐藏功能。", [Language.Japanese] = "開発者デバッグツールを有効化(F9, F11, F12, ログ)。開発用隠し機能。", [Language.Korean] = "개발자 디버그 도구 활성화(F9, F11, F12, 로깅). 개발용 숨겨진 기능.", [Language.Spanish] = "Activar herramientas de depuración (F9, F11, F12, registro). Función oculta para desarrollo.", [Language.French] = "Activer les outils de débogage (F9, F11, F12, journaux). Fonction cachée pour le développement.", [Language.German] = "Entwickler-Debug-Tools aktivieren (F9, F11, F12, Protokollierung). Versteckte Funktion für Entwicklung.", [Language.Russian] = "Включить инструменты отладки разработчика (F9, F11, F12, логирование). Скрытая функция для разработки." }, ["config_verbose_logging"] = new Dictionary<Language, string> { [Language.English] = "Enable detailed attack detection logging. Creates large log files. Use F11 debug overlay for temporary verbose logging instead.", [Language.SimplifiedChinese] = "启用详细的攻击检测日志。会创建大型日志文件。建议使用 F11 调试面板进行临时详细日志记录。", [Language.Japanese] = "詳細な攻撃検出ログを有効化。大きなログファイルが作成されます。代わりにF11デバッグオーバーレイで一時的な詳細ログを使用してください。", [Language.Korean] = "상세 공격 감지 로그 활성화. 큰 로그 파일을 생성합니다. 대신 F11 디버그 오버레이로 임시 상세 로그를 사용하세요.", [Language.Spanish] = "Activar registro detallado de detección de ataques. Crea archivos de registro grandes. Use F11 para registro temporal en su lugar.", [Language.French] = "Activer la journalisation détaillée de détection d'attaque. Crée de gros fichiers journaux. Utilisez F11 pour la journalisation temporaire à la place.", [Language.German] = "Detaillierte Angriffserkennung aktivieren. Erstellt große Protokolldateien. Verwenden Sie stattdessen F11 für temporäre Protokollierung.", [Language.Russian] = "Включить подробное логирование обнаружения атак. Создает большие файлы логов. Используйте F11 для временного подробного логирования." }, ["config_show_guide"] = new Dictionary<Language, string> { [Language.English] = "Show the input guide halo around Hornet", [Language.SimplifiedChinese] = "以大黄蜂为中心显示输入指引光环", [Language.Japanese] = "ホーネットの周りに入力ガイドハローを表示", [Language.Korean] = "호넷 주위에 입력 가이드 후광 표시", [Language.Spanish] = "Mostrar el halo de guía de entrada alrededor de Hornet", [Language.French] = "Afficher le halo de guide d'entrée autour de Hornet", [Language.German] = "Eingabehilfe-Halo um Hornet anzeigen", [Language.Russian] = "Показать ореол гида ввода вокруг Хорнет" }, ["config_halo_radius"] = new Dictionary<Language, string> { [Language.English] = "Radius of the halo around Hornet", [Language.SimplifiedChinese] = "设置输入指引光环的半径", [Language.Japanese] = "ホーネット周りのハローの半径", [Language.Korean] = "호넷 주위 후광의 반경", [Language.Spanish] = "Radio del halo alrededor de Hornet", [Language.French] = "Rayon du halo autour de Hornet", [Language.German] = "Radius des Halos um Hornet", [Language.Russian] = "Радиус ореола вокруг Хорнет" }, ["config_active_opacity"] = new Dictionary<Language, string> { [Language.English] = "Opacity when zone is active (default 0.6)", [Language.SimplifiedChinese] = "区域激活时的不透明度(默认0.6)", [Language.Japanese] = "ゾーンアクティブ時の不透明度(デフォルト0.6)", [Language.Korean] = "구역 활성 시 불투명도(기본값 0.6)", [Language.Spanish] = "Opacidad cuando la zona está activa (predeterminado 0.6)", [Language.French] = "Opacité lorsque la zone est active (par défaut 0.6)", [Language.German] = "Deckkraft bei aktiver Zone (Standard 0.6)", [Language.Russian] = "Непрозрачность при активной зоне (по умолчанию 0.6)" }, ["config_inactive_opacity"] = new Dictionary<Language, string> { [Language.English] = "Opacity when zone is inactive (default 0.2)", [Language.SimplifiedChinese] = "区域未激活时的不透明度(默认0.2)", [Language.Japanese] = "ゾーン非アクティブ時の不透明度(デフォルト0.2)", [Language.Korean] = "구역 비활성 시 불투명도(기본값 0.2)", [Language.Spanish] = "Opacidad cuando la zona está inactiva (predeterminado 0.2)", [Language.French] = "Opacité lorsque la zone est inactive (par défaut 0.2)", [Language.German] = "Deckkraft bei inaktiver Zone (Standard 0.2)", [Language.Russian] = "Непрозрачность при неактивной зоне (по умолчанию 0.2)" }, ["config_indicator_offset"] = new Dictionary<Language, string> { [Language.English] = "How far from center the indicator arrow starts (0=center, 1=edge)", [Language.SimplifiedChinese] = "指示箭头从中心开始的距离(0=中心,1=边缘)", [Language.Japanese] = "インジケーター矢印の開始位置(0=中心, 1=端)", [Language.Korean] = "표시기 화살표 시작 거리(0=중심, 1=가장자리)", [Language.Spanish] = "Distancia desde el centro donde comienza la flecha (0=centro, 1=borde)", [Language.French] = "Distance du centre où commence la flèche (0=centre, 1=bord)", [Language.German] = "Startposition des Indikatorpfeils vom Zentrum (0=Zentrum, 1=Rand)", [Language.Russian] = "Расстояние от центра для стрелки индикатора (0=центр, 1=край)" }, ["config_adaptive_halo"] = new Dictionary<Language, string> { [Language.English] = "Automatically adjust halo radius based on equipped crest and Longclaw tool to match attack range visually. Updates when changing equipment at a bench.", [Language.SimplifiedChinese] = "启用自适应光环半径功能,根据现装备的纹章(和钉爪工具)调整光环视觉大小来预示攻击距离, 仅在坐长椅并切换纹章后更新!", [Language.Japanese] = "装備中のクレストとロングクロー道具に基づいてハロー半径を自動調整し、攻撃範囲を視覚的に一致させます。ベンチで装備変更時に更新されます。", [Language.Korean] = "장착된 문장과 롱클로 도구에 따라 후광 반경을 자동 조정하여 공격 범위를 시각적으로 일치시킵니다. 벤치에서 장비 변경 시 업데이트됩니다.", [Language.Spanish] = "Ajustar automáticamente el radio del halo según la cresta equipada y la herramienta Longclaw para coincidir visualmente con el rango de ataque. Se actualiza al cambiar equipo en un banco.", [Language.French] = "Ajuster automatiquement le rayon du halo en fonction de la crête équipée et de l'outil Longclaw pour correspondre visuellement à la portée d'attaque. Se met à jour lors du changement d'équipement sur un banc.", [Language.German] = "Halo-Radius automatisch an ausgerüsteten Wappen und Longclaw-Werkzeug anpassen, um die Angriffsreichweite visuell anzuzeigen. Aktualisiert sich beim Ausrüstungswechsel auf einer Bank.", [Language.Russian] = "Автоматически настраивать радиус ореола в зависимости от экипированного герба и инструмента Длинный Коготь для визуального соответствия дальности атаки. Обновляется при смене экипировки на скамье." }, ["config_attack_effects"] = new Dictionary<Language, string> { [Language.English] = "Enable attack flash and pulse effects", [Language.SimplifiedChinese] = "启用攻击闪光和脉冲效果", [Language.Japanese] = "攻撃フラッシュとパルスエフェクトを有効化", [Language.Korean] = "공격 플래시 및 펄스 효과 활성화", [Language.Spanish] = "Activar efectos de destello y pulso de ataque", [Language.French] = "Activer les effets de flash et de pulsation d'attaque", [Language.German] = "Angriffsblitz- und Pulseffekte aktivieren", [Language.Russian] = "Включить эффекты вспышки и пульсации атаки" }, ["config_show_facing"] = new Dictionary<Language, string> { [Language.English] = "Always highlight horizontal zone based on facing direction (even without input)", [Language.SimplifiedChinese] = "始终根据面向方向高亮显示水平区域(即使没有输入)", [Language.Japanese] = "向いている方向に基づいて水平ゾーンを常にハイライト表示(入力なしでも)", [Language.Korean] = "향하는 방향에 따라 수평 구역을 항상 강조 표시(입력 없이도)", [Language.Spanish] = "Resaltar siempre la zona horizontal según la dirección frontal (incluso sin entrada)", [Language.French] = "Toujours mettre en surbrillance la zone horizontale selon la direction (même sans entrée)", [Language.German] = "Horizontale Zone basierend auf Blickrichtung immer hervorheben (auch ohne Eingabe)", [Language.Russian] = "Всегда подсвечивать горизонтальную зону в зависимости от направления взгляда (даже без ввода)" }, ["config_attack_persist"] = new Dictionary<Language, string> { [Language.English] = "How long (seconds) to keep attack zone highlighted after fill animation completes", [Language.SimplifiedChinese] = "填充动画完成后保持攻击区域高亮的时长(秒)", [Language.Japanese] = "充填