Decompiled source of VoiceCurseRu v1.1.1

plugins/VoiceCurse.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice;
using Photon.Voice.PUN;
using Photon.Voice.Unity;
using UnityEngine;
using VoiceCurse.Events;
using VoiceCurse.Handlers;
using VoiceCurse.Interfaces;
using VoiceCurse.Voice;
using Vosk;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VoiceCurse")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Russian Voice Recognition Mod")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("VoiceCurse")]
[assembly: AssemblyTitle("VoiceCurse")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.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.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;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace VoiceCurse
{
	public class Config
	{
		public ConfigEntry<bool> EnableDebugLogs { get; private set; }

		public ConfigEntry<float> GlobalCooldown { get; private set; }

		public ConfigEntry<bool> LaunchEnabled { get; private set; }

		public ConfigEntry<string> LaunchKeywords { get; private set; }

		public ConfigEntry<float> LaunchStunDuration { get; private set; }

		public ConfigEntry<float> LaunchForceLowerBound { get; private set; }

		public ConfigEntry<float> LaunchForceHigherBound { get; private set; }

		public ConfigEntry<bool> AfflictionEnabled { get; private set; }

		public ConfigEntry<float> AfflictionMinPercent { get; private set; }

		public ConfigEntry<float> AfflictionMaxPercent { get; private set; }

		public ConfigEntry<bool> AfflictionTemperatureSwapEnabled { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsInjury { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsHunger { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsCold { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsHot { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsPoison { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsSpores { get; private set; }

		public ConfigEntry<bool> TransmuteEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteDeathEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteBackpackEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteMilkEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteCactusEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteCoconutEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteAppleEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteBananaEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteEggEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteFruitEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteMushroomEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteBallEnabled { get; private set; }

		public ConfigEntry<bool> DeathEnabled { get; private set; }

		public ConfigEntry<string> DeathKeywords { get; private set; }

		public ConfigEntry<bool> HealEnabled { get; private set; }

		public ConfigEntry<string> HealKeywords { get; private set; }

		public ConfigEntry<float> HealCooldown { get; private set; }

		public ConfigEntry<float> HealAmount { get; private set; }

		public ConfigEntry<bool> ZombifyEnabled { get; private set; }

		public ConfigEntry<string> ZombifyKeywords { get; private set; }

		public ConfigEntry<bool> SleepEnabled { get; private set; }

		public ConfigEntry<string> SleepKeywords { get; private set; }

		public ConfigEntry<bool> DropEnabled { get; private set; }

		public ConfigEntry<string> DropKeywords { get; private set; }

		public ConfigEntry<bool> ExplodeEnabled { get; private set; }

		public ConfigEntry<string> ExplodeKeywords { get; private set; }

		public ConfigEntry<float> ExplodeRadius { get; private set; }

		public ConfigEntry<float> ExplodeDamage { get; private set; }

		public ConfigEntry<float> ExplodeStunDuration { get; private set; }

		public ConfigEntry<float> ExplodeForceLowerBound { get; private set; }

		public ConfigEntry<float> ExplodeForceHigherBound { get; private set; }

		public ConfigEntry<bool> SlipEnabled { get; private set; }

		public ConfigEntry<string> SlipKeywords { get; private set; }

		public ConfigEntry<float> SlipStunDuration { get; private set; }

		public ConfigEntry<bool> BananaBombEnabled { get; private set; }

		public ConfigEntry<float> BananaBombChance { get; private set; }

		public ConfigEntry<int> BananaBombAmount { get; private set; }

		public ConfigEntry<bool> SacrificeEnabled { get; private set; }

		public ConfigEntry<string> SacrificeKeywords { get; private set; }

		public ConfigEntry<float> SacrificeCooldown { get; private set; }

		public ConfigEntry<bool> BlindEnabled { get; private set; }

		public ConfigEntry<string> BlindKeywords { get; private set; }

		public ConfigEntry<float> BlindDuration { get; private set; }

		public Config(ConfigFile config)
		{
			EnableDebugLogs = config.Bind<bool>("Global", "EnableDebugLogs", true, "Включить отладочные логи для распознавания речи.");
			GlobalCooldown = config.Bind<float>("Global", "GlobalCooldown", 2f, "Время в секундах, которое должно пройти перед возможностью запуска другого голосового события.");
			LaunchEnabled = config.Bind<bool>("Event.Launch", "Enabled", true, "Включить событие 'Запуск'.");
			LaunchKeywords = config.Bind<string>("Event.Launch", "Keywords", "полет, вверх, прыжок, ракета, взлет, космос, лечу, пушка, небо, прыгай, выше, катапульта, запуск, подбрось, высота, подпрыгнул, летим, орбита, прыг, взлетай, ввысь, вправо, влево, назад, вперед, вперёд, поехали, гагарин, илон маск, на луну, отрыв, джетпак, парашют, пружина, батут, лифт, этаж", "Список ключевых слов, вызывающих событие запуска, разделенных запятыми.");
			LaunchForceLowerBound = config.Bind<float>("Event.Launch", "ForceLowerBound", 1500f, "Минимально возможная сила, применяемая к игроку при запуске.");
			LaunchForceHigherBound = config.Bind<float>("Event.Launch", "ForceHigherBound", 3000f, "Максимально возможная сила, применяемая к игроку при запуске.");
			LaunchStunDuration = config.Bind<float>("Event.Launch", "StunDuration", 3f, "Длительность в секундах, на которую игрок будет оглушен/сбит с ног после запуска.");
			AfflictionEnabled = config.Bind<bool>("Event.Affliction", "Enabled", true, "Включить событие 'Недуг'.");
			AfflictionMinPercent = config.Bind<float>("Event.Affliction", "MinPercent", 0.2f, "Минимальный процент (от 0.0 до 1.0) заполнения шкалы состояния при срабатывании.");
			AfflictionMaxPercent = config.Bind<float>("Event.Affliction", "MaxPercent", 0.6f, "Максимальный процент (от 0.0 до 1.0) заполнения шкалы состояния при срабатывании.");
			AfflictionTemperatureSwapEnabled = config.Bind<bool>("Event.Affliction", "TemperatureSwapEnabled", true, "Если включено, попытка избавиться от жары или холода, сказав противоположное, просто заменит текущий эффект на новый и добавит его сверху, чтобы предотвратить злоупотребление механикой.");
			AfflictionKeywordsInjury = config.Bind<string>("Event.Affliction", "KeywordsInjury", "урон, ударился, травма, ранил, поранил, боль, вред, ранка, рана, удар, кровь, синяк, порез, оранж, язва, разрез, соскреб, слеза, рвать, лом, растяжение, калеч, калек, больно, минус хп, дамаг, покоцал, шотнул, ваншот, ранение, кровотечение, ударили, ушиб, перелом, бо-бо", "Ключевые слова, вызывающие физическую травму.");
			AfflictionKeywordsHunger = config.Bind<string>("Event.Affliction", "KeywordsHunger", "голод, голоден, еда, кушать, жрать, пища, аппетит, желтый, перекус, обед, ужин, жратва, голодаю, проголодался, хавать, питание, продукты, перекусить, ням, вкусно, живот урчит, хавчик, сухпай, консерва, завтрак, полдник, хочу есть, заморить червячка, столовая, бургер, пицца, снек", "Ключевые слова, вызывающие голод.");
			AfflictionKeywordsCold = config.Bind<string>("Event.Affliction", "KeywordsCold", "холод, мороз, лед, зима, синий, иней, метель, стужа, замерз, озноб, льдина, онемел, холодрыга, ледяной, снег, вьюга, арктика, полярный, дубак, замерзаю, фриз, колотун, дрожу, сосулька, прохладно, сквозняк, свежо, минус градус, окоченел, мерзляк, айсберг, снеговик", "Ключевые слова, вызывающие статус холода.");
			AfflictionKeywordsHot = config.Bind<string>("Event.Affliction", "KeywordsHot", "жара, огонь, пламя, лето, красный, пожар, печка, кипит, жарко, горю, пекло, поджог, костер, солнце, духота, варить, запекать, сгораю, искры, плавить, обжегся, ожог, негр, нигер, уголек, черный, шалава, пидор, пидрас, пидорас, гей, гомик, петух, черт, демон, лава, духовка, кипяток, прожарка, гриль, факел, спички, зажигалка", "Ключевые слова, вызывающие статус жары.");
			AfflictionKeywordsPoison = config.Bind<string>("Event.Affliction", "KeywordsPoison", "тошнота, рвота, токсин, фиолетовый, болезнь, болен, зараза, отрава, мутит, тошнит, инфекция, болячка, недуг, токсичный, отравился, блевать, рыгать, укачало, химия, радиация, газ, воняет, дурно, плохо мне, живот болит, диарея, понос, вирус", "Ключевые слова, вызывающие статус отравления.");
			AfflictionKeywordsSpores = config.Bind<string>("Event.Affliction", "KeywordsSpores", "споры, розовый, гриб, плесень, грибок, грибочек, мухомор, поганка, мицелий, сырость, заплесневел, аллергия", "Ключевые слова, вызывающие статус спор.");
			TransmuteEnabled = config.Bind<bool>("Event.Transmute", "Enabled", true, "Включить событие 'Превращение'.");
			TransmuteDeathEnabled = config.Bind<bool>("Event.Transmute", "EnableDeath", true, "Включить мгновенную смерть при срабатывании превращения (используя вашу плоть как материал). Если отключено, вы просто получите урон (ваша плоть частично превратится).");
			TransmuteBackpackEnabled = config.Bind<bool>("Event.Transmute", "EnableBackpack", false, "Включить превращение рюкзака в предметы");
			TransmuteMilkEnabled = config.Bind<bool>("Event.Transmute", "EnableMilk", true, "Включить превращение 'молоко/кальций' -> Обогащенное молоко");
			TransmuteCactusEnabled = config.Bind<bool>("Event.Transmute", "EnableCactus", true, "Включить превращение 'кактус' -> Кактус");
			TransmuteCoconutEnabled = config.Bind<bool>("Event.Transmute", "EnableCoconut", true, "Включить превращение 'кокос' -> Кокос");
			TransmuteAppleEnabled = config.Bind<bool>("Event.Transmute", "EnableApple", true, "Включить превращение 'яблоко/ягода' -> Хрустягоды");
			TransmuteBananaEnabled = config.Bind<bool>("Event.Transmute", "EnableBanana", true, "Включить превращение 'банан' -> Кожура");
			TransmuteEggEnabled = config.Bind<bool>("Event.Transmute", "EnableEgg", true, "Включить превращение 'яйцо' -> Яйцо");
			TransmuteFruitEnabled = config.Bind<bool>("Event.Transmute", "EnableFruit", true, "Включить превращение 'фрукт' -> Случайный фрукт");
			TransmuteMushroomEnabled = config.Bind<bool>("Event.Transmute", "EnableMushroom", true, "Включить превращение 'гриб' -> Гриб");
			TransmuteBallEnabled = config.Bind<bool>("Event.Transmute", "EnableBall", true, "Включить превращение 'мяч' -> Баскетбольный мяч");
			DeathEnabled = config.Bind<bool>("Event.Death", "Enabled", true, "Включить событие 'Смерть'.");
			DeathKeywords = config.Bind<string>("Event.Death", "Keywords", "смерть, умер, умри, труп, конец, сдохни, гроб, могила, череп, скелет, убить, гибель, мертв, финиш, хана, крышка, покойник, кости, фаталити, прикончи, убит, костлявая, суицид, скелетон, тлен, сдох, погиб, скончался, жмур, мертвец, на небеса, откинулся, преставился, ласты склеил", "Список ключевых слов, вызывающих событие смерти, разделенных запятыми.");
			HealEnabled = config.Bind<bool>("Event.Heal", "Enabled", true, "Включить событие 'Лечение'.");
			HealKeywords = config.Bind<string>("Event.Heal", "Keywords", "здоровье, хп, жизнь, жиза, лечи, хиль, хил, аптечка, медик, доктор, врач, бинт, таблетка, шприц, укол, реген, восстанови, вылечил, жив, здорово, полечи, медпункт, пластырь, стимулятор", "Список ключевых слов, вызывающих событие лечения, разделенных запятыми.");
			HealCooldown = config.Bind<float>("Event.Heal", "Cooldown", 120f, "Перезарядка в секундах для события лечения.");
			HealAmount = config.Bind<float>("Event.Heal", "Amount", 0.4f, "Процент (от 0.0 до 1.0) заполнения шкалы состояния при срабатывании.");
			ZombifyEnabled = config.Bind<bool>("Event.Zombify", "Enabled", true, "Включить событие 'Зомбификация'.");
			ZombifyKeywords = config.Bind<string>("Event.Zombify", "Keywords", "зомби, укус, мозг, гниль, зараза, вирус, нежить, мертвец, апокалипсис, мозги, ходячий, плоть, мясо, заражен, гниет, зомбак, людоед, трупоед, живой труп, кусь, вурдалак, укусил, монстр, чужой, паразит, мутант, рейк, слендер, бессмертный", "Список ключевых слов, вызывающих событие зомбификации, разделенных запятыми.");
			SleepEnabled = config.Bind<bool>("Event.Sleep", "Enabled", true, "Включить событие 'Сон'.");
			SleepKeywords = config.Bind<string>("Event.Sleep", "Keywords", "спать, сон, устал, кровать, вырубился, отдых, дремота, зевнул, бай, храп, отрубился, выдохся, спатки, сонный, подушка, поспать, дрыхнуть, соня, тихий час, спокойной ночи, боковая, баиньки, сновидение, кошмар, вздремнуть, койка, диван, матрас", "Список ключевых слов, вызывающих событие сна, разделенных запятыми.");
			DropEnabled = config.Bind<bool>("Event.Drop", "Enabled", true, "Включить событие 'Выброс предмета'.");
			DropKeywords = config.Bind<string>("Event.Drop", "Keywords", "уронил, выбросил, выронил, брось, потерял, выкинь, упс, потеря, отдай, бросил, отпусти, скинул, криворукий, растяпа, избавься, выбрось, выпало, руки дырявые, скользкие руки, не удержал, лови, кидай, дроп, дропни, выложи, положи, убери из рук", "Список ключевых слов, вызывающих событие выброса предмета, разделенных запятыми.");
			ExplodeEnabled = config.Bind<bool>("Event.Explode", "Enabled", true, "Включить событие 'Взрыв'.");
			ExplodeKeywords = config.Bind<string>("Event.Explode", "Keywords", "взрыв, бум, бомба, бабах, бах, рвануло, динамит, граната, ядерка, детонация, бабахнуло, рванет, взрывчатка, хлопок, взрывай, кабум, рвануть, мина, крипер, пластид, аллах акбар, бам, тыдыщ, петарда, салют, фейерверк, подрыв, запал, фитиль, тротил", "Список ключевых слов, вызывающих событие взрыва, разделенных запятыми.");
			ExplodeRadius = config.Bind<float>("Event.Explode", "Radius", 6f, "Радиус эффекта взрыва и урона.");
			ExplodeDamage = config.Bind<float>("Event.Explode", "DamagePercent", 0.4f, "Процент травмы (от 0.0 до 1.0), наносимый игроку.");
			ExplodeStunDuration = config.Bind<float>("Event.Explode", "StunDuration", 3f, "Длительность в секундах, на которую игрок будет оглушен/сбит с ног после взрыва.");
			ExplodeForceLowerBound = config.Bind<float>("Event.Explode", "ForceLowerBound", 2000f, "Минимально возможная сила взрыва.");
			ExplodeForceHigherBound = config.Bind<float>("Event.Explode", "ForceHigherBound", 3000f, "Максимально возможная сила взрыва.");
			SlipEnabled = config.Bind<bool>("Event.Slip", "Enabled", true, "Включить событие 'Поскальзывание'.");
			SlipKeywords = config.Bind<string>("Event.Slip", "Keywords", "упал, придурок, скользко, споткнулся, падение, качусь, блин, лед, скольжу, грохнулся, пиздец, блять, блядь, сука, хуйня, говно, ебать, ебаный, гад, скотина, урод, жопа, херня, проклятье, залупа, бля, ебать-копать, мразь, нахуй, ебанешься, ахуеть, охуеть, я хуею, выебу, выебать, манда, пидарас, гондон, шлюха, чмо, лох, дебил, даун, запнулся, равновесие, занесло, дрифт", "Список ключевых слов, вызывающих событие поскальзывания, разделенных запятыми.");
			SlipStunDuration = config.Bind<float>("Event.Slip", "StunDuration", 2f, "Длительность в секундах, на которую игрок будет оглушен/сбит с ног после поскальзывания.");
			BananaBombEnabled = config.Bind<bool>("Event.Slip", "BananaBombEnabled", true, "Включить редкую пасхалку 'Банановая бомба' при поскальзывании.");
			BananaBombChance = config.Bind<float>("Event.Slip", "BananaBombChance", 0.05f, "Шанс (0.0 - 1.0), что поскальзывание активирует 'Банановую бомбу'.");
			BananaBombAmount = config.Bind<int>("Event.Slip", "BananaBombAmount", 30, "Количество бананов, появляющихся во время 'Банановой бомбы'.");
			SacrificeEnabled = config.Bind<bool>("Event.Sacrifice", "Enabled", true, "Включить событие 'Жертвоприношение'.");
			SacrificeKeywords = config.Bind<string>("Event.Sacrifice", "Keywords", "жертва, обмен, душа, дар, оживи, воскреси, алтарь, дух, отдать, ритуал, приношение, воскрешение, пентаграмма, сатана, дьявол, сделка, кровь за кровь, жизнь за жизнь, верни, рес, ресни, подними", "Список ключевых слов, вызывающих событие жертвоприношения.");
			SacrificeCooldown = config.Bind<float>("Event.Sacrifice", "Cooldown", 300f, "Перезарядка в секундах для события жертвоприношения.");
			BlindEnabled = config.Bind<bool>("Event.Blind", "Enabled", true, "Включить событие 'Ослепление'.");
			BlindKeywords = config.Bind<string>("Event.Blind", "Keywords", "слепой, вспышка, глаза, зрение, не вижу, темно, ослеп, свет, ослепило, блик, фонарик, очи, темнота, ночь, мрак, выколи глаз, ничего не видно, черный экран, кто выключил свет, лампочка, прожектор, ярко, крот, повязка, туман войны", "Список ключевых слов, вызывающих событие ослепления.");
			BlindDuration = config.Bind<float>("Event.Blind", "Duration", 15f, "Длительность ослепления игрока в секундах.");
		}
	}
	[BepInPlugin("VoiceCurse", "VoiceCurse", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		private Config? _config;

		private VoiceHandler? _voiceHandler;

		private Harmony? _harmony;

		public const string Id = "VoiceCurse";

		private static ManualLogSource Log { get; set; }

		public static string Name => "VoiceCurse";

		public static string Version => "1.1.0";

		private void Awake()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)("Плагин " + Name + " загружается..."));
			_config = new Config(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("VoiceCurse");
			_harmony.PatchAll();
			Log.LogInfo((object)"Harmony Patches применен.");
			string text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			if (string.IsNullOrEmpty(text))
			{
				text = Paths.PluginPath;
			}
			_voiceHandler = new VoiceHandler(Log, _config, text);
			Log.LogInfo((object)("Плагин " + Name + " успешно загрузился."));
		}

		private void Update()
		{
			_voiceHandler?.Update();
		}

		private void OnDestroy()
		{
			_voiceHandler?.Dispose();
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace VoiceCurse.Voice
{
	public class VoiceHook : MonoBehaviour
	{
		private VoiceHandler? _manager;

		private Recorder? _recorder;

		private bool _hasInjected;

		public void Initialize(VoiceHandler manager, Recorder recorder)
		{
			_manager = manager;
			_recorder = recorder;
			CheckIfReady();
		}

		private void Update()
		{
			if (!_hasInjected)
			{
				CheckIfReady();
			}
		}

		private void CheckIfReady()
		{
			if (!Object.op_Implicit((Object)(object)_recorder) || _manager == null || !_recorder.IsCurrentlyTransmitting)
			{
				return;
			}
			FieldInfo field = typeof(Recorder).GetField("voice", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field == null))
			{
				object? value = field.GetValue(_recorder);
				LocalVoice val = (LocalVoice)((value is LocalVoice) ? value : null);
				if (val != null)
				{
					_manager.OnPhotonVoiceReady(_recorder, val);
					_hasInjected = true;
				}
			}
		}

		private void PhotonVoiceCreated(PhotonVoiceCreatedParams p)
		{
			if (!_hasInjected && !((Object)(object)_recorder == (Object)null))
			{
				_manager?.OnPhotonVoiceReady(_recorder, p.Voice);
				_hasInjected = true;
			}
		}
	}
	public class VoiceProcessor : IProcessor<float>, IDisposable
	{
		[CompilerGenerated]
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private IVoiceRecognizer <recognizer>P;

		[CompilerGenerated]
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private int <inputSampleRate>P;

		private const int TargetSampleRate = 16000;

		public VoiceProcessor(IVoiceRecognizer recognizer, int inputSampleRate)
		{
			<recognizer>P = recognizer;
			<inputSampleRate>P = inputSampleRate;
			base..ctor();
		}

		public float[]? Process(float[]? buf)
		{
			if (buf == null || buf.Length == 0)
			{
				return buf;
			}
			if (Math.Abs(<inputSampleRate>P - 16000) < 100)
			{
				ProcessDirect(buf);
				return buf;
			}
			float num = (float)<inputSampleRate>P / 16000f;
			int num2 = (int)((float)buf.Length / num);
			if (num2 == 0)
			{
				return buf;
			}
			short[] array = new short[num2];
			for (int i = 0; i < num2; i++)
			{
				float num3 = (float)i * num;
				int num4 = (int)num3;
				float num5 = num3 - (float)num4;
				if (num4 >= buf.Length - 1)
				{
					array[i] = FloatToShort(buf[^1]);
					continue;
				}
				float num6 = buf[num4];
				float num7 = buf[num4 + 1];
				float sample = num6 + (num7 - num6) * num5;
				array[i] = FloatToShort(sample);
			}
			<recognizer>P.FeedAudio(array, array.Length);
			return buf;
		}

		private void ProcessDirect(float[] buf)
		{
			short[] array = new short[buf.Length];
			for (int i = 0; i < buf.Length; i++)
			{
				array[i] = FloatToShort(buf[i]);
			}
			<recognizer>P.FeedAudio(array, array.Length);
		}

		private static short FloatToShort(float sample)
		{
			if (1 == 0)
			{
			}
			float num = ((sample > 1f) ? 1f : ((!(sample < -1f)) ? sample : (-1f)));
			if (1 == 0)
			{
			}
			sample = num;
			return (short)(sample * 32767f);
		}

		public void Dispose()
		{
		}
	}
	public class VoiceRecognizer : IVoiceRecognizer, IDisposable
	{
		private readonly VoskRecognizer _recognizer;

		private readonly ConcurrentQueue<short[]> _audioQueue = new ConcurrentQueue<short[]>();

		private Thread? _workerThread;

		private volatile bool _isRunning;

		private const int MaxQueueSize = 50;

		public event Action<string>? OnPhraseRecognized;

		public event Action<string>? OnPartialResult;

		public VoiceRecognizer(Model model, float sampleRate)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			try
			{
				_recognizer = new VoskRecognizer(model, sampleRate);
				_recognizer.SetMaxAlternatives(0);
				_recognizer.SetWords(true);
				Debug.Log((object)$"[VoiceCurse] Инициализация VoskRecognizer с частотой: {sampleRate} Hz");
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Ошибка создания VoskRecognizer: " + ex.Message));
				throw;
			}
		}

		public void Start()
		{
			if (!_isRunning)
			{
				_isRunning = true;
				_workerThread = new Thread(ProcessAudioLoop)
				{
					IsBackground = true,
					Name = "VoiceCurse Worker"
				};
				_workerThread.Start();
			}
		}

		public void Stop()
		{
			_isRunning = false;
			Thread workerThread = _workerThread;
			if (workerThread != null && workerThread.IsAlive)
			{
				_workerThread.Join(500);
			}
		}

		public void FeedAudio(short[] pcmData, int length)
		{
			if (!_isRunning)
			{
				return;
			}
			if (_audioQueue.Count >= 50)
			{
				short[] result;
				while (_audioQueue.TryDequeue(out result))
				{
				}
			}
			_audioQueue.Enqueue(pcmData);
		}

		private void ProcessAudioLoop()
		{
			while (_isRunning)
			{
				if (_audioQueue.TryDequeue(out short[] result))
				{
					try
					{
						if (_recognizer.AcceptWaveform(result, result.Length))
						{
							string json = _recognizer.Result();
							ExtractAndFire(json, isPartial: false);
						}
						else
						{
							string json2 = _recognizer.PartialResult();
							ExtractAndFire(json2, isPartial: true);
						}
					}
					catch (Exception ex)
					{
						Debug.LogError((object)("[VoiceCurse] Vosk ошибка: " + ex.Message));
					}
				}
				else
				{
					Thread.Sleep(10);
				}
			}
		}

		private void ExtractAndFire(string json, bool isPartial)
		{
			if (string.IsNullOrEmpty(json))
			{
				return;
			}
			string text = (isPartial ? "\"partial\"" : "\"text\"");
			int num = json.IndexOf(text + " :", StringComparison.Ordinal);
			if (num == -1)
			{
				num = json.IndexOf(text + ":", StringComparison.Ordinal);
			}
			if (num == -1)
			{
				return;
			}
			int num2 = json.IndexOf("\"", num + text.Length + 1, StringComparison.Ordinal) + 1;
			int num3 = json.LastIndexOf("\"", StringComparison.Ordinal);
			if (num3 <= num2)
			{
				return;
			}
			string text2 = json.Substring(num2, num3 - num2);
			if (!string.IsNullOrWhiteSpace(text2))
			{
				if (isPartial)
				{
					this.OnPartialResult?.Invoke(text2);
				}
				else
				{
					this.OnPhraseRecognized?.Invoke(text2);
				}
			}
		}

		public void Dispose()
		{
			Stop();
			_recognizer.Dispose();
		}
	}
}
namespace VoiceCurse.Interfaces
{
	public interface IVoiceEvent
	{
		bool TryExecute(string spokenWord, string fullSentence);

		void PlayEffects(Vector3 position);

		void PlayEffects(Character origin, Vector3 position, string detail);
	}
	public interface IVoiceRecognizer : IDisposable
	{
		event Action<string> OnPhraseRecognized;

		event Action<string> OnPartialResult;

		void FeedAudio(short[] pcmData, int length);

		void Start();

		void Stop();
	}
}
namespace VoiceCurse.Handlers
{
	public class EventHandler
	{
		public static readonly Dictionary<string, IVoiceEvent> Events = new Dictionary<string, IVoiceEvent>();

		private readonly Dictionary<string, int> _previousWordCounts = new Dictionary<string, int>();

		public EventHandler(Config config)
		{
			Events.Clear();
			RegisterEvents(config);
		}

		private static void RegisterEvents(Config config)
		{
			IEnumerable<Type> enumerable = from t in Assembly.GetExecutingAssembly().GetTypes()
				where typeof(VoiceEventBase).IsAssignableFrom(t) && !t.IsAbstract && t.IsClass
				select t;
			foreach (Type item in enumerable)
			{
				try
				{
					if (Activator.CreateInstance(item, config) is IVoiceEvent value)
					{
						string text = item.Name.Replace("Event", "");
						Events[text] = value;
						if (config.EnableDebugLogs.Value)
						{
							Debug.Log((object)("[VoiceCurseRu] Ивент зарегистрирован: " + text));
						}
					}
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("[VoiceCurse] Ошибка регистрации ивента " + item.Name + ": " + ex.Message));
				}
			}
		}

		public void HandleSpeech(string text, bool isFinal)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				return;
			}
			string text2 = text.ToLowerInvariant();
			string[] array = text2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			string[] array2 = array;
			string key;
			int value;
			foreach (string text3 in array2)
			{
				dictionary.TryAdd(text3, 0);
				key = text3;
				value = dictionary[key]++;
			}
			foreach (KeyValuePair<string, int> item in dictionary)
			{
				item.Deconstruct(out key, out value);
				string text4 = key;
				int num = value;
				int num2 = 0;
				if (_previousWordCounts.TryGetValue(text4, out var value2))
				{
					num2 = value2;
				}
				int num3 = num - num2;
				if (num3 <= 0)
				{
					continue;
				}
				for (int j = 0; j < num3; j++)
				{
					foreach (IVoiceEvent value3 in Events.Values)
					{
						value3.TryExecute(text4, text2);
					}
				}
			}
			_previousWordCounts.Clear();
			foreach (KeyValuePair<string, int> item2 in dictionary)
			{
				_previousWordCounts[item2.Key] = item2.Value;
			}
			if (isFinal)
			{
				_previousWordCounts.Clear();
			}
		}
	}
	public class NetworkHandler : IOnEventCallback
	{
		private const byte VoiceCurseEventCode = 187;

		private static MonoBehaviour? _connectionLog;

		private static MethodInfo? _addMessageMethod;

		private static Dictionary<string, string> engToRuWords = new Dictionary<string, string>
		{
			{ "Slip", "Скольжение" },
			{ "Heal", "Лечение" },
			{ "Affliction", "Бедствие" },
			{ "Sleep", "Сон" },
			{ "Launch", "Полёт" },
			{ "Zombify", "Зомбифицирование" },
			{ "Trasmute", "Превращение" },
			{ "Sacrifice", "Жертвоприношение" },
			{ "Explode", "Взрыв" },
			{ "Death", "Смерть" },
			{ "Blind", "Слепота" },
			{ "Drop", "Уронить" },
			{ "Forward", "Вперёд" },
			{ "Back", "Назад" },
			{ "Right", "Вправо" },
			{ "Left", "Влево" },
			{ "Up", "Вверх" },
			{ "Cold", "Холод" },
			{ "Hot", "Жара" },
			{ "Injury", "Урон" },
			{ "Hunger", "Голод" },
			{ "Poison", "Яд" },
			{ "Spores", "Споры" }
		};

		public static void SendCurseEvent(string spokenWord, string matchedKeyword, string eventName, string? detail, string? payload, Vector3 position)
		{
			//IL_0034: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			object[] array = new object[7]
			{
				PhotonNetwork.LocalPlayer.ActorNumber,
				spokenWord,
				matchedKeyword,
				eventName,
				detail ?? string.Empty,
				position,
				payload ?? string.Empty
			};
			RaiseEventOptions val = new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)1
			};
			SendOptions val2 = default(SendOptions);
			((SendOptions)(ref val2)).Reliability = true;
			SendOptions val3 = val2;
			PhotonNetwork.RaiseEvent((byte)187, (object)array, val, val3);
		}

		public void OnEvent(EventData photonEvent)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent.Code != 187)
			{
				return;
			}
			object[] array = (object[])photonEvent.CustomData;
			int num = (int)array[0];
			string fullWord = (string)array[1];
			string keyword = (string)array[2];
			string text = (string)array[3];
			string text2 = (string)array[4];
			Vector3 position = (Vector3)array[5];
			string text3 = ((array.Length > 6) ? ((string)array[6]) : string.Empty);
			string playerName = "Unknown";
			Color color = Color.white;
			Player player = PhotonNetwork.CurrentRoom.GetPlayer(num, false);
			if (player != null)
			{
				playerName = player.NickName;
			}
			Character val = FindCharacterByActorNumber(num);
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.refs?.customization))
			{
				color = val.refs.customization.PlayerColor;
			}
			DisplayNotification(playerName, color, fullWord, keyword, text, text2);
			if (EventHandler.Events.TryGetValue(text, out IVoiceEvent value))
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					string detail = ((!string.IsNullOrEmpty(text3)) ? text3 : text2);
					value.PlayEffects(val, position, detail);
				}
				else
				{
					value.PlayEffects(position);
				}
			}
		}

		private static Character? FindCharacterByActorNumber(int actorNumber)
		{
			return ((IEnumerable<Character>)Character.AllCharacters).FirstOrDefault((Func<Character, bool>)((Character c) => ((MonoBehaviourPun)c).photonView.OwnerActorNr == actorNumber));
		}

		private static void DisplayNotification(string playerName, Color color, string fullWord, string keyword, string eventName, string detail)
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_connectionLog))
			{
				Object obj = Object.FindFirstObjectByType(Type.GetType("PlayerConnectionLog, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
				_connectionLog = (MonoBehaviour?)(((object)((obj is MonoBehaviour) ? obj : null)) ?? ((object)((IEnumerable<MonoBehaviour>)Object.FindObjectsByType<MonoBehaviour>((FindObjectsSortMode)0)).FirstOrDefault((Func<MonoBehaviour, bool>)((MonoBehaviour m) => ((object)m).GetType().Name == "PlayerConnectionLog"))));
				_addMessageMethod = null;
			}
			if (!Object.op_Implicit((Object)(object)_connectionLog))
			{
				return;
			}
			if (_addMessageMethod == null)
			{
				_addMessageMethod = ((object)_connectionLog).GetType().GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			if (_addMessageMethod == null)
			{
				return;
			}
			string text = "#" + ColorUtility.ToHtmlStringRGB(color);
			string text2 = fullWord;
			int num = fullWord.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				string text3 = fullWord.Substring(0, num);
				string text4 = fullWord.Substring(num, keyword.Length);
				int num2 = num + keyword.Length;
				string text5 = fullWord.Substring(num2, fullWord.Length - num2);
				text2 = text3 + "<color=#8B0000>" + text4 + "</color>" + text5;
			}
			string text6 = "<color=" + text + ">" + playerName + " сказал \"" + text2 + "\" что запустило </color><color=#FFA500>" + (engToRuWords.ContainsKey(eventName) ? engToRuWords[eventName] : eventName) + "</color><color=#FAFA33>" + (string.IsNullOrEmpty(detail) ? "" : (" (" + (engToRuWords.ContainsKey(detail) ? engToRuWords[detail] : detail) + ")")) + "</color>";
			try
			{
				_addMessageMethod.Invoke(_connectionLog, new object[1] { text6 });
			}
			catch
			{
				_connectionLog = null;
			}
		}
	}
	public class VoiceHandler : IDisposable
	{
		private readonly ManualLogSource _log;

		private readonly Config _config;

		private IVoiceRecognizer? _recognizer;

		private EventHandler? _eventHandler;

		private NetworkHandler? _networker;

		private Model? _voskModel;

		private VoiceHook? _activeHook;

		private readonly ConcurrentQueue<Action> _mainThreadActions = new ConcurrentQueue<Action>();

		private volatile string _lastPartialText = "";

		[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
		private static extern bool SetDllDirectory(string lpPathName);

		public VoiceHandler(ManualLogSource logger, Config config, string pluginDir)
		{
			_log = logger;
			_config = config;
			Initialize(pluginDir);
		}

		private void Initialize(string pluginDir)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			_log.LogInfo((object)"Инициализация менеджера VoiceCurseRu...");
			if (Directory.Exists(pluginDir))
			{
				SetDllDirectory(pluginDir);
			}
			_eventHandler = new EventHandler(_config);
			_networker = new NetworkHandler();
			PhotonNetwork.AddCallbackTarget((object)_networker);
			string text = Path.Combine(pluginDir, "model-ru-ru");
			if (Directory.Exists(text))
			{
				try
				{
					_voskModel = new Model(text);
					_log.LogInfo((object)"Vosk Model loaded successfully.");
					return;
				}
				catch (Exception ex)
				{
					_log.LogError((object)("Ошибка запуска Vosk Model: " + ex.Message));
					return;
				}
			}
			_log.LogError((object)("Vosk model не найден: " + text));
		}

		public void Update()
		{
			Action result;
			while (_mainThreadActions.TryDequeue(out result))
			{
				result();
			}
			if (!Object.op_Implicit((Object)(object)_activeHook) && Object.op_Implicit((Object)(object)Character.localCharacter))
			{
				TryHookIntoPhotonVoice();
			}
		}

		private void TryHookIntoPhotonVoice()
		{
			PhotonVoiceView component = ((Component)Character.localCharacter).GetComponent<PhotonVoiceView>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.RecorderInUse))
			{
				Recorder recorderInUse = component.RecorderInUse;
				VoiceHook voiceHook = ((Component)recorderInUse).gameObject.AddComponent<VoiceHook>();
				voiceHook.Initialize(this, recorderInUse);
				_activeHook = voiceHook;
				_log.LogInfo((object)("[VoiceCurseRu] Hooked into Recorder on: " + ((Object)((Component)recorderInUse).gameObject).name));
			}
		}

		public void OnPhotonVoiceReady(Recorder recorder, LocalVoice voice)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			int num = 48000;
			VoiceInfo info = voice.Info;
			if (((VoiceInfo)(ref info)).SamplingRate > 0)
			{
				info = voice.Info;
				num = ((VoiceInfo)(ref info)).SamplingRate;
			}
			_log.LogInfo((object)$"[VoiceCurseRu] Photon Input Rate: {num} Hz. Initializing Vosk at 16000 Hz.");
			SetupVoiceRecognition();
			if (_recognizer is VoiceRecognizer && voice is LocalVoiceAudio<float> val)
			{
				((LocalVoiceFramed<float>)(object)val).AddPostProcessor(new IProcessor<float>[1]
				{
					new VoiceProcessor(_recognizer, num)
				});
				_log.LogInfo((object)$"[VoiceCurseRu] Audio Processor attached. Resampling {num} -> 16000 Hz.");
			}
			else
			{
				_log.LogWarning((object)("[VoiceCurseRu] Could not attach processor. Voice type: " + ((object)voice).GetType().Name));
			}
		}

		private void SetupVoiceRecognition()
		{
			if (_recognizer != null || _voskModel == null)
			{
				return;
			}
			try
			{
				_recognizer = new VoiceRecognizer(_voskModel, 16000f);
				_recognizer.OnPhraseRecognized += delegate(string text)
				{
					string text2 = text;
					_lastPartialText = "";
					_mainThreadActions.Enqueue(delegate
					{
						_log.LogInfo((object)("[Recognized]: " + text2));
						_eventHandler?.HandleSpeech(text2, isFinal: true);
					});
				};
				_recognizer.OnPartialResult += delegate(string text)
				{
					if (!string.IsNullOrWhiteSpace(text) && text.Length >= 2 && !(_lastPartialText == text))
					{
						_lastPartialText = text;
						string captured = text;
						_mainThreadActions.Enqueue(delegate
						{
							_log.LogInfo((object)("[Partial]: " + captured));
							_eventHandler?.HandleSpeech(captured, isFinal: false);
						});
					}
				};
				_recognizer.Start();
				_log.LogInfo((object)"[VoiceCurse] Vosk Recognizer запустился.");
			}
			catch (Exception ex)
			{
				_log.LogError((object)("Ошибка запуска Vosk Recognizer: " + ex.Message));
			}
		}

		public void Dispose()
		{
			if (_networker != null)
			{
				PhotonNetwork.RemoveCallbackTarget((object)_networker);
			}
			_recognizer?.Stop();
			_recognizer?.Dispose();
			Model? voskModel = _voskModel;
			if (voskModel != null)
			{
				voskModel.Dispose();
			}
			_log.LogInfo((object)"VoiceCurse Manager отключился.");
		}
	}
}
namespace VoiceCurse.Events
{
	public class AfflictionEvent : VoiceEventBase
	{
		private readonly Dictionary<string, STATUSTYPE> _wordToType;

