Decompiled source of MageArenaRussianVoice v2.0.0

BepInEx/plugins/MageArenaRussianVoice.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance;
using HarmonyLib;
using MageArenaRussianVoice.Config;
using Microsoft.CodeAnalysis;
using Recognissimo;
using Recognissimo.Components;
using UnityEngine;
using UnityEngine.Events;

[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("MageArenaRussianVoice")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0+3f78881f8bcbfc19d17c49680613fb49de4bd2b7")]
[assembly: AssemblyProduct("MageArenaRussianVoice")]
[assembly: AssemblyTitle("MageArenaRussianVoice")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MageArenaRussianVoice
{
	[BepInPlugin("com.infernumvii.magearenarussianvoice", "MageArenaRussianVoice", "2.0.0")]
	public class MageArenaRussianVoice : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("com.infernumvii.magearenarussianvoice");

		internal static ManualLogSource Logger;

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			VoiceCommandConfig.Init(((BaseUnityPlugin)this).Config);
			harmony.PatchAll();
			Logger.LogInfo((object)"MageArenaRussianVoice loaded!");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "MageArenaRussianVoice";

		public const string PLUGIN_NAME = "MageArenaRussianVoice";

		public const string PLUGIN_VERSION = "2.0.0";
	}
}
namespace MageArenaRussianVoice.Patches
{
	[HarmonyPatch(typeof(SetUpModelProvider), "Setup")]
	public static class SetUpModelProviderPatch
	{
		private static readonly string nameOfModel = "vosk-model-small-ru-0.22";

		[HarmonyPrefix]
		public static bool Prefix(SetUpModelProvider __instance)
		{
			//IL_000f: 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_0027: 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)
			StreamingAssetsLanguageModelProvider val = ((Component)__instance).gameObject.AddComponent<StreamingAssetsLanguageModelProvider>();
			val.language = (SystemLanguage)30;
			val.languageModels = new List<StreamingAssetsLanguageModel>
			{
				new StreamingAssetsLanguageModel
				{
					language = (SystemLanguage)30,
					path = "LanguageModels/" + nameOfModel
				}
			};
			((SpeechProcessor)((Component)__instance).GetComponent<SpeechRecognizer>()).LanguageModelProvider = (LanguageModelProvider)(object)val;
			return false;
		}
	}
	[HarmonyPatch(typeof(VoiceControlListener))]
	public static class VoiceControlListenerPatch
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass11_0
		{
			public VoiceControlListener instance;

			internal void <ModifiedResetMicLong>b__0(Result res)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				instance.tryresult(res.text);
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass7_0
		{
			public VoiceControlListener instance;

			internal void <ModifiedWaitGetPlayer>b__0(Result res)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				instance.tryresult(res.text);
			}
		}

		[CompilerGenerated]
		private sealed class <ModifiedResetMicLong>d__11 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public VoiceControlListener instance;

			private <>c__DisplayClass11_0 <>8__1;

			private SpeechRecognizer <recognizer>5__2;

			private SpeechRecognizer <recognizerNew>5__3;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ModifiedResetMicLong>d__11(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = null;
				<recognizer>5__2 = null;
				<recognizerNew>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Expected O, but got Unknown
				//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b4: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>8__1 = new <>c__DisplayClass11_0();
					<>8__1.instance = instance;
					<recognizer>5__2 = srRef.Invoke(<>8__1.instance);
					((SpeechProcessor)<recognizer>5__2).StopProcessing();
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					Object.Destroy((Object)(object)<recognizer>5__2);
					srRef.Invoke(<>8__1.instance) = ((Component)<>8__1.instance).gameObject.AddComponent<SpeechRecognizer>();
					<recognizerNew>5__3 = srRef.Invoke(<>8__1.instance);
					((SpeechProcessor)<recognizerNew>5__3).LanguageModelProvider = (LanguageModelProvider)(object)((Component)<>8__1.instance).GetComponent<StreamingAssetsLanguageModelProvider>();
					((SpeechProcessor)<recognizerNew>5__3).SpeechSource = (SpeechSource)(object)((Component)<>8__1.instance).GetComponent<DissonanceSpeechSource>();
					<recognizerNew>5__3.Vocabulary = new List<string>();
					<>8__1.instance.SpellPages = new List<ISpellCommand>();
					MonoBehaviour[] components = ((Component)<>8__1.instance).gameObject.GetComponents<MonoBehaviour>();
					foreach (MonoBehaviour obj in components)
					{
						ISpellCommand val = (ISpellCommand)(object)((obj is ISpellCommand) ? obj : null);
						if (val != null)
						{
							<>8__1.instance.SpellPages.Add(val);
						}
					}
					addSpellsToVocabulary(<recognizerNew>5__3);
					((UnityEvent<Result>)(object)<recognizerNew>5__3.ResultReady).AddListener((UnityAction<Result>)delegate(Result res)
					{
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						<>8__1.instance.tryresult(res.text);
					});
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 2;
					return true;
				}
				case 2:
					<>1__state = -1;
					((SpeechProcessor)<recognizerNew>5__3).StartProcessing();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <ModifiedWaitGetPlayer>d__7 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public VoiceControlListener instance;

			private <>c__DisplayClass7_0 <>8__1;

			private SpeechRecognizer <recognizer>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ModifiedWaitGetPlayer>d__7(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = null;
				<recognizer>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bf: Expected O, but got Unknown
				//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f9: Expected O, but got Unknown
				//IL_023a: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>8__1 = new <>c__DisplayClass7_0();
					<>8__1.instance = instance;
					goto IL_009f;
				case 1:
					<>1__state = -1;
					goto IL_009f;
				case 2:
				{
					<>1__state = -1;
					srRef.Invoke(<>8__1.instance) = ((Component)<>8__1.instance).GetComponent<SpeechRecognizer>();
					<>8__1.instance.SpellPages = new List<ISpellCommand>();
					MonoBehaviour[] components = ((Component)<>8__1.instance).gameObject.GetComponents<MonoBehaviour>();
					foreach (MonoBehaviour obj in components)
					{
						ISpellCommand val = (ISpellCommand)(object)((obj is ISpellCommand) ? obj : null);
						if (val != null)
						{
							<>8__1.instance.SpellPages.Add(val);
						}
					}
					<recognizer>5__2 = srRef.Invoke(<>8__1.instance);
					addSpellsToVocabulary(<recognizer>5__2);
					((UnityEvent<Result>)(object)<recognizer>5__2.ResultReady).AddListener((UnityAction<Result>)delegate(Result res)
					{
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						<>8__1.instance.tryresult(res.text);
					});
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 3;
					return true;
				}
				case 3:
					<>1__state = -1;
					((SpeechProcessor)((Component)<>8__1.instance).GetComponent<SpeechRecognizer>()).StartProcessing();
					break;
				case 4:
					{
						<>1__state = -1;
						if (!vbtRef.Invoke(<>8__1.instance).IsTransmitting && (Object)(object)<recognizer>5__2 != (Object)null && (int)((SpeechProcessor)<recognizer>5__2).State != 0)
						{
							((SpeechProcessor)<recognizer>5__2).StopProcessing();
							((MonoBehaviour)<>8__1.instance).StartCoroutine((IEnumerator)restartsrMethod.Invoke(<>8__1.instance, null));
						}
						break;
					}
					IL_009f:
					if ((Object)(object)<>8__1.instance.pi == (Object)null)
					{
						PlayerInventory pi = default(PlayerInventory);
						if ((Object)(object)((Component)Camera.main).transform.parent != (Object)null && ((Component)((Component)Camera.main).transform.parent).TryGetComponent<PlayerInventory>(ref pi))
						{
							<>8__1.instance.pi = pi;
						}
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					((Component)<>8__1.instance).GetComponent<SetUpModelProvider>().Setup();
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				if (((Behaviour)<>8__1.instance).isActiveAndEnabled)
				{
					<>2__current = (object)new WaitForSeconds(30f);
					<>1__state = 4;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SafeRestartSr>d__13 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public VoiceControlListener instance;

			private SpeechRecognizer <recognizer>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SafeRestartSr>d__13(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<recognizer>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<recognizer>5__2 = srRef.Invoke(instance);
					if ((Object)(object)<recognizer>5__2 == (Object)null)
					{
						return false;
					}
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((int)((SpeechProcessor)<recognizer>5__2).State != 0)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if ((Object)(object)<recognizer>5__2 != (Object)null)
				{
					((SpeechProcessor)<recognizer>5__2).StartProcessing();
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static Dictionary<string[], Action<VoiceControlListener>> russianCommandMap;

		private static Dictionary<string, string[]> russianAdditionalCommandMap;

		private static readonly FieldRef<VoiceControlListener, SpeechRecognizer> srRef = AccessTools.FieldRefAccess<VoiceControlListener, SpeechRecognizer>("sr");

		private static readonly FieldRef<VoiceControlListener, VoiceBroadcastTrigger> vbtRef = AccessTools.FieldRefAccess<VoiceControlListener, VoiceBroadcastTrigger>("vbt");

		private static readonly MethodInfo restartsrMethod = AccessTools.Method(typeof(VoiceControlListener), "restartsr", (Type[])null, (Type[])null);

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(VoiceControlListener __instance)
		{
			PluginInfo val = ((IEnumerable<PluginInfo>)Chainloader.PluginInfos.Values).FirstOrDefault((Func<PluginInfo, bool>)((PluginInfo p) => p.Metadata.GUID == "com.infernumvii.magearenarussianvoice"));
			if (val != null)
			{
				VoiceCommandConfig.Init(val.Instance.Config);
				Dictionary<string[], Action<VoiceControlListener>> dictionary = new Dictionary<string[], Action<VoiceControlListener>>();
				dictionary.Add(VoiceCommandConfig.FireballCommand.Value.Split(new char[1] { ' ' }), delegate(VoiceControlListener v)
				{
					v.CastFireball();
				});
				dictionary.Add(VoiceCommandConfig.FrostBoltCommand.Value.Split(new char[1] { ' ' }), delegate(VoiceControlListener v)
				{
					v.CastFrostBolt();
				});
				dictionary.Add(VoiceCommandConfig.WormCommand.Value.Split(new char[1] { ' ' }), delegate(VoiceControlListener v)
				{
					v.CastWorm();
				});
				dictionary.Add(VoiceCommandConfig.HoleCommand.Value.Split(new char[1] { ' ' }), delegate(VoiceControlListener v)
				{
					v.CastHole();
				});
				dictionary.Add(VoiceCommandConfig.MagicMissileCommand.Value.Split(new char[1] { ' ' }), delegate(VoiceControlListener v)
				{
					v.CastMagicMissle();
				});
				dictionary.Add(VoiceCommandConfig.MirrorCommand.Value.Split(new char[1] { ' ' }), delegate(VoiceControlListener v)
				{
					v.ActivateMirror();
				});
				russianCommandMap = dictionary;
				Dictionary<string, string[]> dictionary2 = new Dictionary<string, string[]>();
				dictionary2.Add("rock", VoiceCommandConfig.RockCommand.Value.Split(new char[1] { ' ' }));
				dictionary2.Add("wisp", VoiceCommandConfig.WispCommand.Value.Split(new char[1] { ' ' }));
				dictionary2.Add("blast", VoiceCommandConfig.BlastCommand.Value.Split(new char[1] { ' ' }));
				dictionary2.Add("divine", VoiceCommandConfig.DivineCommand.Value.Split(new char[1] { ' ' }));
				dictionary2.Add("blink", VoiceCommandConfig.BlinkCommand.Value.Split(new char[1] { ' ' }));
				dictionary2.Add("thunderbolt", VoiceCommandConfig.ThunderboltCommand.Value.Split(new char[1] { ' ' }));
				russianAdditionalCommandMap = dictionary2;
			}
		}

		[HarmonyPatch("waitgetplayer")]
		[HarmonyPrefix]
		private static bool WaitGetPlayerPrefix(VoiceControlListener __instance, ref IEnumerator __result)
		{
			__result = ModifiedWaitGetPlayer(__instance);
			return false;
		}

		[IteratorStateMachine(typeof(<ModifiedWaitGetPlayer>d__7))]
		private static IEnumerator ModifiedWaitGetPlayer(VoiceControlListener instance)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ModifiedWaitGetPlayer>d__7(0)
			{
				instance = instance
			};
		}

		private static void addSpellsToVocabulary(SpeechRecognizer recognizer)
		{
			foreach (KeyValuePair<string[], Action<VoiceControlListener>> item3 in russianCommandMap)
			{
				string[] key = item3.Key;
				foreach (string item in key)
				{
					recognizer.Vocabulary.Add(item);
				}
			}
			foreach (KeyValuePair<string, string[]> item4 in russianAdditionalCommandMap)
			{
				string[] key = item4.Value;
				foreach (string item2 in key)
				{
					recognizer.Vocabulary.Add(item2);
				}
			}
		}

		[HarmonyPatch("tryresult")]
		[HarmonyPrefix]
		private static bool TryResultPrefix(VoiceControlListener __instance, string res)
		{
			if (res != null)
			{
				foreach (KeyValuePair<string[], Action<VoiceControlListener>> item in russianCommandMap)
				{
					if (item.Key.Any((string keyword) => res.Contains(keyword)))
					{
						item.Value(__instance);
					}
				}
				foreach (KeyValuePair<string, string[]> pair in russianAdditionalCommandMap)
				{
					if (pair.Value.Any((string keyword) => res.Contains(keyword)))
					{
						ISpellCommand? obj = ((IEnumerable<ISpellCommand>)__instance.SpellPages).FirstOrDefault((Func<ISpellCommand, bool>)((ISpellCommand s) => s != null && s.GetSpellName() == pair.Key));
						if (obj != null)
						{
							obj.TryCastSpell();
						}
					}
				}
				((SpeechProcessor)srRef.Invoke(__instance)).StopProcessing();
				((MonoBehaviour)__instance).StartCoroutine((IEnumerator)restartsrMethod.Invoke(__instance, null));
			}
			return false;
		}

		[HarmonyPatch("resetmiclong")]
		[HarmonyPrefix]
		private static bool ResetMicLongPrefix(VoiceControlListener __instance, ref IEnumerator __result)
		{
			__result = ModifiedResetMicLong(__instance);
			return false;
		}

		[IteratorStateMachine(typeof(<ModifiedResetMicLong>d__11))]
		private static IEnumerator ModifiedResetMicLong(VoiceControlListener instance)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ModifiedResetMicLong>d__11(0)
			{
				instance = instance
			};
		}

		[HarmonyPatch("restartsr")]
		[HarmonyPrefix]
		private static bool RestartSrPrefix(VoiceControlListener __instance, ref IEnumerator __result)
		{
			__result = SafeRestartSr(__instance);
			return false;
		}

		[IteratorStateMachine(typeof(<SafeRestartSr>d__13))]
		private static IEnumerator SafeRestartSr(VoiceControlListener instance)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SafeRestartSr>d__13(0)
			{
				instance = instance
			};
		}
	}
}
namespace MageArenaRussianVoice.Config
{
	public static class VoiceCommandConfig
	{
		public static ConfigEntry<string> FireballCommand;

		public static ConfigEntry<string> FrostBoltCommand;

		public static ConfigEntry<string> WormCommand;

		public static ConfigEntry<string> HoleCommand;

		public static ConfigEntry<string> MagicMissileCommand;

		public static ConfigEntry<string> MirrorCommand;

		public static ConfigEntry<string> RockCommand;

		public static ConfigEntry<string> WispCommand;

		public static ConfigEntry<string> BlastCommand;

		public static ConfigEntry<string> DivineCommand;

		public static ConfigEntry<string> BlinkCommand;

		public static ConfigEntry<string> ThunderboltCommand;

		public static void Init(ConfigFile config)
		{
			FireballCommand = config.Bind<string>("Commands", "Fireball", "огненный шар", "Russian command for Fireball spell (все варианты слова могут быть разделены через пробел)");
			FrostBoltCommand = config.Bind<string>("Commands", "FrostBolt", "сосулька", "Russian command for Frost Bolt spell (все варианты слова могут быть разделены через пробел)");
			WormCommand = config.Bind<string>("Commands", "Worm", "вход", "Russian command for Worm spell (все варианты слова могут быть разделены через пробел)");
			HoleCommand = config.Bind<string>("Commands", "Hole", "выход", "Russian command for Hole spell (все варианты слова могут быть разделены через пробел)");
			MagicMissileCommand = config.Bind<string>("Commands", "MagicMissile", "магический снаряд", "Russian command for Magic Missile spell (все варианты слова могут быть разделены через пробел)");
			MirrorCommand = config.Bind<string>("Commands", "Mirror", "зеркало", "Russian command for Mirror spell (все варианты слова могут быть разделены через пробел)");
			RockCommand = config.Bind<string>("AdditionalCommands", "Rock", "валун", "Russian command for Rock spell (все варианты слова могут быть разделены через пробел)");
			WispCommand = config.Bind<string>("AdditionalCommands", "Wisp", "дух", "Russian command for Wisp spell (все варианты слова могут быть разделены через пробел)");
			BlastCommand = config.Bind<string>("AdditionalCommands", "Blast", "тёмный луч", "Russian command for Blast spell (все варианты слова могут быть разделены через пробел)");
			DivineCommand = config.Bind<string>("AdditionalCommands", "Divine", "божий свет", "Russian command for Divine spell (все варианты слова могут быть разделены через пробел)");
			BlinkCommand = config.Bind<string>("AdditionalCommands", "Blink", "прыжок", "Russian command for Blink spell (все варианты слова могут быть разделены через пробел)");
			ThunderboltCommand = config.Bind<string>("AdditionalCommands", "Thunderbolt", "гром", "Russian command for Thunderbolt spell (все варианты слова могут быть разделены через пробел)");
		}
	}
}