		public AfflictionEvent(Config config)
			: base(config)
		{
			_wordToType = new Dictionary<string, STATUSTYPE>();
			LoadKeywordsForType(config.AfflictionKeywordsInjury.Value, (STATUSTYPE)0);
			LoadKeywordsForType(config.AfflictionKeywordsHunger.Value, (STATUSTYPE)1);
			LoadKeywordsForType(config.AfflictionKeywordsCold.Value, (STATUSTYPE)2);
			LoadKeywordsForType(config.AfflictionKeywordsHot.Value, (STATUSTYPE)8);
			LoadKeywordsForType(config.AfflictionKeywordsPoison.Value, (STATUSTYPE)3);
			LoadKeywordsForType(config.AfflictionKeywordsSpores.Value, (STATUSTYPE)10);
		}

		private void LoadKeywordsForType(string configLine, STATUSTYPE type)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			IEnumerable<string> enumerable = from w in configLine.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select w.Trim().ToLowerInvariant() into w
				where !string.IsNullOrWhiteSpace(w)
				select w;
			foreach (string item in enumerable)
			{
				_wordToType[item] = type;
			}
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.AfflictionEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> keys = _wordToType.Keys;
				result = keys;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Invalid comparison between Unknown and I4
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Invalid comparison between Unknown and I4
			if (!Config.AfflictionEnabled.Value)
			{
				return false;
			}
			if (player.refs?.afflictions == null)
			{
				return false;
			}
			if (player.data.dead || player.data.fullyPassedOut)
			{
				return false;
			}
			if (!_wordToType.TryGetValue(matchedKeyword, out var value))
			{
				return false;
			}
			base.ExecutionDetail = ((object)(STATUSTYPE)(ref value)).ToString();
			bool value2 = Config.AfflictionTemperatureSwapEnabled.Value;
			bool flag = value2;
			if (flag)
			{
				bool flag2 = (((int)value == 2 || (int)value == 8) ? true : false);
				flag = flag2;
			}
			if (flag)
			{
				HandleTemperatureExchange(player, value);
			}
			float num = Random.Range(Config.AfflictionMinPercent.Value, Config.AfflictionMaxPercent.Value);
			if (Config.EnableDebugLogs.Value)
			{
				Debug.Log((object)$"[VoiceCurse] Affliction Specifics: {value} ({num:P0})");
			}
			player.refs.afflictions.AddStatus(value, num, false, true);
			return true;
		}

		private void HandleTemperatureExchange(Character player, STATUSTYPE incomingType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0085: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			STATUSTYPE val = (STATUSTYPE)(((int)incomingType == 8) ? 2 : 8);
			float currentStatus = player.refs.afflictions.GetCurrentStatus(val);
			if (!(currentStatus <= 0.01f))
			{
				if (Config.EnableDebugLogs.Value)
				{
					Debug.Log((object)$"[VoiceCurse] Swapping {val} ({currentStatus:P0}) to {incomingType}");
				}
				player.refs.afflictions.SubtractStatus(val, currentStatus, false, false);
				player.refs.afflictions.AddStatus(incomingType, currentStatus, false, true);
			}
		}
	}
	public class BlindEvent : VoiceEventBase
	{
		[CompilerGenerated]
		private sealed class <BlindnessRoutine>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Character player;

			public BlindEvent <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (Time.time < <>4__this._blindEndTime && Object.op_Implicit((Object)(object)player) && !player.data.dead)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if (Object.op_Implicit((Object)(object)player))
				{
					ToggleBlindness(player, enable: false);
				}
				<>4__this._blindRoutine = null;
				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 readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.BlindKeywords.Value);

		private float _blindEndTime;

		private Coroutine? _blindRoutine;

		public BlindEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.BlindEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> keywords = _keywords;
				result = keywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.BlindEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			float value = Config.BlindDuration.Value;
			_blindEndTime = Time.time + value;
			if (_blindRoutine == null)
			{
				ToggleBlindness(player, enable: true);
				_blindRoutine = ((MonoBehaviour)player).StartCoroutine(BlindnessRoutine(player));
			}
			player.AddIllegalStatus("BLIND", value);
			return true;
		}

		[IteratorStateMachine(typeof(<BlindnessRoutine>d__6))]
		private IEnumerator BlindnessRoutine(Character player)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BlindnessRoutine>d__6(0)
			{
				<>4__this = this,
				player = player
			};
		}

		private static void ToggleBlindness(Character player, bool enable)
		{
			if (Object.op_Implicit((Object)(object)player) && player.refs != null && Object.op_Implicit((Object)(object)player.refs.customization) && Object.op_Implicit((Object)(object)player.refs.customization.refs))
			{
				Renderer blindRenderer = player.refs.customization.refs.blindRenderer;
				if (Object.op_Implicit((Object)(object)blindRenderer))
				{
					((Component)blindRenderer).gameObject.SetActive(enable);
				}
			}
		}
	}
	public class DeathEvent : VoiceEventBase
	{
		private readonly HashSet<string> _deathKeywords = VoiceEventBase.ParseKeywords(config.DeathKeywords.Value);

		public DeathEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.DeathEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> deathKeywords = _deathKeywords;
				result = deathKeywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.DeathEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			player.DieInstantly();
			return true;
		}
	}
	public class DropEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.DropKeywords.Value);

		public DropEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.DropEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> keywords = _keywords;
				result = keywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			return Config.DropEnabled.Value && !player.data.dead;
		}

		public override void PlayEffects(Character origin, Vector3 position)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient || !Object.op_Implicit((Object)(object)origin) || origin.data.dead)
			{
				return;
			}
			ScatterBackpackContents(origin);
			Transform transform = ((Component)origin.GetBodypart((BodypartType)0)).transform;
			Vector3 val = transform.forward;
			if (Vector3.Dot(val, Vector3.up) < 0f)
			{
				val = -val;
			}
			Vector3 val2 = origin.Center + val * 0.6f + Vector3.up * 0.5f;
			for (byte b = 0; b < 4; b++)
			{
				if (!origin.player.GetItemSlot(b).IsEmpty())
				{
					origin.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val2 });
					val2 += Vector3.up * 0.3f;
				}
			}
			origin.refs.items.photonView.RPC("EquipSlotRpc", (RpcTarget)0, new object[2] { -1, -1 });
		}

		private static void ScatterBackpackContents(Character player)
		{
			//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)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			ItemSlot itemSlot = player.player.GetItemSlot((byte)3);
			BackpackData val = default(BackpackData);
			if (itemSlot.IsEmpty() || !itemSlot.data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val))
			{
				return;
			}
			Vector3 center = player.Center;
			ItemSlot[] itemSlots = val.itemSlots;
			PhotonView val5 = default(PhotonView);
			foreach (ItemSlot val2 in itemSlots)
			{
				if (val2.IsEmpty())
				{
					continue;
				}
				string prefabName = val2.GetPrefabName();
				if (!string.IsNullOrEmpty(prefabName))
				{
					Vector3 val3 = center + Random.insideUnitSphere * 0.5f;
					val3.y = center.y + 0.5f;
					GameObject val4 = PhotonNetwork.Instantiate("0_Items/" + prefabName, val3, Quaternion.identity, (byte)0, (object[])null);
					if (val4.TryGetComponent<PhotonView>(ref val5))
					{
						val5.RPC("SetItemInstanceDataRPC", (RpcTarget)0, new object[1] { val2.data });
						val5.RPC("SetKinematicRPC", (RpcTarget)0, new object[3]
						{
							false,
							val3,
							Quaternion.identity
						});
					}
					val2.EmptyOut();
				}
			}
		}
	}
	public class ExplodeEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.ExplodeKeywords.Value);

		private static GameObject? _cachedExplosionPrefab;

		public ExplodeEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.ExplodeEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> keywords = _keywords;
				result = keywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.ExplodeEnabled.Value)
			{
				return false;
			}
			return !player.data.dead;
		}

		public override void PlayEffects(Vector3 position)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_006a: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_cachedExplosionPrefab))
			{
				FindExplosionPrefab();
			}
			if (Object.op_Implicit((Object)(object)_cachedExplosionPrefab))
			{
				Object.Instantiate<GameObject>(_cachedExplosionPrefab, position, Quaternion.identity);
			}
			Character localCharacter = Character.localCharacter;
			if (!Object.op_Implicit((Object)(object)localCharacter) || localCharacter.data.dead)
			{
				return;
			}
			float num = Vector3.Distance(localCharacter.Center, position);
			if (num <= Config.ExplodeRadius.Value)
			{
				if (Object.op_Implicit((Object)(object)localCharacter.refs.afflictions))
				{
					localCharacter.refs.afflictions.AddStatus((STATUSTYPE)0, Config.ExplodeDamage.Value, false, true);
				}
				localCharacter.Fall(Config.ExplodeStunDuration.Value, 0f);
				Vector3 val = localCharacter.Center - position;
				Vector3 val2 = ((Vector3)(ref val)).normalized;
				val2 += Vector3.up * 0.6f;
				((Vector3)(ref val2)).Normalize();
				float num2 = Random.Range(Config.ExplodeForceLowerBound.Value, Config.ExplodeForceHigherBound.Value);
				localCharacter.AddForce(val2 * num2, 1f, 1f);
			}
		}

		private static void FindExplosionPrefab()
		{
			Dynamite val = Resources.FindObjectsOfTypeAll<Dynamite>().FirstOrDefault();
			if (Object.op_Implicit((Object)(object)val))
			{
				_cachedExplosionPrefab = val.explosionPrefab;
			}
		}
	}
	public class HealEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.HealKeywords.Value);

		private float _lastHealTime = -999f;

		public HealEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.HealEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> keywords = _keywords;
				result = keywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.HealEnabled.Value)
			{
				return false;
			}
			if (player.data.dead || player.data.fullyPassedOut)
			{
				return false;
			}
			if (Time.time < _lastHealTime + Config.HealCooldown.Value)
			{
				Debug.Log((object)"[VoiceCurse] Cooldown active, cannot heal now.");
				return false;
			}
			_lastHealTime = Time.time;
			player.refs.afflictions.SubtractStatus((STATUSTYPE)0, Config.HealAmount.Value, false, false);
			player.refs.afflictions.SubtractStatus((STATUSTYPE)10, Config.HealAmount.Value, false, false);
			player.refs.afflictions.SubtractStatus((STATUSTYPE)2, Config.HealAmount.Value, false, false);
			player.refs.afflictions.SubtractStatus((STATUSTYPE)6, Config.HealAmount.Value, false, false);
			player.refs.afflictions.SubtractStatus((STATUSTYPE)8, Config.HealAmount.Value, false, false);
			player.refs.afflictions.SubtractStatus((STATUSTYPE)3, Config.HealAmount.Value, false, false);
			player.refs.afflictions.SubtractStatus((STATUSTYPE)9, Config.HealAmount.Value, false, false);
			return true;
		}
	}
	public class LaunchEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.LaunchKeywords.Value);

		private static GameObject? _cachedLaunchSFX;

		public LaunchEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.LaunchEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> keywords = _keywords;
				result = keywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: 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)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.LaunchEnabled.Value)
			{
				return false;
			}
			if (player.data.dead || player.data.fullyPassedOut)
			{
				return false;
			}
			if (_cachedLaunchSFX == null)
			{
				FindLaunchSFX();
			}
			player.Fall(Config.LaunchStunDuration.Value, 0f);
			Vector3 normalized = ((Vector3)(ref player.data.lookDirection_Flat)).normalized;
			Vector3 val = Vector3.Cross(Vector3.up, normalized);
			string executionDetail;
			Vector3 val2;
			if (fullSentence.Contains("влево") || fullSentence.Contains("налево"))
			{
				executionDetail = "Left";
				val2 = -val + Vector3.up * 0.2f;
			}
			else if (fullSentence.Contains("вправо") || fullSentence.Contains("направо"))
			{
				executionDetail = "Right";
				val2 = val + Vector3.up * 0.2f;
			}
			else if (fullSentence.Contains("взад") || fullSentence.Contains("назад") || fullSentence.Contains("сзади"))
			{
				executionDetail = "Back";
				val2 = -normalized + Vector3.up * 0.2f;
			}
			else if (fullSentence.Contains("вперёд") || fullSentence.Contains("вперед") || fullSentence.Contains("впереди"))
			{
				executionDetail = "Forward";
				val2 = normalized + Vector3.up * 0.2f;
			}
			else if (fullSentence.Contains("вверх") || fullSentence.Contains("наверх"))
			{
				executionDetail = "Up";
				val2 = Vector3.up;
			}
			else
			{
				executionDetail = "Random";
				val2 = GetRandomUpwardDirection();
			}
			base.ExecutionDetail = executionDetail;
			((Vector3)(ref val2)).Normalize();
			float num = Random.Range(Config.LaunchForceLowerBound.Value, Config.LaunchForceHigherBound.Value);
			Vector3 val3 = val2 * num;
			player.AddForce(val3, 1f, 1f);
			return true;
		}

		private static Vector3 GetRandomUpwardDirection()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			Vector3 onUnitSphere = Random.onUnitSphere;
			onUnitSphere.y = Mathf.Abs(onUnitSphere.y);
			if (onUnitSphere.y < 0.5f)
			{
				onUnitSphere.y = 0.5f;
			}
			return onUnitSphere;
		}

		public override void PlayEffects(Vector3 position)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_cachedLaunchSFX))
			{
				FindLaunchSFX();
			}
			if (Object.op_Implicit((Object)(object)_cachedLaunchSFX))
			{
				GameObject val = Object.Instantiate<GameObject>(_cachedLaunchSFX, position, Quaternion.identity);
				val.SetActive(true);
				Object.Destroy((Object)(object)val, 5f);
			}
		}

		private static void FindLaunchSFX()
		{
			ScoutCannon val = Resources.FindObjectsOfTypeAll<ScoutCannon>().FirstOrDefault();
			if (val != null)
			{
				_cachedLaunchSFX = val.fireSFX;
			}
		}
	}
	public class SacrificeEvent : VoiceEventBase
	{
		private readonly HashSet<string> _sacrificeKeywords = VoiceEventBase.ParseKeywords(config.SacrificeKeywords.Value);

		private float _lastSacrificeTime = -999f;

		public SacrificeEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.SacrificeEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> sacrificeKeywords = _sacrificeKeywords;
				result = sacrificeKeywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0072: 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_009f: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.SacrificeEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			if (Time.time < _lastSacrificeTime + Config.SacrificeCooldown.Value)
			{
				Debug.Log((object)"[VoiceCurse] Cooldown active, cannot sacrifice now.");
				return false;
			}
			Vector3 deathPos;
			Character closestDeadPlayer = DeathTracker.GetClosestDeadPlayer(player.Center, out deathPos);
			if (!Object.op_Implicit((Object)(object)closestDeadPlayer))
			{
				return false;
			}
			_lastSacrificeTime = Time.time;
			Vector3 val = deathPos + Vector3.up * 1f;
			base.ExecutionDetail = "Reviving " + closestDeadPlayer.characterName;
			closestDeadPlayer.view.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[2] { val, true });
			DeathTracker.RemoveDeath(closestDeadPlayer);
			player.DieInstantly();
			return true;
		}
	}
	[HarmonyPatch(typeof(Character))]
	public static class DeathTracker
	{
		private static readonly Dictionary<int, Vector3> DeathLocations = new Dictionary<int, Vector3>();

		[HarmonyPatch("RPCA_Die")]
		[HarmonyPrefix]
		private static void OnDiePrefix(Character __instance)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)__instance))
			{
				DeathLocations[((MonoBehaviourPun)__instance).photonView.ViewID] = __instance.Center;
			}
		}

		[HarmonyPatch("RPCA_Revive")]
		[HarmonyPostfix]
		private static void OnRevivePostfix(Character __instance)
		{
			RemoveDeath(__instance);
		}

		[HarmonyPatch("RPCA_ReviveAtPosition")]
		[HarmonyPostfix]
		private static void OnReviveAtPosPostfix(Character __instance)
		{
			RemoveDeath(__instance);
		}

		public static void RemoveDeath(Character c)
		{
			if (Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)((MonoBehaviourPun)c).photonView))
			{
				DeathLocations.Remove(((MonoBehaviourPun)c).photonView.ViewID);
			}
		}

		public static Character? GetClosestDeadPlayer(Vector3 origin, out Vector3 deathPos)
		{
			//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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			Character result = null;
			float num = float.MaxValue;
			deathPos = Vector3.zero;
			foreach (Character item in Character.AllCharacters.Where((Character c) => c.data.dead))
			{
				Vector3 val;
				if (DeathLocations.TryGetValue(((MonoBehaviourPun)item).photonView.ViewID, out var value))
				{
					val = value;
				}
				else
				{
					if (!Object.op_Implicit((Object)(object)item.Ghost))
					{
						continue;
					}
					val = ((Component)item.Ghost).transform.position;
				}
				float num2 = Vector3.Distance(origin, val);
				if (num2 < num)
				{
					num = num2;
					result = item;
					deathPos = val;
				}
			}
			return result;
		}
	}
	public class SleepEvent : VoiceEventBase
	{
		private readonly HashSet<string> _sleepKeywords = VoiceEventBase.ParseKeywords(config.SleepKeywords.Value);

		public SleepEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.SleepEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> sleepKeywords = _sleepKeywords;
				result = sleepKeywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.SleepEnabled.Value)
			{
				return false;
			}
			if (player.data.passedOut || player.data.dead)
			{
				return false;
			}
			player.PassOutInstantly();
			return true;
		}
	}
	public class SlipEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.SlipKeywords.Value);

		private static AudioClip? _cachedTripSound;

		private Item? _cachedBananaItem;

		private static readonly Regex NameCleaner = new Regex("\\s*\\((\\d+|Clone)\\)", RegexOptions.Compiled);

		public SlipEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.SlipEnabled.Value)
			{
				result = Enumerable.Empty<string>();
			}
			else
			{
				IEnumerable<string> keywords = _keywords;
				result = keywords;
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00d4: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.SlipEnabled.Value)
			{
				return false;
			}
			if (player.data.dead || player.data.fullyPassedOut)
			{
				return false;
			}
			if (Config.BananaBombEnabled.Value && Random.value <= Config.BananaBombChance.Value)
			{
				base.ExecutionDetail = "BananaBomb";
			}
			player.Fall(Config.SlipStunDuration.Value, 0f);
			Vector3 lookDirection_Flat = player.data.lookDirection_Flat;
			ApplyForceToPart(player, (BodypartType)16, (lookDirection_Flat + Vector3.up) * 200f);
			ApplyForceToPart(player, (BodypartType)13, (lookDirection_Flat + Vector3.up) * 200f);
			ApplyForceToPart(player, (BodypartType)0, Vector3.up * 1500f);
			ApplyForceToPart(player, (BodypartType)4, lookDirection_Flat * -300f);
			return true;
		}

		private static void ApplyForceToPart(Character player, BodypartType partType, Vector3 force)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody bodypartRig = player.GetBodypartRig(partType);
			if (Object.op_Implicit((Object)(object)bodypartRig))
			{
				bodypartRig.AddForce(force, (ForceMode)1);
			}
		}

		public override void PlayEffects(Character origin, Vector3 position, string detail)
		{
			//IL_0003: 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)
			base.PlayEffects(origin, position, detail);
			if (detail == "BananaBomb")
			{
				SpawnBananaBomb(position);
			}
		}

		public override void PlayEffects(Vector3 position)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			AudioClip tripSound = GetTripSound();
			if (Object.op_Implicit((Object)(object)tripSound))
			{
				AudioSource.PlayClipAtPoint(tripSound, position);
			}
		}

		private void SpawnBananaBomb(Vector3 origin)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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_015c: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			Item bananaItem = GetBananaItem();
			if (!Object.op_Implicit((Object)(object)bananaItem))
			{
				if (Config.EnableDebugLogs.Value)
				{
					Debug.LogWarning((object)"[VoiceCurseRu] 'Банановая желтая кожура' не найдена для Банановой бомбы.");
				}
				return;
			}
			string text = NameCleaner.Replace(((Object)bananaItem).name, "").Trim();
			string text2 = "0_Items/" + text;
			int value = Config.BananaBombAmount.Value;
			PhotonView val3 = default(PhotonView);
			Rigidbody val4 = default(Rigidbody);
			for (int i = 0; i < value; i++)
			{
				Vector3 val = origin + Random.insideUnitSphere * 3f;
				val.y = origin.y + 1.5f;
				GameObject val2 = PhotonNetwork.Instantiate(text2, val, Quaternion.identity, (byte)0, (object[])null);
				if (Object.op_Implicit((Object)(object)val2) && val2.TryGetComponent<PhotonView>(ref val3))
				{
					val3.RPC("SetKinematicRPC", (RpcTarget)0, new object[3]
					{
						false,
						val,
						Quaternion.identity
					});
					Vector3 randomUpwardDirection = GetRandomUpwardDirection();
					float num = Random.Range(25f, 200f);
					if (val2.TryGetComponent<Rigidbody>(ref val4))
					{
						val4.isKinematic = false;
						val4.AddForce(randomUpwardDirection * num, (ForceMode)1);
					}
				}
			}
		}

		private static Vector3 GetRandomUpwardDirection()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Vector3 onUnitSphere = Random.onUnitSphere;
			onUnitSphere.y = Mathf.Abs(onUnitSphere.y);
			if (onUnitSphere.y < 0.2f)
			{
				onUnitSphere.y = 0.5f;
			}
			return ((Vector3)(ref onUnitSphere)).normalized;
		}

		private Item? GetBananaItem()
		{
			if (Object.op_Implicit((Object)(object)_cachedBananaItem))
			{
				return _cachedBananaItem;
			}
			_cachedBananaItem = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item i) => ((Object)i).name.Contains("Berrynana Peel Yellow")));
			return _cachedBananaItem;
		}

		private static AudioClip? GetTripSound()
		{
			if (!Object.op_Implicit((Object)(object)_cachedTripSound))
			{
				_cachedTripSound = ((IEnumerable<AudioClip>)Resources.FindObjectsOfTypeAll<AudioClip>()).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => ((Object)c).name == "Au_Slip1"));
			}
			return _cachedTripSound;
		}
	}
	[Serializable]
	public class TransmutePayload
	{
		public string? ruleName;

		public bool isDeath;

		public int spawnCount;

		public Vector3 deathPosition;
	}
	public class TransmuteEvent : VoiceEventBase
	{
		private readonly List<(string Name, string[] Triggers, string[] Targets, Func<bool> IsEnabled)> _definitions;

		private readonly Dictionary<string, (string Name, string[] Targets, Func<bool> IsEnabled)> _transmuteLookup = new Dictionary<string, (string, string[], Func<bool>)>();

		private readonly Dictionary<string, Item?> _itemCache = new Dictionary<string, Item>();

		private static readonly Regex NameCleaner = new Regex("\\s*\\((\\d+|Clone)\\)", RegexOptions.Compiled);

		public TransmuteEvent(Config config)
		{
			Config config2 = config;
			base..ctor(config2);
			_definitions = new List<(string, string[], string[], Func<bool>)>(9)
			{
				("Milk", new string[2] { "молоко", "кальций" }, new string[1] { "Fortified Milk" }, () => config2.TransmuteMilkEnabled.Value),
				("Cactus", new string[1] { "кактус" }, new string[1] { "Cactus" }, () => config2.TransmuteCactusEnabled.Value),
				("Coconut", new string[1] { "кокос" }, new string[1] { "Coconut" }, () => config2.TransmuteCoconutEnabled.Value),
				("Apple", new string[2] { "яблок", "ягод" }, new string[3] { "Red Crispberry", "Yellow Crispberry", "Green Crispberry" }, () => config2.TransmuteAppleEnabled.Value),
				("Banana", new string[1] { "банан" }, new string[1] { "Berrynana Peel Yellow" }, () => config2.TransmuteBananaEnabled.Value),
				("Egg", new string[1] { "яйц" }, new string[1] { "Egg" }, () => config2.TransmuteEggEnabled.Value),
				("Fruit", new string[1] { "фрукт" }, new string[10] { "Red Crispberry", "Yellow Crispberry", "Green Crispberry", "Kingberry Purple", "Kingberry Yellow", "Kingberry Green", "Berrynana Brown", "Berrynana Yellow", "Berrynana Pink", "Berrynana Blue" }, () => config2.TransmuteFruitEnabled.Value),
				("Mushroom", new string[1] { "гриб" }, new string[1] { "Mushroom Normie" }, () => config2.TransmuteMushroomEnabled.Value),
				("Ball", new string[1] { "мяч" }, new string[1] { "Basketball" }, () => config2.TransmuteBallEnabled.Value)
			};
			foreach (var definition in _definitions)
			{
				string[] item = definition.Triggers;
				foreach (string key in item)
				{
					_transmuteLookup[key] = (definition.Name, definition.Targets, definition.IsEnabled);
				}
			}
		}

		protected override IEnumerable<string> GetKeywords()
		{
			IEnumerable<string> result;
			if (!Config.TransmuteEnabled.Value)
			{
				IEnumerable<string> enumerable = Array.Empty<string>();
				result = enumerable;
			}
			else
			{
				result = _definitions.Where<(string, string[], string[], Func<bool>)>(((string Name, string[] Triggers, string[] Targets, Func<bool> IsEnabled) d) => d.IsEnabled()).SelectMany<(string, string[], string[], Func<bool>), string>(((string Name, string[] Triggers, string[] Targets, Func<bool> IsEnabled) d) => d.Triggers);
			}
			return result;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			string fullSentence2 = fullSentence;
			if (!Config.TransmuteEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			string[] array = null;
			string text = null;
			if (_transmuteLookup.TryGetValue(matchedKeyword, out (string, string[], Func<bool>) value) && value.Item3())
			{
				(text, array, _) = value;
			}
			if (array == null)
			{
				string text2 = _transmuteLookup.Keys.FirstOrDefault((string k) => fullSentence2.Contains(k) && _transmuteLookup[k].IsEnabled());
				if (text2 != null)
				{
					(text, array, _) = _transmuteLookup[text2];
				}
			}
			if (array == null || array.Length == 0)
			{
				return false;
			}
			bool value2 = Config.TransmuteDeathEnabled.Value;
			TransmutePayload transmutePayload = new TransmutePayload
			{
				ruleName = text,
				isDeath = value2,
				spawnCount = 0,
				deathPosition = player.Center
			};
			if (value2)
			{
				int spawnCount = ClearInventoryForDeath(player);
				player.DieInstantly();
				transmutePayload.spawnCount = spawnCount;
			}
			base.ExecutionDetail = text;
			base.ExecutionPayload = JsonUtility.ToJson((object)transmutePayload);
			return true;
		}

		public override void PlayEffects(Character origin, Vector3 position, string detail)
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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)
			if (!PhotonNetwork.IsMasterClient || !Object.op_Implicit((Object)(object)origin) || string.IsNullOrEmpty(detail))
			{
				return;
			}
			TransmutePayload payload;
			try
			{
				payload = JsonUtility.FromJson<TransmutePayload>(detail);
			}
			catch
			{
				return;
			}
			if (payload == null || string.IsNullOrEmpty(payload.ruleName))
			{
				return;
			}
			(string, string[], string[], Func<bool>) tuple = _definitions.FirstOrDefault<(string, string[], string[], Func<bool>)>(((string Name, string[] Triggers, string[] Targets, Func<bool> IsEnabled) d) => d.Name == payload.ruleName);
			if (tuple.Item3 == null || tuple.Item3.Length == 0)
			{
				return;
			}
			string[] item = tuple.Item3;
			if (payload.isDeath)
			{
				Vector3 origin2 = ((payload.deathPosition != Vector3.zero) ? payload.deathPosition : origin.Center);
				SpawnTransmutedItems(origin2, payload.spawnCount, item);
				return;
			}
			TransmuteInventoryAlive(origin, item);
			float num = Random.Range(Config.AfflictionMinPercent.Value, Config.AfflictionMaxPercent.Value);
			if (Object.op_Implicit((Object)(object)origin.refs.afflictions))
			{
				origin.refs.afflictions.AddStatus((STATUSTYPE)0, num, false, true);
			}
		}

		private static int ClearInventoryForDeath(Character player)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			int num = 1;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f, -5000f, 0f);
			for (byte b = 0; b < 3; b++)
			{
				ItemSlot itemSlot = player.player.GetItemSlot(b);
				if (itemSlot != null && !itemSlot.IsEmpty())
				{
					num++;
					player.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val });
				}
			}
			ItemSlot itemSlot2 = player.player.GetItemSlot((byte)3);
			if (itemSlot2 != null && !itemSlot2.IsEmpty())
			{
				BackpackData val2 = default(BackpackData);
				if (itemSlot2.data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val2))
				{
					num += val2.FilledSlotCount();
				}
				num++;
				player.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2]
				{
					(byte)3,
					val
				});
			}
			if (Object.op_Implicit((Object)(object)player.refs.afflictions))
			{
				player.refs.afflictions.UpdateWeight();
			}
			return num;
		}

		private void TransmuteInventoryAlive(Character player, string[] possibleTargets)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f, -5000f, 0f);
			Vector3 center = player.Center;
			player.refs.items.photonView.RPC("EquipSlotRpc", (RpcTarget)0, new object[2] { -1, -1 });
			for (byte b = 0; b < 3; b++)
			{
				ItemSlot itemSlot = player.player.GetItemSlot(b);
				if (itemSlot != null && !itemSlot.IsEmpty())
				{
					player.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val });
					SpawnTransmutedItems(center, 1, possibleTargets);
				}
			}
			if (Config.TransmuteBackpackEnabled.Value)
			{
				ItemSlot itemSlot2 = player.player.GetItemSlot((byte)3);
				if (itemSlot2 != null && !itemSlot2.IsEmpty())
				{
					int num = 1;
					BackpackData val2 = default(BackpackData);
					if (itemSlot2.data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val2))
					{
						num += val2.FilledSlotCount();
					}
					player.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2]
					{
						(byte)3,
						val
					});
					SpawnTransmutedItems(center, num, possibleTargets);
				}
			}
			if (Object.op_Implicit((Object)(object)player.refs.afflictions))
			{
				player.refs.afflictions.UpdateWeight();
			}
		}

		private void SpawnTransmutedItems(Vector3 origin, int count, string[] targets)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < count; i++)
			{
				SpawnItem(origin, targets, autoPickup: false, null);
			}
		}

		private void SpawnItem(Vector3 origin, string[] targets, bool autoPickup, Character? picker)
		{
			//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)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_00c7: 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)
			string searchName = targets[Random.Range(0, targets.Length)];
			Item orFindItem = GetOrFindItem(searchName);
			if (!Object.op_Implicit((Object)(object)orFindItem))
			{
				return;
			}
			Vector3 val = origin + Random.insideUnitSphere * 0.5f;
			val.y = origin.y + 0.5f;
			string text = NameCleaner.Replace(((Object)orFindItem).name, "").Trim();
			string text2 = "0_Items/" + text;
			GameObject val2 = PhotonNetwork.Instantiate(text2, val, Quaternion.identity, (byte)0, (object[])null);
			PhotonView val3 = default(PhotonView);
			if (!Object.op_Implicit((Object)(object)val2) || !val2.TryGetComponent<PhotonView>(ref val3))
			{
				return;
			}
			val3.RPC("SetKinematicRPC", (RpcTarget)0, new object[3]
			{
				false,
				val,
				Quaternion.identity
			});
			Item val4 = default(Item);
			if (autoPickup && Object.op_Implicit((Object)(object)picker) && val2.TryGetComponent<Item>(ref val4))
			{
				if (picker.refs != null && (Object)(object)picker.refs.items != (Object)null)
				{
					picker.refs.items.lastEquippedSlotTime = 0f;
				}
				val4.Interact(picker);
			}
		}

		private Item? GetOrFindItem(string searchName)
		{
			string searchName2 = searchName;
			if (_itemCache.TryGetValue(searchName2, out Item value))
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					return value;
				}
				_itemCache.Remove(searchName2);
			}
			Item val = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item i) => ((Object)i).name.Contains(searchName2) || (i.UIData != null && i.UIData.itemName.Contains(searchName2))));
			_itemCache[searchName2] = val;
			if (!Object.op_Implicit((Object)(object)val) && Config.EnableDebugLogs.Value)
			{
				Debug.LogWarning((object)("[VoiceCurseRu] Не найден подходящий предмет '" + searchName2 + "'"));
			}
			return val;
		}
	}
	public abstract class VoiceEventBase : IVoiceEvent
	{
		protected readonly Config Config;

		private float _lastExecutionTime;

		private float Cooldown => Config.GlobalCooldown.Value;

		protected string? ExecutionDetail { get; set; }

		protected string? ExecutionPayload { get; set; }

		protected VoiceEventBase(Config config)
		{
			Config = config;
			_lastExecutionTime = -999f;
			base..ctor();
		}

		protected abstract IEnumerable<string> GetKeywords();

		protected abstract bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword);

		protected static HashSet<string> ParseKeywords(string configLine)
		{
			return (from k in configLine.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select k.Trim().ToLowerInvariant() into k
				where !string.IsNullOrWhiteSpace(k)
				select k).ToHashSet();
		}

		public bool TryExecute(string spokenWord, string fullSentence)
		{
			//IL_0232: Unknown result type (might be due to invalid I

plugins/Vosk.dll

Decompiled a day ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Vosk;

public class Model : IDisposable
{
	private HandleRef handle;

	internal Model(IntPtr cPtr)
	{
		handle = new HandleRef(this, cPtr);
	}

	public Model(string model_path)
		: this(VoskPINVOKE.new_Model(model_path))
	{
	}

	internal static HandleRef getCPtr(Model obj)
	{
		return obj?.handle ?? new HandleRef(null, IntPtr.Zero);
	}

	~Model()
	{
		Dispose(disposing: false);
	}

	public void Dispose()
	{
		Dispose(disposing: true);
		GC.SuppressFinalize(this);
	}

	protected virtual void Dispose(bool disposing)
	{
		lock (this)
		{
			if (handle.Handle != IntPtr.Zero)
			{
				VoskPINVOKE.delete_Model(handle);
				handle = new HandleRef(null, IntPtr.Zero);
			}
		}
	}

	public int FindWord(string word)
	{
		return VoskPINVOKE.Model_vosk_model_find_word(handle, word);
	}
}
public class SpkModel : IDisposable
{
	private HandleRef handle;

	internal SpkModel(IntPtr cPtr)
	{
		handle = new HandleRef(this, cPtr);
	}

	public SpkModel(string model_path)
		: this(VoskPINVOKE.new_SpkModel(model_path))
	{
	}

	internal static HandleRef getCPtr(SpkModel obj)
	{
		return obj?.handle ?? new HandleRef(null, IntPtr.Zero);
	}

	~SpkModel()
	{
		Dispose(disposing: false);
	}

	public void Dispose()
	{
		Dispose(disposing: true);
		GC.SuppressFinalize(this);
	}

	protected virtual void Dispose(bool disposing)
	{
		lock (this)
		{
			if (handle.Handle != IntPtr.Zero)
			{
				VoskPINVOKE.delete_SpkModel(handle);
				handle = new HandleRef(null, IntPtr.Zero);
			}
		}
	}
}
public class Vosk
{
	public static void SetLogLevel(int level)
	{
		VoskPINVOKE.SetLogLevel(level);
	}

	public static void GpuInit()
	{
		VoskPINVOKE.GpuInit();
	}

	public static void GpuThreadInit()
	{
		VoskPINVOKE.GpuThreadInit();
	}
}
internal class VoskPINVOKE
{
	static VoskPINVOKE()
	{
	}

	[DllImport("libvosk", EntryPoint = "vosk_model_new")]
	public static extern IntPtr new_Model(string jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_model_free")]
	public static extern void delete_Model(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_model_find_word")]
	public static extern int Model_vosk_model_find_word(HandleRef jarg1, string jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_spk_model_new")]
	public static extern IntPtr new_SpkModel(string jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_spk_model_free")]
	public static extern void delete_SpkModel(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_new")]
	public static extern IntPtr new_VoskRecognizer(HandleRef jarg1, float jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_new_spk")]
	public static extern IntPtr new_VoskRecognizerSpk(HandleRef jarg1, float jarg2, HandleRef jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_new_grm")]
	public static extern IntPtr new_VoskRecognizerGrm(HandleRef jarg1, float jarg2, string jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_free")]
	public static extern void delete_VoskRecognizer(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_set_max_alternatives")]
	public static extern void VoskRecognizer_SetMaxAlternatives(HandleRef jarg1, int jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_set_words")]
	public static extern void VoskRecognizer_SetWords(HandleRef jarg1, int jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_set_partial_words")]
	public static extern void VoskRecognizer_SetPartialWords(HandleRef jarg1, int jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_set_spk_model")]
	public static extern void VoskRecognizer_SetSpkModel(HandleRef jarg1, HandleRef jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_accept_waveform")]
	public static extern bool VoskRecognizer_AcceptWaveform(HandleRef jarg1, [In][MarshalAs(UnmanagedType.LPArray)] byte[] jarg2, int jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_accept_waveform_s")]
	public static extern bool VoskRecognizer_AcceptWaveformShort(HandleRef jarg1, [In][MarshalAs(UnmanagedType.LPArray)] short[] jarg2, int jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_accept_waveform_f")]
	public static extern bool VoskRecognizer_AcceptWaveformFloat(HandleRef jarg1, [In][MarshalAs(UnmanagedType.LPArray)] float[] jarg2, int jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_result")]
	public static extern IntPtr VoskRecognizer_Result(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_partial_result")]
	public static extern IntPtr VoskRecognizer_PartialResult(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_final_result")]
	public static extern IntPtr VoskRecognizer_FinalResult(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_reset")]
	public static extern void VoskRecognizer_Reset(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_set_log_level")]
	public static extern void SetLogLevel(int jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_gpu_init")]
	public static extern void GpuInit();

	[DllImport("libvosk", EntryPoint = "vosk_gpu_thread_init")]
	public static extern void GpuThreadInit();
}
public class VoskRecognizer : IDisposable
{
	private HandleRef handle;

	internal VoskRecognizer(IntPtr cPtr)
	{
		handle = new HandleRef(this, cPtr);
	}

	public VoskRecognizer(Model model, float sample_rate)
		: this(VoskPINVOKE.new_VoskRecognizer(Model.getCPtr(model), sample_rate))
	{
	}

	public VoskRecognizer(Model model, float sample_rate, SpkModel spk_model)
		: this(VoskPINVOKE.new_VoskRecognizerSpk(Model.getCPtr(model), sample_rate, SpkModel.getCPtr(spk_model)))
	{
	}

	public VoskRecognizer(Model model, float sample_rate, string grammar)
		: this(VoskPINVOKE.new_VoskRecognizerGrm(Model.getCPtr(model), sample_rate, grammar))
	{
	}

	internal static HandleRef getCPtr(VoskRecognizer obj)
	{
		return obj?.handle ?? new HandleRef(null, IntPtr.Zero);
	}

	~VoskRecognizer()
	{
		Dispose(disposing: false);
	}

	public void Dispose()
	{
		Dispose(disposing: true);
		GC.SuppressFinalize(this);
	}

	protected virtual void Dispose(bool disposing)
	{
		lock (this)
		{
			if (handle.Handle != IntPtr.Zero)
			{
				VoskPINVOKE.delete_VoskRecognizer(handle);
				handle = new HandleRef(null, IntPtr.Zero);
			}
		}
	}

	public void SetMaxAlternatives(int max_alternatives)
	{
		VoskPINVOKE.VoskRecognizer_SetMaxAlternatives(handle, max_alternatives);
	}

	public void SetWords(bool words)
	{
		VoskPINVOKE.VoskRecognizer_SetWords(handle, words ? 1 : 0);
	}

	public void SetPartialWords(bool partial_words)
	{
		VoskPINVOKE.VoskRecognizer_SetPartialWords(handle, partial_words ? 1 : 0);
	}

	public void SetSpkModel(SpkModel spk_model)
	{
		VoskPINVOKE.VoskRecognizer_SetSpkModel(handle, SpkModel.getCPtr(spk_model));
	}

	public bool AcceptWaveform(byte[] data, int len)
	{
		return VoskPINVOKE.VoskRecognizer_AcceptWaveform(handle, data, len);
	}

	public bool AcceptWaveform(short[] sdata, int len)
	{
		return VoskPINVOKE.VoskRecognizer_AcceptWaveformShort(handle, sdata, len);
	}

	public bool AcceptWaveform(float[] fdata, int len)
	{
		return VoskPINVOKE.VoskRecognizer_AcceptWaveformFloat(handle, fdata, len);
	}

	private static string PtrToStringUTF8(IntPtr ptr)
	{
		int i;
		for (i = 0; Marshal.ReadByte(ptr, i) != 0; i++)
		{
		}
		byte[] array = new byte[i];
		Marshal.Copy(ptr, array, 0, i);
		return Encoding.UTF8.GetString(array);
	}

	public string Result()
	{
		return PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_Result(handle));
	}

	public string PartialResult()
	{
		return PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_PartialResult(handle));
	}

	public string FinalResult()
	{
		return PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_FinalResult(handle));
	}

	public void Reset()
	{
		VoskPINVOKE.VoskRecognizer_Reset(handle);
	}
}