Decompiled source of VoiceCurseReborn v1.0.2

plugins/jill920.VoiceCurseReborn.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 System.Threading.Tasks;
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 VoiceCurseReborn.Events;
using VoiceCurseReborn.Handlers;
using VoiceCurseReborn.Helpers;
using VoiceCurseReborn.Interfaces;
using VoiceCurseReborn.Voice;
using Vosk;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("jill920.VoiceCurseReborn")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+3f2a718bf951ad1e51ce18ab71dd7a603fb24cf7")]
[assembly: AssemblyProduct("jill920.VoiceCurseReborn")]
[assembly: AssemblyTitle("jill920.VoiceCurseReborn")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VoiceCurseReborn
{
	public class FollowTarget : MonoBehaviour
	{
		public Character? Target;

		private void Update()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Target != (Object)null)
			{
				((Component)this).transform.position = Target.Center;
			}
		}
	}
	public static class CleanupManager
	{
		private static readonly string[] _objectNamesToCleanup = new string[27]
		{
			"SpawnedMushroom", "SpawnedRope", "SpawnedLuggage", "SpawnedTree", "SpawnedRock", "RopeDynamic(Clone)", "ShelfShroomSpawn(Clone)", "RopeAnchor(Clone)", "MagicBeanVine(Clone)", "Shell Big(Clone)",
			"ChainShooter(Clone)", "Berrynana Blue(Clone)", "Berrynana Brown(Clone)", "Berrynana Yellow(Clone)", "Apple Berry Red(Clone)", "Apple Berry Green(Clone)", "Apple Berry Yellow(Clone)", "ClimbingSpikeHammered(Clone)", "ClimbingSpike(Clone)", "Clusterberry Red(Clone)",
			"Item_Coconut(Clone)", "ScoutCannonItem(Clone)", "Cure-All(Clone)", "ShelfShroom(Clone)", "RopeSpool(Clone)", "SnowPile Variant", "RavenVoiceThief(Clone)"
		};

		public static void CleanupAllSpawnedObjects()
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			try
			{
				GameObject[] array = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0);
				foreach (GameObject val in array)
				{
					if ((Object)(object)val == (Object)null || (Object)(object)val.GetComponent<Character>() != (Object)null)
					{
						continue;
					}
					string name = ((Object)val).name;
					bool flag = false;
					string[] objectNamesToCleanup = _objectNamesToCleanup;
					foreach (string value in objectNamesToCleanup)
					{
						if (name.Contains(value))
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						try
						{
							Object.Destroy((Object)(object)val);
							num++;
						}
						catch (Exception ex)
						{
							num2++;
							Plugin.Log.LogWarning((object)("[CleanUp] Failed to destroy " + ((Object)val).name + ": " + ex.Message));
						}
					}
				}
				if (num > 0)
				{
					NotificationManager.ForceDisplay($"<color=#FFA500>VoiceCurse</color> Cleared {num} spawned objects!");
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogError((object)("[CleanUp] failed: " + ex2.Message));
			}
		}

		public static void CleanupAll()
		{
			CleanupAllSpawnedObjects();
		}
	}
	public class Config
	{
		public ConfigEntry<bool> EnableDebugLogs { get; private set; }

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

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

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

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

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

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

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

		public ConfigEntry<float> LaunchStunDuration { 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> 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> TransmuteBingBongEnabled { get; private set; }

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

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

		public ConfigEntry<string> DeathKeywords { 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 ConfigEntry<bool> FartEnabled { get; private set; }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		public ConfigEntry<KeyCode> CleanupKey { get; private set; }

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

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

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

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

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

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

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

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

		public Config(ConfigFile config)
		{
			EnableDebugLogs = config.Bind<bool>("Global", "EnableDebugLogs", false, "Enable debug logs for speech detection.");
			GlobalCooldown = config.Bind<float>("Global", "GlobalCooldown", 1f, "The time in seconds that must pass before another voice event can be triggered.");
			ChatEnabled = config.Bind<bool>("Global", "EnableTextChat", true, "Enables the voice curse system for text chat.");
			FuzzyChatMatchingEnabled = config.Bind<bool>("Global", "EnableFuzzyMatching", true, "Enable fuzzy word matching for the text chat, ie. 'dexth' -> 'death'.");
			LaunchEnabled = config.Bind<bool>("Event.Launch", "Enabled", true, "Enable the Launch event.");
			LaunchKeywords = config.Bind<string>("Event.Launch", "Keywords", "launch, fly, boost, ascend, lift, up, soar, jump, spring, catapult, fling, hurl, propel, shoot, skyrocket, takeoff, left, right, forward, back, yeet, lob, pitch, chuck, heave, airborne, levitate, hover, elevate, rise, vault, leap, hop, eject, thrust, projectile, missile, space, orbit", "List of keywords that trigger the launch event, separated by commas.");
			LaunchForceLowerBound = config.Bind<float>("Event.Launch", "ForceLowerBound", 1800f, "Lowest possible amount of force applied to the player upon launching.");
			LaunchForceHigherBound = config.Bind<float>("Event.Launch", "ForceHigherBound", 1800f, "Highest possible amount of force applied to the player upon launching.");
			LaunchStunDuration = config.Bind<float>("Event.Launch", "StunDuration", 3f, "Duration in seconds the player will be stunned/ragdolled after launching.");
			AfflictionEnabled = config.Bind<bool>("Event.Affliction", "Enabled", true, "Enable the Affliction event.");
			AfflictionMinPercent = config.Bind<float>("Event.Affliction", "MinPercent", 0.2f, "The minimum percentage (0.0 to 1.0) of the status bar to fill when triggered.");
			AfflictionMaxPercent = config.Bind<float>("Event.Affliction", "MaxPercent", 0.35f, "The maximum percentage (0.0 to 1.0) of the status bar to fill when triggered.");
			AfflictionTemperatureSwapEnabled = config.Bind<bool>("Event.Affliction", "TemperatureSwapEnabled", true, "If enabled, attempting to get rid of hot or cold by saying the opposite will just swap the existing effect to the new one and add on top of that to prevent cheesing it.");
			AfflictionKeywordsInjury = config.Bind<string>("Event.Affliction", "KeywordsInjury", "damage, hurt, injury, injured, pain, harm, wound, hit, bleed, bruise, cut, slash, orange, ache, sore, trauma, gash, scrape, laceration, tear, torn, broken, fracture, sprain, puncture, stab, maim, cripple, batter", "Keywords that trigger physical injury.");
			AfflictionKeywordsHunger = config.Bind<string>("Event.Affliction", "KeywordsHunger", "hunger, hungry, starving, starve, food, malnourishment, famished, eat, snack, meal, yellow, appetite, crave, craving, ravenous, peckish, feast, feed, sustenance, nourishment, nutrition, consume", "Keywords that trigger hunger.");
			AfflictionKeywordsCold = config.Bind<string>("Event.Affliction", "KeywordsCold", "freezing, cool, cold, blizzard, shiver, ice, frozen, chill, frigid, winter, blue, frost, arctic, polar, glacier, icicle, hypothermia, numb, shivering, freeze", "Keywords that trigger cold status.");
			AfflictionKeywordsHot = config.Bind<string>("Event.Affliction", "KeywordsHot", "hot, fire, melt, scorching, heat, burn, pyro, flame, summer, cook, hell, red, sizzle, sear, swelter, boil, roast, bake, baking, scald, inferno, blaze, blazing, ignite, combust, incinerate", "Keywords that trigger hot status.");
			AfflictionKeywordsPoison = config.Bind<string>("Event.Affliction", "KeywordsPoison", "poison, sick, vomit, toxic, venom, contaminate, purple, nausea, nauseous, intoxicate, pollute, taint, corrupt, disease, ill, ailment, malady", "Keywords that trigger poison status.");
			AfflictionKeywordsSpores = config.Bind<string>("Event.Affliction", "KeywordsSpores", "spore, pink, bacterium, germ, microorganism", "Keywords that trigger spore status.");
			TransmuteEnabled = config.Bind<bool>("Event.Transmute", "Enabled", true, "Enable the Transmute event.");
			TransmuteDeathEnabled = config.Bind<bool>("Event.Transmute", "EnableDeath", true, "Enable instant death when transmute is triggered (by using your flesh as something to transmute). If disabled, you will just take damage instead (your flesh partially transmutes).");
			TransmuteMilkEnabled = config.Bind<bool>("Event.Transmute", "EnableMilk", true, "Enable 'milk/calcium' -> Fortified Milk");
			TransmuteCactusEnabled = config.Bind<bool>("Event.Transmute", "EnableCactus", true, "Enable 'cactus' -> Cactus");
			TransmuteCoconutEnabled = config.Bind<bool>("Event.Transmute", "EnableCoconut", true, "Enable 'coconut' -> Coconut");
			TransmuteAppleEnabled = config.Bind<bool>("Event.Transmute", "EnableApple", true, "Enable 'apple/berry' -> Crispberries");
			TransmuteBananaEnabled = config.Bind<bool>("Event.Transmute", "EnableBanana", true, "Enable 'banana' -> Peel");
			TransmuteEggEnabled = config.Bind<bool>("Event.Transmute", "EnableEgg", true, "Enable 'egg' -> Egg");
			TransmuteFruitEnabled = config.Bind<bool>("Event.Transmute", "EnableFruit", true, "Enable 'fruit' -> Random Fruit");
			TransmuteMushroomEnabled = config.Bind<bool>("Event.Transmute", "EnableMushroom", true, "Enable 'mushroom/fungus' -> Mushroom");
			TransmuteBallEnabled = config.Bind<bool>("Event.Transmute", "EnableBall", true, "Enable 'ball' -> Basketball");
			TransmuteBingBongEnabled = config.Bind<bool>("Event.Transmute", "EnableBingBong", true, "Enable 'eyy waddup' -> Bing Bong");
			TransmuteKingberryEnabled = config.Bind<bool>("Event.Transmute", "EnableKingberry", true, "Enable 'babydoll' -> Purple Kingberry");
			DeathEnabled = config.Bind<bool>("Event.Death", "Enabled", true, "Enable the Death event.");
			DeathKeywords = config.Bind<string>("Event.Death", "Keywords", "die, death, dead, suicide, kill, deceased, skeleton, skull, bone, perish, demise, expire, fatal, mortal, slain, dying, corpse, cadaver, lifeless, cease, extinct, eliminate, terminate, execute, obliterate, annihilate, eradicate, end, finish, doom, grave, burial, coffin, casket, tomb, crypt, reaper, grim", "List of keywords that trigger the death event, separated by commas.");
			ZombifyEnabled = config.Bind<bool>("Event.Zombify", "Enabled", true, "Enable the Zombify event.");
			ZombifyKeywords = config.Bind<string>("Event.Zombify", "Keywords", "zombie, zombify, zombified, walker, ghoul, bitten, bite, brain, rot, decay, infected, infection, plague, pandemic, virus, outbreak, cannibal, flesh, meat, undead, risen, horde, apocalypse, reanimate, lurker, creeper, crawler, groaning, groan, moan, growl, snarl", "List of keywords that trigger the zombify event, separated by commas.");
			SleepEnabled = config.Bind<bool>("Event.Sleep", "Enabled", true, "Enable the Sleep event.");
			SleepKeywords = config.Bind<string>("Event.Sleep", "Keywords", "faint, sleep, exhausted, sleepy, tired, bed, nap, rest, slumber, doze, snooze, pass out, knockout, blackout, coma, narc, drowsy, unconscious, collapse, zonk, conk, yawn, fatigue, fatigued, weary, lethargic, sluggish, drained, wiped, beat, worn, spent, shut-eye, shuteye, siesta, catnap, dreamland, nodding off, drift off, lights out, out cold, RNAV", "List of keywords that trigger the sleep event, separated by commas.");
			DropEnabled = config.Bind<bool>("Event.Drop", "Enabled", true, "Enable the Drop event.");
			DropKeywords = config.Bind<string>("Event.Drop", "Keywords", "drop, oops, whoops, butterfingers, fumble, release, discard, off, loss, lose, let go, slip away, misplace, clumsy, accident, unhand, relinquish, surrender, abandon, ditch, shed, cast, toss, throw away, get rid", "List of keywords that trigger the drop event, separated by commas.");
			ExplodeEnabled = config.Bind<bool>("Event.Explode", "Enabled", true, "Enable the Explode event.");
			ExplodeKeywords = config.Bind<string>("Event.Explode", "Keywords", "explosion, dynamite, grenade, explode, blow, blast, boom, nuke, bomb, nuclear, detonate, detonation, explosive, kaboom, burst", "List of keywords that trigger the explode event, separated by commas.");
			ExplodeRadius = config.Bind<float>("Event.Explode", "Radius", 6f, "The radius of the explosion effect and damage.");
			ExplodeStunDuration = config.Bind<float>("Event.Explode", "StunDuration", 3f, "Duration in seconds the player will be stunned/ragdolled after explosion.");
			ExplodeForceLowerBound = config.Bind<float>("Event.Explode", "ForceLowerBound", 800f, "Lowest possible amount of explosion force applied.");
			ExplodeForceHigherBound = config.Bind<float>("Event.Explode", "ForceHigherBound", 1200f, "Highest possible amount of explosion force applied.");
			SlipEnabled = config.Bind<bool>("Event.Slip", "Enabled", true, "Enable the Slip event.");
			SlipKeywords = config.Bind<string>("Event.Slip", "Keywords", "fuck, asshole, bastard, bitch, fag, damn, crap, slip, slide, trip, fall, fell, stumble, tumble, topple, stagger, wobble, skid, slick, peel, unbalanced, unstable, tilt", "List of keywords that trigger the slip event, separated by commas.");
			SlipStunDuration = config.Bind<float>("Event.Slip", "StunDuration", 2f, "Duration in seconds the player will be stunned/ragdolled after slipping.");
			BananaBombEnabled = config.Bind<bool>("Event.Slip", "BananaBombEnabled", true, "Enable the rare Banana Bomb easter egg on slip.");
			BananaBombChance = config.Bind<float>("Event.Slip", "BananaBombChance", 0.05f, "Chance (0.0 - 1.0) for a slip to trigger a Banana Bomb.");
			BananaBombAmount = config.Bind<int>("Event.Slip", "BananaBombAmount", 20, "Amount of bananas to spawn during a Banana Bomb.");
			SacrificeEnabled = config.Bind<bool>("Event.Sacrifice", "Enabled", true, "Enable the Sacrifice event.");
			SacrificeKeywords = config.Bind<string>("Event.Sacrifice", "Keywords", "sacrifice, trade, revive, resurrect, exchange, soul, offer", "List of keywords that trigger the sacrifice event.");
			SacrificeCooldown = config.Bind<float>("Event.Sacrifice", "Cooldown", 300f, "Cooldown in seconds for the sacrifice event.");
			BlindEnabled = config.Bind<bool>("Event.Blind", "Enabled", true, "Enable the Blind event.");
			BlindKeywords = config.Bind<string>("Event.Blind", "Keywords", "blind, flash, eyes, vision, can't see, my eyes", "List of keywords that trigger the blind event.");
			BlindDuration = config.Bind<float>("Event.Blind", "Duration", 45f, "Duration in seconds the player will be blinded.");
			FartEnabled = config.Bind<bool>("Event.Fart", "Enabled", true, "Enable the Fart event.");
			FartKeywords = config.Bind<string>("Event.Fart", "Keywords", "million, gas, cloud, inhale, vapors, toot", "Keywords that trigger the fart event.");
			RandomCosmeticsEnabled = config.Bind<bool>("Event.RandomCosmetics", "Enabled", true, "Enable the Random Cosmetics event.");
			RandomCosmeticsKeywords = config.Bind<string>("Event.RandomCosmetics", "Keywords", "rigor, creek, nigga", "Keywords that trigger random cosmetics.");
			VineEnabled = config.Bind<bool>("Event.Vine", "Enabled", true, "Enable the Vine event.");
			VineKeywords = config.Bind<string>("Event.Vine", "Keywords", "tiktok, vine, creeper, plant, bean, seed, kernel, tendril", "Keywords that trigger the vine event.");
			BeeEnabled = config.Bind<bool>("Event.Bee", "Enabled", true, "Enable the Bee event.");
			BeeKeywords = config.Bind<string>("Event.Bee", "Keywords", "buzz, peace, bees, rape, honey, drone, harvest, party, social, gathering", "Keywords that trigger the bee event.");
			KickEnabled = config.Bind<bool>("Event.Kick", "Enabled", true, "Enable the Kick event.");
			KickKeywords = config.Bind<string>("Event.Kick", "Keywords", "puppies, piece, help, gamer, boot, punt, kick, peace", "Keywords that trigger the kick event.");
			CannonEnabled = config.Bind<bool>("Event.Cannon", "Enabled", true, "Enable the Cannon event.");
			CannonKeywords = config.Bind<string>("Event.Cannon", "Keywords", "cannon, canon, beep, america, freedom, howitzer, mortar, ordnance, Big Bertha, Long Tom, artillery, dimi", "Keywords that trigger the cannon event.");
			RocketEnabled = config.Bind<bool>("Event.Rocket", "Enabled", true, "Enable the Rocket event.");
			RocketKeywords = config.Bind<string>("Event.Rocket", "Keywords", "rocket, launch, blastoff, liftoff, ignition, ignite, thrust, boost, propulsion, jet, liftoff, launch, rocketpack, fly, soar, ascend, takeoff, missiles, space, orbit, countdown, stage, booster, throttle, flame, burn, nozzle, engine, fuel", "Keywords that trigger the rocket event.");
			GhostEnabled = config.Bind<bool>("Event.Ghost", "Enabled", true, "Enable the Ghost event.");
			GhostKeywords = config.Bind<string>("Event.Ghost", "Keywords", "aether, ethereal, ghost, spirit, haunt, spooky, phantom, eerie, poltergeist, specter, wraith, apparition, phantom, ghostly, supernatural, paranormal, haunting, boo, scary, fright, creepy, chill, spook, phantom, shade, soul, demon, banshee, ghoul, phantom, shadow, unearthly, occult, mystic, demon, devil", "Keywords that trigger the ghost event.");
			FrogEnabled = config.Bind<bool>("Event.Frog", "Enabled", true, "Enable the Frog event.");
			FrogKeywords = config.Bind<string>("Event.Frog", "Keywords", "georgia, frog, frogs, toad, ribbit, hop, leap, amphibian, croak, jump, tadpole, swamp, pond, lily, croaking, ribbiting, jumping, hopping, amphibious, wet, slimy, green, treefrog, bullfrog, poison, dart, froglegs, kermit, hopper, chouja, boombax, boombox, ribbit", "Keywords that trigger the frog event.");
			TumbleweedEnabled = config.Bind<bool>("Event.Tumbleweed", "Enabled", true, "Enable the Tumbleweed event.");
			TumbleweedKeywords = config.Bind<string>("Event.Tumbleweed", "Keywords", "tumbleweed, tumble, weed, roll, rolling, desert, western, highnoon, cowboy, spin, wind, dusty, dirt, sand, storm, cyclone, whirl, twister, dust devil, sandstorm, sagebrush, dry, arid, plains, prairie, gust, breeze, drift, blow, scatter, tumble, weed, rolling, Biggus, Bovinus", "Keywords that trigger the tumbleweed event.");
			TornadoEnabled = config.Bind<bool>("Event.Tornado", "Enabled", true, "Enable the Tornado event.");
			TornadoKeywords = config.Bind<string>("Event.Tornado", "Keywords", "tornado, twister, cyclone, storm, whirlwind, vortex, funnel, wind, gust, tempest, typhoon, hurricane, whirl, spin, debris, destroy, devastation, storm, tornado, funnel, cloud, rotation, wind, disaster, extreme, weather, natural, disaster, havoc, chaos, whirlpool, maelstrom, vortex. Droppings", "Keywords that trigger the tornado event.");
			PetrifyEnabled = config.Bind<bool>("Event.Petrify", "Enabled", true, "Enable the Petrify event.");
			PetrifyKeywords = config.Bind<string>("Event.Petrify", "Keywords", "petrify, stone, statue, petrified, fossil, rock, solid, medusa, gorgon, gaze, basilisk, cockatrice, gem, amulet, gravel, metal, pebble, boulder, crag, jewel, mason, masonry, ore", "Keywords that trigger petrify.");
			PetrifyMinAmount = config.Bind<int>("Event.Petrify", "MinAmount", 5, "Minimum petrify amount (0-100).");
			PetrifyMaxAmount = config.Bind<int>("Event.Petrify", "MaxAmount", 15, "Maximum petrify amount (0-100).");
			ArrowEnabled = config.Bind<bool>("Event.Arrow", "Enabled", true, "Enable the Arrow event.");
			ArrowKeywords = config.Bind<string>("Event.Arrow", "Keywords", "arrow, arrows, archer, bow, shoot, quiver, bolt, dart, projectile, piercing, puncture, arrowed, pierce, tip", "Keywords that trigger arrows.");
			ArrowMinCount = config.Bind<int>("Event.Arrow", "MinCount", 2, "Minimum number of arrows to spawn.");
			ArrowMaxCount = config.Bind<int>("Event.Arrow", "MaxCount", 5, "Maximum number of arrows to spawn.");
			CleanupKey = config.Bind<KeyCode>("General", "CleanupKey", (KeyCode)291, "Key to clean up all VoiceCurse spawned objects.");
		}
	}
	public static class NotificationManager
	{
		private static PlayerConnectionLog? _connectionLog;

		private static MethodInfo? _addMessageMethod;

		private static MethodInfo? _getColorTagMethod;

		private static float _searchTimer;

		private static bool _isSearching = true;

		private static bool _found = false;

		private static readonly object _lock = new object();

		public static void Initialize()
		{
			_isSearching = true;
			_found = false;
		}

		public static void UpdateSearch()
		{
			if (_found && (Object)(object)_connectionLog != (Object)null && _addMessageMethod != null)
			{
				return;
			}
			_searchTimer += Time.deltaTime;
			if (_searchTimer < 0.1f)
			{
				return;
			}
			_searchTimer = 0f;
			if ((Object)(object)_connectionLog == (Object)null)
			{
				_connectionLog = Object.FindFirstObjectByType<PlayerConnectionLog>();
			}
			if ((Object)(object)_connectionLog == (Object)null)
			{
				GameObject val = GameObject.Find("PlayerConnectionLog");
				if ((Object)(object)val != (Object)null)
				{
					_connectionLog = val.GetComponent<PlayerConnectionLog>();
				}
			}
			if ((Object)(object)_connectionLog != (Object)null)
			{
				if (_addMessageMethod == null)
				{
					_addMessageMethod = typeof(PlayerConnectionLog).GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				if (_getColorTagMethod == null)
				{
					_getColorTagMethod = typeof(PlayerConnectionLog).GetMethod("GetColorTag", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				if (_addMessageMethod != null)
				{
					_found = true;
					Plugin.Log.LogInfo((object)"[NotificationManager] PlayerConnectionLog found and AddMessage method located!");
				}
				else
				{
					Plugin.Log.LogWarning((object)"[NotificationManager] AddMessage method is null!");
				}
			}
			else if (Time.frameCount % 60 == 0)
			{
				Plugin.Log.LogInfo((object)"[NotificationManager] Still searching for PlayerConnectionLog...");
			}
		}

		public static void DisplayNotification(string playerName, Color color, string fullWord, string keyword, string eventName, string detail)
		{
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_found || (Object)(object)_connectionLog == (Object)null || _addMessageMethod == null)
				{
					UpdateSearch();
					if (!_found || (Object)(object)_connectionLog == (Object)null || _addMessageMethod == null)
					{
						Plugin.Log.LogInfo((object)("[NotificationManager] (queued): " + playerName + " triggered " + eventName + " with '" + keyword + "'"));
						return;
					}
				}
				int num = fullWord.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);
				if (num >= 0)
				{
					string text = fullWord.Substring(0, num);
					string text2 = fullWord.Substring(num, keyword.Length);
					int num2 = num + keyword.Length;
					string text3 = fullWord.Substring(num2, fullWord.Length - num2);
					_ = text + "<color=#8B0000>" + text2 + "</color>" + text3;
				}
				string text6;
				if (_getColorTagMethod != null)
				{
					string text4 = (string)_getColorTagMethod.Invoke(_connectionLog, new object[1] { color });
					string text5 = (string)_getColorTagMethod.Invoke(_connectionLog, new object[1] { Color.white });
					text6 = text4 + playerName + "</color>" + text5 + " triggered <color=#FFA500>" + eventName + "</color>";
				}
				else
				{
					string text7 = "#" + ColorUtility.ToHtmlStringRGB(color);
					text6 = "<color=" + text7 + ">" + playerName + "</color> triggered <color=#FFA500>" + eventName + "</color>";
				}
				_addMessageMethod.Invoke(_connectionLog, new object[1] { text6 });
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[NotificationManager] Failed to display notification: " + ex.Message));
				Plugin.Log.LogInfo((object)("[NotificationManager] " + playerName + " triggered " + eventName));
			}
		}

		public static void ForceDisplay(string message)
		{
			try
			{
				if (!_found || (Object)(object)_connectionLog == (Object)null || _addMessageMethod == null)
				{
					UpdateSearch();
					if (!_found || (Object)(object)_connectionLog == (Object)null || _addMessageMethod == null)
					{
						return;
					}
				}
				_addMessageMethod.Invoke(_connectionLog, new object[1] { message });
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[NotificationManager] Failed to force display: " + ex.Message));
			}
		}
	}
	[BepInPlugin("jill920.VoiceCurseReborn", "VoiceCurseReborn", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		private Config? _config;

		private VoiceHandler? _voiceHandler;

		private Harmony? _harmony;

		internal static ManualLogSource Log { get; private set; }

		public static string Name => "VoiceCurseReborn";

		private void Awake()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				_config = new Config(((BaseUnityPlugin)this).Config);
				if (_config != null)
				{
					Log.LogInfo((object)$"EnableDebugLogs: {_config.EnableDebugLogs.Value}");
					Log.LogInfo((object)$"ChatEnabled: {_config.ChatEnabled.Value}");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Config load failed: " + ex.Message));
			}
			try
			{
				_harmony = new Harmony("jill920.VoiceCurseReborn");
				_harmony.PatchAll();
				Log.LogInfo((object)"[Plugin] Harmony Patches applied.");
			}
			catch (Exception ex2)
			{
				Log.LogError((object)("[Plugin] Harmony patch failed: " + ex2.Message));
				Log.LogError((object)ex2.StackTrace);
			}
			PhotonNetwork.NetworkingClient.EventReceived += delegate(EventData eventData)
			{
				if (eventData.Code != 81 && eventData.Code != 187 && eventData.CustomData is object[] array)
				{
					_ = array.Length;
					_ = 3;
				}
			};
			try
			{
				string text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
				if (string.IsNullOrEmpty(text))
				{
					text = Paths.PluginPath;
				}
				if (_config == null)
				{
					return;
				}
				_voiceHandler = new VoiceHandler(Log, _config, text);
				Log.LogInfo((object)"VoiceHandler created successfully!");
			}
			catch (Exception ex3)
			{
				Log.LogError((object)("VoiceHandler creation failed: " + ex3.Message));
				Log.LogError((object)ex3.StackTrace);
			}
			NotificationManager.Initialize();
			Log.LogInfo((object)("Plugin " + Name + " loaded successfully."));
			PhotonNetwork.NetworkingClient.EventReceived += OnPhotonChatEvent;
		}

		private void OnPhotonChatEvent(EventData eventData)
		{
			if (eventData.Code == 81)
			{
				_voiceHandler?.OnPhotonEvent(eventData);
			}
		}

		private void Update()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			_voiceHandler?.Update();
			NotificationManager.UpdateSearch();
			if (_config != null && Input.GetKeyDown(_config.CleanupKey.Value))
			{
				CleanupManager.CleanupAllSpawnedObjects();
			}
		}

		private void OnDestroy()
		{
			PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonChatEvent;
			_voiceHandler?.Dispose();
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace VoiceCurseReborn.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)(object)_recorder == (Object)null || _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
	{
		private readonly IVoiceRecognizer? _recognizer;

		private readonly int _inputSampleRate;

		private const int TargetSampleRate = 16000;

		public VoiceProcessor(IVoiceRecognizer recognizer, int inputSampleRate)
		{
			_recognizer = recognizer;
			_inputSampleRate = inputSampleRate;
		}

		public float[]? Process(float[]? buf)
		{
			if (buf == null || buf.Length == 0 || _recognizer == null)
			{
				return buf;
			}
			if (Math.Abs(_inputSampleRate - 16000) < 100)
			{
				ProcessDirect(buf);
				return buf;
			}
			float num = (float)_inputSampleRate / 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 sample = buf[num4] + (buf[num4 + 1] - buf[num4]) * num5;
				array[i] = FloatToShort(sample);
			}
			_recognizer.FeedAudio(array, array.Length);
			return buf;
		}

		private void ProcessDirect(float[] buf)
		{
			if (_recognizer != null)
			{
				short[] array = new short[buf.Length];
				for (int i = 0; i < buf.Length; i++)
				{
					array[i] = FloatToShort(buf[i]);
				}
				_recognizer.FeedAudio(array, array.Length);
			}
		}

		private static short FloatToShort(float sample)
		{
			return (short)(Mathf.Clamp(sample, -1f, 1f) * 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			try
			{
				_recognizer = new VoskRecognizer(model, sampleRate);
				_recognizer.SetMaxAlternatives(0);
				_recognizer.SetWords(true);
				Debug.Log((object)$"[VoiceCurseReborn] Initialized VoskRecognizer with Rate: {sampleRate} Hz");
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to create 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;
			_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)("[VoiceCurseReborn] Vosk Error: " + 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) + 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 VoiceCurseReborn.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 VoiceCurseReborn.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>();

		private readonly Config _config;

		public EventHandler(Config config)
		{
			_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;
			Plugin.Log.LogInfo((object)$"[EventHandler] Found {enumerable.Count()} event types");
			foreach (Type item in enumerable)
			{
				try
				{
					if (Activator.CreateInstance(item, config) is IVoiceEvent value)
					{
						string key = item.Name.Replace("Event", "");
						Events[key] = value;
					}
				}
				catch (Exception)
				{
				}
			}
		}

		public void HandleSpeech(string text, bool isFinal)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				return;
			}
			if (_config.EnableDebugLogs.Value)
			{
				Debug.Log((object)$"[EventHandler] HandleSpeech: '{text}' (isFinal: {isFinal})");
			}
			Plugin.Log.LogInfo((object)$"[EventHandler] SPEECH DETECTED: '{text}' (isFinal: {isFinal})");
			string text2 = text.ToLowerInvariant();
			string[] array = text2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			string[] array2 = array;
			foreach (string key in array2)
			{
				dictionary.TryAdd(key, 0);
				dictionary[key]++;
			}
			foreach (KeyValuePair<string, int> item in dictionary)
			{
				string key2 = item.Key;
				int value = item.Value;
				_previousWordCounts.TryGetValue(key2, out var value2);
				int num = value - value2;
				if (num <= 0)
				{
					continue;
				}
				for (int j = 0; j < num; j++)
				{
					foreach (IVoiceEvent value3 in Events.Values)
					{
						value3.TryExecute(key2, 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;

		public static void SendCurseEvent(string spokenWord, string matchedKeyword, string eventName, string? detail, string? payload, Vector3 position)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0059: 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_0068: 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)
			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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: 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)(object)val != (Object)null && (Object)(object)val.refs?.customization != (Object)null)
			{
				color = val.refs.customization.PlayerColor;
			}
			DisplayNotification(playerName, color, fullWord, keyword, text, text2);
			if (EventHandler.Events.TryGetValue(text, out var value))
			{
				if ((Object)(object)val != (Object)null)
				{
					string detail = ((!string.IsNullOrEmpty(text3)) ? text3 : text2);
					value.PlayEffects(val, position, detail);
				}
				else
				{
					value.PlayEffects(position);
				}
			}
			else
			{
				Plugin.Log.LogError((object)("[NetworkHandler] Event NOT FOUND: '" + text + "'"));
			}
		}

		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_0001: Unknown result type (might be due to invalid IL or missing references)
			NotificationManager.DisplayNotification(playerName, color, fullWord, keyword, eventName, detail);
		}
	}
	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 = "";

		private const byte ChatEventCode = 81;

		private static readonly Random _rng = new Random();

		[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;
			_eventHandler = new EventHandler(_config);
			_networker = new NetworkHandler();
			PhotonNetwork.AddCallbackTarget((object)_networker);
			Initialize(pluginDir);
		}

		private void Initialize(string pluginDir)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			if (Directory.Exists(pluginDir))
			{
				SetDllDirectory(pluginDir);
			}
			string text = Path.Combine(pluginDir, "model-en-us");
			_log.LogInfo((object)("[VoiceHandler] Looking for Vosk model at: " + text));
			if (Directory.Exists(text))
			{
				try
				{
					string[] files = Directory.GetFiles(text, "*", SearchOption.AllDirectories);
					_log.LogInfo((object)$"[VoiceHandler] Model files found: {files.Length}");
				}
				catch (Exception ex)
				{
					_log.LogError((object)("[VoiceHandler] Error listing model: " + ex.Message));
				}
				try
				{
					_voskModel = new Model(text);
					SetupVoiceRecognition();
					_log.LogInfo((object)"[VoiceHandler] Voice recognition setup complete!");
					return;
				}
				catch (Exception ex2)
				{
					_log.LogError((object)("[VoiceHandler] Stack trace: " + ex2.StackTrace));
					return;
				}
			}
			_log.LogError((object)("[VoiceHandler] Vosk model not found at: " + text));
		}

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

		private void TryHookIntoPhotonVoice()
		{
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			_log.LogInfo((object)("[VoiceHandler] localCharacter: " + ((Object)localCharacter).name));
			PhotonVoiceView component = ((Component)localCharacter).GetComponent<PhotonVoiceView>();
			if ((Object)(object)component != (Object)null)
			{
				if ((Object)(object)component.RecorderInUse != (Object)null)
				{
					Recorder recorderInUse = component.RecorderInUse;
					VoiceHook voiceHook = ((Component)recorderInUse).gameObject.AddComponent<VoiceHook>();
					voiceHook.Initialize(this, recorderInUse);
					_activeHook = voiceHook;
					_log.LogInfo((object)("[VoiceHandler] Hooked into Recorder on: " + ((Object)((Component)recorderInUse).gameObject).name));
				}
			}
			else
			{
				PhotonVoiceView[] array = Object.FindObjectsByType<PhotonVoiceView>((FindObjectsSortMode)0);
				foreach (PhotonVoiceView val in array)
				{
					_log.LogInfo((object)$"[VoiceHandler] - {((Object)val).name}, RecorderInUse: {(Object)(object)val.RecorderInUse != (Object)null}");
				}
			}
		}

		public void OnPhotonVoiceReady(Recorder recorder, LocalVoice voice)
		{
			//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_0019: 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)
			VoiceInfo info = voice.Info;
			int num;
			if (((VoiceInfo)(ref info)).SamplingRate <= 0)
			{
				num = 48000;
			}
			else
			{
				info = voice.Info;
				num = ((VoiceInfo)(ref info)).SamplingRate;
			}
			int num2 = num;
			SetupVoiceRecognition();
			if (_recognizer is VoiceRecognizer && voice is LocalVoiceAudio<float> val)
			{
				((LocalVoiceFramed<float>)(object)val).AddPostProcessor(new IProcessor<float>[1]
				{
					new VoiceProcessor(_recognizer, num2)
				});
				_log.LogInfo((object)$"[VoiceHandler] Audio Processor attached. Resampling {num2} -> 16000 Hz.");
			}
			else
			{
				_log.LogWarning((object)("[VoiceHandler] 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)
				{
					_lastPartialText = "";
					_mainThreadActions.Enqueue(delegate
					{
						_log.LogInfo((object)("[Recognized]: " + text));
						_eventHandler?.HandleSpeech(text, 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)"[VoiceHandler] Vosk Recognizer started.");
			}
			catch (Exception ex)
			{
				_log.LogError((object)("Failed to start Vosk Recognizer: " + ex.Message));
			}
		}

		public void Dispose()
		{
			if (_networker != null)
			{
				PhotonNetwork.RemoveCallbackTarget((object)_networker);
				PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent;
			}
			_recognizer?.Stop();
			_recognizer?.Dispose();
			Model? voskModel = _voskModel;
			if (voskModel != null)
			{
				voskModel.Dispose();
			}
		}

		public void OnPhotonEvent(EventData eventData)
		{
			Plugin.Log.LogInfo((object)$"[VoiceHandler] OnPhotonEvent called - Code: {eventData.Code}");
			if (!_config.ChatEnabled.Value)
			{
				Plugin.Log.LogInfo((object)"[VoiceHandler] Chat disabled, skipping");
				return;
			}
			if (eventData.Code != 81)
			{
				Plugin.Log.LogInfo((object)$"[VoiceHandler] Not chat event (expected 81, got {eventData.Code})");
				return;
			}
			if (!(eventData.CustomData is object[] array) || array.Length < 4)
			{
				object[] obj = eventData.CustomData as object[];
				int num = ((obj != null) ? obj.Length : 0);
				Plugin.Log.LogWarning((object)$"[VoiceHandler] Invalid chat data: {num} items (expected 4+)");
				return;
			}
			string text = array[1]?.ToString();
			string text2 = array[2]?.ToString();
			Plugin.Log.LogInfo((object)("[VoiceHandler] Chat message: '" + text + "' from user: '" + text2 + "'"));
			if (string.IsNullOrWhiteSpace(text))
			{
				return;
			}
			Hashtable customProperties = PhotonNetwork.LocalPlayer.CustomProperties;
			string text3 = ((customProperties == null || !((Dictionary<object, object>)(object)customProperties).ContainsKey((object)"steamId")) ? PhotonNetwork.LocalPlayer.UserId : PhotonNetwork.LocalPlayer.CustomProperties[(object)"steamId"]?.ToString());
			if (string.IsNullOrEmpty(text3) || !string.Equals(text2, text3, StringComparison.Ordinal))
			{
				return;
			}
			string cleaned = NormalizeText(text);
			Plugin.Log.LogInfo((object)("[VoiceHandler] Processed chat message: '" + cleaned + "'"));
			Task.Delay(TimeSpan.FromSeconds((float)(_rng.NextDouble() * 2.5 + 0.5))).ContinueWith(delegate
			{
				_mainThreadActions.Enqueue(delegate
				{
					_eventHandler?.HandleSpeech(cleaned, isFinal: true);
				});
			});
		}

		private string NormalizeText(string input)
		{
			if (string.IsNullOrWhiteSpace(input))
			{
				return "";
			}
			input = input.ToLowerInvariant();
			input = Regex.Replace(input, "[^a-z0-9\\s]", " ");
			input = Regex.Replace(input, "\\s+", " ").Trim();
			return input;
		}

		private string CorrectTokenFuzzy(string token)
		{
			if (string.IsNullOrWhiteSpace(token))
			{
				return token;
			}
			token = token.ToLowerInvariant();
			char[] array = new char[token.Length];
			int num = 0;
			string text = token;
			foreach (char c in text)
			{
				if (num == 0 || array[num - 1] != c)
				{
					array[num++] = c;
				}
			}
			string text2 = new string(array, 0, num);
			string result = token;
			int num2 = int.MaxValue;
			foreach (string key in EventHandler.Events.Keys)
			{
				string text3 = key.ToLowerInvariant();
				int length = text2.Length;
				int length2 = text3.Length;
				if (Math.Abs(length - length2) <= Math.Max(length, length2) / 2)
				{
					int num3 = LevenshteinDistance(text2, text3);
					int num4 = Math.Max(1, Math.Min(length, length2) / 3 + 1);
					if ((num3 <= num4 || (num3 <= num4 + 1 && IsCommonTypo(text2, text3))) && num3 < num2)
					{
						num2 = num3;
						result = key;
					}
				}
			}
			return result;
		}

		private static int LevenshteinDistance(string s, string t)
		{
			int length = s.Length;
			int length2 = t.Length;
			int[,] array = new int[length + 1, length2 + 1];
			if (length == 0)
			{
				return length2;
			}
			if (length2 == 0)
			{
				return length;
			}
			int num = 0;
			while (num <= length)
			{
				array[num, 0] = num++;
			}
			int num2 = 0;
			while (num2 <= length2)
			{
				array[0, num2] = num2++;
			}
			for (int i = 1; i <= length; i++)
			{
				for (int j = 1; j <= length2; j++)
				{
					int num3 = ((t[j - 1] != s[i - 1]) ? 1 : 0);
					array[i, j] = Math.Min(Math.Min(array[i - 1, j] + 1, array[i, j - 1] + 1), array[i - 1, j - 1] + num3);
				}
			}
			return array[length, length2];
		}

		private static bool IsCommonTypo(string input, string target)
		{
			_ = new string[2] { "aeiou", "aeiouy" };
			if (input.Length != target.Length && Math.Abs(input.Length - target.Length) > 1)
			{
				return false;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			while (num2 < input.Length && num3 < target.Length)
			{
				if (input[num2] == target[num3])
				{
					num2++;
					num3++;
				}
				else if (IsVowel(input[num2]) && IsVowel(target[num3]))
				{
					num++;
					num2++;
					num3++;
				}
				else if (num2 + 1 < input.Length && num3 + 1 < target.Length && input[num2] == target[num3 + 1] && input[num2 + 1] == target[num3])
				{
					num++;
					num2 += 2;
					num3 += 2;
				}
				else if (num2 + 1 < input.Length && input[num2 + 1] == target[num3])
				{
					num++;
					num2++;
				}
				else if (num3 + 1 < target.Length && input[num2] == target[num3 + 1])
				{
					num++;
					num3++;
				}
				else
				{
					num++;
					num2++;
					num3++;
				}
			}
			return num <= 2;
		}

		private static bool IsVowel(char c)
		{
			c = char.ToLowerInvariant(c);
			if (c != 'a' && c != 'e' && c != 'i' && c != 'o' && c != 'u')
			{
				return c == 'y';
			}
			return true;
		}
	}
}
namespace VoiceCurseReborn.Helpers
{
	public static class CharacterExtensions
	{
		public static void DieInstantly(this Character player)
		{
			if ((Object)(object)player == (Object)null || player.data.dead)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Character), "DieInstantly", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					Plugin.Log.LogInfo((object)("[VoiceCurseReborn] DieInstantly: Calling game's DieInstantly for " + player.characterName));
					methodInfo.Invoke(player, null);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[VoiceCurseReborn] DieInstantly failed: " + ex.Message));
			}
		}

		public static void DieWithCheckpoint(this Character player)
		{
			player.DieInstantly();
		}

		public static void Fall(this Character player, float seconds, float screenShake = 0f)
		{
			AccessTools.Method(typeof(Character), "Fall", new Type[2]
			{
				typeof(float),
				typeof(float)
			}, (Type[])null).Invoke(player, new object[2] { seconds, screenShake });
		}

		public static void AddForce(this Character player, Vector3 move, float minRandomMultiplier = 1f, float maxRandomMultiplier = 1f)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			AccessTools.Method(typeof(Character), "AddForce", new Type[3]
			{
				typeof(Vector3),
				typeof(float),
				typeof(float)
			}, (Type[])null).Invoke(player, new object[3] { move, minRandomMultiplier, maxRandomMultiplier });
		}

		public static Bodypart GetBodypart(this Character player, BodypartType head)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			object? obj = AccessTools.Method(typeof(Character), "GetBodypart", new Type[1] { typeof(BodypartType) }, (Type[])null).Invoke(player, new object[1] { head });
			return (Bodypart)((obj is Bodypart) ? obj : null);
		}

		public static Rigidbody GetBodypartRig(this Character player, BodypartType head)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			object? obj = AccessTools.Method(typeof(Character), "GetBodypartRig", new Type[1] { typeof(BodypartType) }, (Type[])null).Invoke(player, new object[1] { head });
			return (Rigidbody)((obj is Rigidbody) ? obj : null);
		}

		public static void AddIllegalStatus(this Character player, string illegalStatus, float amount)
		{
			AccessTools.Method(typeof(Character), "AddIllegalStatus", new Type[2]
			{
				typeof(string),
				typeof(float)
			}, (Type[])null).Invoke(player, new object[2] { illegalStatus, amount });
		}

		public static bool OutOfRegularStamina(this Character player)
		{
			return (bool)AccessTools.Method(typeof(Character), "OutOfRegularStamina", (Type[])null, (Type[])null).Invoke(player, null);
		}

		public static void PassOutInstantly(this Character player)
		{
			AccessTools.Method(typeof(Character), "PassOutInstantly", (Type[])null, (Type[])null).Invoke(player, null);
		}

		public static bool WillDoCheckpoint(this Character player, out CheckpointFlag flag)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(Character), "WillDoCheckpoint", new Type[1] { typeof(CheckpointFlag).MakeByRefType() }, (Type[])null);
			if (methodInfo != null)
			{
				object[] array = new object[1];
				bool result = (bool)methodInfo.Invoke(player, array);
				flag = (CheckpointFlag)array[0];
				return result;
			}
			flag = null;
			return false;
		}

		public static bool TryCheckpoint(this Character player)
		{
			return (bool)AccessTools.Method(typeof(Character), "TryCheckpoint", (Type[])null, (Type[])null).Invoke(player, null);
		}
	}
	public static class CharacterAfflictionsExtensions
	{
		public static void UpdateWeight(this CharacterAfflictions afflictions)
		{
			AccessTools.Method(typeof(CharacterAfflictions), "UpdateWeight", (Type[])null, (Type[])null).Invoke(afflictions, null);
		}

		public static void AddArrow(this CharacterAfflictions afflictions, Vector3 position, Vector3 normal)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			AccessTools.Method(typeof(CharacterAfflictions), "AddArrow", new Type[2]
			{
				typeof(Vector3),
				typeof(Vector3)
			}, (Type[])null)?.Invoke(afflictions, new object[2] { position, normal });
		}

		public static void AddArrow(this CharacterAfflictions afflictions, Vector3 position, int type)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			AccessTools.Method(typeof(CharacterAfflictions), "AddThorn", new Type[2]
			{
				typeof(Vector3),
				typeof(int)
			}, (Type[])null)?.Invoke(afflictions, new object[2] { position, type });
		}
	}
}
namespace VoiceCurseReborn.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_0070: Unknown result type (might be due to invalid IL or missing references)
			foreach (string item in from w in configLine.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select w.Trim().ToLowerInvariant() into w
				where !string.IsNullOrWhiteSpace(w)
				select w)
			{
				_wordToType[item] = type;
			}
		}

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

		protected unsafe override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Invalid comparison between Unknown and I4
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Invalid comparison between Unknown and I4
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.AfflictionEnabled.Value)
			{
				return false;
			}
			if ((Object)(object)player.refs?.afflictions == (Object)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*)(&value))/*cast due to .constrained prefix*/).ToString();
			if (Config.AfflictionTemperatureSwapEnabled.Value && ((int)value == 2 || (int)value == 8))
			{
				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, true, false);
			return true;
		}

		private void HandleTemperatureExchange(Character player, STATUSTYPE incomingType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			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, true, false);
			}
		}
	}
	public class ArrowEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		public ArrowEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.ArrowKeywords?.Value);
		}

		protected override IEnumerable<string> GetKeywords()
		{
			ConfigEntry<bool> arrowEnabled = Config.ArrowEnabled;
			if (arrowEnabled != null && !arrowEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			ConfigEntry<bool> arrowEnabled = Config.ArrowEnabled;
			if (arrowEnabled != null && !arrowEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			Plugin.Log.LogInfo((object)("[VoiceCurse] ArrowEvent: Triggered for " + player.characterName));
			((MonoBehaviour)player).StartCoroutine(ArrowSequence(player));
			return true;
		}

		private IEnumerator ArrowSequence(Character player)
		{
			Plugin.Log.LogInfo((object)"[VoiceCurse] ArrowEvent: Spawning arrows directly on player");
			int arrowCount = Random.Range(Config.ArrowMinCount?.Value ?? 1, Config.ArrowMaxCount?.Value ?? 4);
			for (int i = 0; i < arrowCount; i++)
			{
				Vector3 val = player.Center + Random.onUnitSphere * 0.5f;
				val.y += Random.Range(-0.5f, 0.5f);
				Vector3 onUnitSphere = Random.onUnitSphere;
				onUnitSphere.y = Mathf.Abs(onUnitSphere.y) * 0.5f;
				((Vector3)(ref onUnitSphere)).Normalize();
				player.refs.afflictions.AddArrow(val, onUnitSphere);
				yield return (object)new WaitForSeconds(0.2f);
			}
			Plugin.Log.LogInfo((object)$"[VoiceCurse] ArrowEvent: Spawned {arrowCount} arrows on {player.characterName}");
		}

		public override void PlayEffects(Character origin, Vector3 position, string detail)
		{
			_ = (Object)(object)origin != (Object)null;
		}
	}
	public class BeeSwarmEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		public BeeSwarmEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.BeeKeywords.Value);
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.BeeEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (Config.BeeEnabled.Value && (Object)(object)player != (Object)null)
			{
				return !player.data.dead;
			}
			return false;
		}

		public override void PlayEffects(Character origin, Vector3 position)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient || (Object)(object)origin == (Object)null || origin.data.dead)
			{
				return;
			}
			GameObject val = PhotonNetwork.Instantiate("BeeSwarm", origin.Head, Quaternion.identity, (byte)0, (object[])null);
			if (!((Object)(object)val == (Object)null))
			{
				BeeSwarm component = val.GetComponent<BeeSwarm>();
				if (!((Object)(object)component == (Object)null))
				{
					((MonoBehaviourPun)component).photonView.RPC("SetBeesAngryRPC", (RpcTarget)0, new object[1] { true });
				}
			}
		}
	}
	public class BlindEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		private float _blindEndTime;

		private Coroutine? _blindRoutine;

		public BlindEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.BlindKeywords.Value);
		}

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

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

		private IEnumerator BlindnessRoutine(Character player)
		{
			while (Time.time < _blindEndTime && (Object)(object)player != (Object)null && !player.data.dead)
			{
				yield return null;
			}
			if ((Object)(object)player != (Object)null)
			{
				ToggleBlindness(player, enable: false);
			}
			_blindRoutine = null;
		}

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

		public DeathEvent(Config config)
			: base(config)
		{
			_deathKeywords = VoiceEventBase.ParseKeywords(config.DeathKeywords.Value);
		}

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

		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.DieWithCheckpoint();
			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_001a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)null)
			{
				DeathLocations[((MonoBehaviourPun)__instance).photonView.ViewID] = __instance.Center;
			}
		}

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

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

		public static Character? GetClosestDeadPlayer(Vector3 origin, out Vector3 deathPos)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_00a1: 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)(object)item.Ghost != (Object)null))
					{
						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 DropEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		public DropEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.DropKeywords.Value);
		}

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

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

		public override void PlayEffects(Character origin, Vector3 position)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient || (Object)(object)origin == (Object)null || origin.data.dead)
			{
				return;
			}
			Transform transform = origin.GetBodypart((BodypartType)0).transform;
			Vector3 val = transform.forward;
			if (Vector3.Dot(val, Vector3.up) < 0f)
			{
				val = -val;
			}
			Vector3 val2 = transform.position + val * 0.6f;
			if (origin.refs.items.currentSelectedSlot.IsSome && (Object)(object)origin.data.currentItem != (Object)null)
			{
				byte value = origin.refs.items.currentSelectedSlot.Value;
				ItemSlot itemSlot = origin.player.GetItemSlot(value);
				if (itemSlot != null && ((Object)(object)itemSlot.prefab == (Object)null || itemSlot.prefab.UIData.canDrop))
				{
					((MonoBehaviourPun)origin.refs.items).photonView.RPC("DropItemRpc", (RpcTarget)0, new object[7]
					{
						origin.refs.items.throwChargeLevel,
						value,
						((Component)origin.data.currentItem).transform.position,
						Vector3.zero,
						((Component)origin.data.currentItem).transform.rotation,
						itemSlot.data,
						true
					});
					val2 += Vector3.up * 0.5f;
				}
			}
			for (int num = 3; num >= 0; num--)
			{
				byte b = (byte)num;
				ItemSlot itemSlot2 = origin.player.GetItemSlot(b);
				if (itemSlot2 != null && ((Object)(object)itemSlot2.prefab == (Object)null || itemSlot2.prefab.UIData.canDrop) && !itemSlot2.IsEmpty())
				{
					((MonoBehaviourPun)origin.refs.items).photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val2 });
					val2 += Vector3.up * 0.5f;
				}
			}
		}
	}
	public class ExplodeEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		private static GameObject? _cachedExplosionPrefab;

		private static string? _cachedExplosionPrefabName;

		private float _lastExplodeTime = -999f;

		private const float EXPLODE_COOLDOWN = 0.8f;

		public ExplodeEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.ExplodeKeywords.Value);
		}

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

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.ExplodeEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			if (Time.time < _lastExplodeTime + 0.8f)
			{
				if (Config.EnableDebugLogs.Value)
				{
					Debug.Log((object)$"[VoiceCurseReborn] ExplodeEvent on cooldown ({0.8f}s)");
				}
				return false;
			}
			_lastExplodeTime = Time.time;
			return true;
		}

		public override void PlayEffects(Vector3 position)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if (Config.EnableDebugLogs.Value)
			{
				Debug.Log((object)$"[VoiceCurseReborn] ExplodeEvent.PlayEffects called at position: {position}");
			}
			if (!PhotonNetwork.IsMasterClient)
			{
				if (Config.EnableDebugLogs.Value)
				{
					Debug.Log((object)"[VoiceCurseReborn] Not master client, skipping explosion spawn");
				}
				return;
			}
			if (_cachedExplosionPrefabName == null)
			{
				FindExplosionPrefab();
			}
			if (false)
			{
				return;
			}
			try
			{
				GameObject val = PhotonNetwork.Instantiate("0_items/Dynamite", position, Quaternion.identity, (byte)0, (object[])null);
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				Dynamite component = val.GetComponent<Dynamite>();
				if ((Object)(object)component != (Object)null)
				{
					((MonoBehaviourPun)component).photonView.RPC("RPC_Explode", (RpcTarget)0, Array.Empty<object>());
					if (Config.EnableDebugLogs.Value)
					{
						Debug.Log((object)"[VoiceCurseReborn] Spawned Dynamite and exploded via RPC");
					}
				}
			}
			catch (Exception ex)
			{
				if (Config.EnableDebugLogs.Value)
				{
					Debug.LogWarning((object)("[VoiceCurseReborn] Failed to spawn Dynamite: " + ex.Message));
				}
			}
		}

		private void FindExplosionPrefab()
		{
			Dynamite val = Resources.FindObjectsOfTypeAll<Dynamite>().FirstOrDefault();
			if ((Object)(object)val != (Object)null && (Object)(object)val.explosionPrefab != (Object)null)
			{
				_cachedExplosionPrefab = val.explosionPrefab;
				_cachedExplosionPrefabName = ((Object)val.explosionPrefab).name;
				if (Config.EnableDebugLogs.Value)
				{
					Debug.Log((object)("[VoiceCurseReborn] Cached explosion prefab: " + _cachedExplosionPrefabName));
				}
			}
		}
	}
	public class FartEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		public FartEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.FartKeywords.Value);
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.FartEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (Config.FartEnabled.Value && (Object)(object)player != (Object)null)
			{
				return !player.data.dead;
			}
			return false;
		}

		public override void PlayEffects(Character origin, Vector3 position)
		{
			//IL_002a: 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)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)origin == (Object)null) && !origin.data.dead && !origin.IsGhost)
			{
				GameUtils.instance.SpawnResourceAtPositionNetworked("VFX_SporeExploExploEdibleSpawn", origin.Center, (RpcTarget)0);
				GameUtils.instance.RPC_SpawnResourceAtPosition("VFX_SporeExploExploEdibleSpawn_NoKnockback", origin.Center);
				Rigidbody bodypartRig = origin.GetBodypartRig((BodypartType)0);
				if ((Object)(object)bodypartRig != (Object)null)
				{
					float num = 100f;
					origin.AddForceToBodyPart(bodypartRig, Vector3.zero, Vector3.up * num);
				}
			}
		}
	}
	public class FrogEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		public FrogEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.FrogKeywords.Value);
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.FrogEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

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

		public override void PlayEffects(Character origin, Vector3 position, string detail)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0082: 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_0086: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_0098: 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_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_00d5: 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)
			if (!PhotonNetwork.IsMasterClient || (Object)(object)origin == (Object)null || origin.data.dead)
			{
				return;
			}
			int num = Random.Range(3, 8);
			Vector3 val = default(Vector3);
			for (int i = 0; i < num; i++)
			{
				float num2 = Random.Range(0f, 360f) * (MathF.PI / 180f);
				float num3 = Random.Range(5f, 20f);
				((Vector3)(ref val))..ctor(Mathf.Cos(num2) * num3, 0f, Mathf.Sin(num2) * num3);
				Vector3 groundPosition = GetGroundPosition(origin.Center + val);
				groundPosition = ((!(groundPosition == Vector3.zero)) ? (groundPosition + Vector3.up * 0.5f) : (origin.Center + val + Vector3.up * 0.5f));
				try
				{
					GameObject val2 = PhotonNetwork.Instantiate("0_Items/Frog", groundPosition, Quaternion.identity, (byte)0, (object[])null);
					if ((Object)(object)val2 != (Object)null)
					{
						RemoveAfterSeconds obj = val2.AddComponent<RemoveAfterSeconds>();
						obj.photonRemove = true;
						obj.seconds = 7f;
					}
				}
				catch (Exception)
				{
				}
			}
		}

		private Vector3 GetGroundPosition(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit groundPosRaycast = HelperFunctions.GetGroundPosRaycast(position + Vector3.up * 20f, (LayerType)1, 0f);
			if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null)
			{
				return ((RaycastHit)(ref groundPosRaycast)).point;
			}
			return Vector3.zero;
		}
	}
	public class GhostEvent : VoiceEventBase
	{
		[Serializable]
		private class GhostPayload
		{
			public int playerViewID;

			public Vector3 playerPosition;
		}

		private class GhostCoroutineRunner : MonoBehaviour
		{
			public void StartStaggeredSpawn(Vector3 position, int ghostCount)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				((MonoBehaviour)this).StartCoroutine(StaggeredSpawnCoroutine(position, ghostCount));
			}

			private IEnumerator StaggeredSpawnCoroutine(Vector3 position, int ghostCount)
			{
				//IL_000e: 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)
				for (int i = 0; i < ghostCount; i++)
				{
					Vector3 val = GetRandomPositionAroundPoint(position);
					if (val == Vector3.zero)
					{
						val = position + new Vector3(Random.Range(-15f, 15f), 5f, Random.Range(-15f, 15f));
					}
					PhotonNetwork.Instantiate("GhostBall", val, Quaternion.identity, (byte)0, (object[])null);
					if (i < ghostCount - 1)
					{
						yield return (object)new WaitForSeconds(0.8f);
					}
				}
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}

			private Vector3 GetRandomPositionAroundPoint(Vector3 center)
			{
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: 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_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_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: 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_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_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: 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)
				Vector3 val = default(Vector3);
				for (int i = 0; i < 5; i++)
				{
					float num = Random.Range(0f, 360f) * (MathF.PI / 180f);
					float num2 = Random.Range(12f, 15f);
					((Vector3)(ref val))..ctor(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2);
					RaycastHit groundPosRaycast = HelperFunctions.GetGroundPosRaycast(center + val + Vector3.up * 30f, (LayerType)1, 0f);
					if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null)
					{
						return ((RaycastHit)(ref groundPosRaycast)).point + Vector3.up * 0.5f;
					}
				}
				return center + new Vector3(0f, 5f, 0f);
			}
		}

		private readonly HashSet<string> _keywords;

		public GhostEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.GhostKeywords.Value);
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.GhostEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_003b: 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)
			if (!Config.GhostEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			GhostPayload ghostPayload = new GhostPayload
			{
				playerViewID = ((MonoBehaviourPun)player).photonView.ViewID,
				playerPosition = player.Center
			};
			base.ExecutionPayload = JsonUtility.ToJson((object)ghostPayload);
			return true;
		}

		public override void PlayEffects(Character origin, Vector3 position, string detail)
		{
			//IL_0051: 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)
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			GhostPayload ghostPayload = null;
			Character val = origin;
			if (!string.IsNullOrEmpty(detail))
			{
				try
				{
					ghostPayload = JsonUtility.FromJson<GhostPayload>(detail);
					Character val2 = default(Character);
					if (ghostPayload != null && ghostPayload.playerViewID != 0 && Character.GetCharacterWithPhotonID(ghostPayload.playerViewID, ref val2))
					{
						val = val2;
					}
				}
				catch (Exception)
				{
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				StartGhostSpawning(null, position);
			}
			else
			{
				StartGhostSpawning(val, val.Center);
			}
		}

		private void StartGhostSpawning(Character player, Vector3 position)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.IsMasterClient)
			{
				int num = Character.AllCharacters.Count((Character c) => !c.data.dead);
				int num2 = Mathf.Max(1, num / 2);
				num2 = Mathf.Clamp(num2, 1, 3);
				if ((Object)(object)player != (Object)null)
				{
					((MonoBehaviour)player).StartCoroutine(StaggeredGhostSpawn(player, num2));
				}
				else
				{
					new GameObject("GhostSpawnHost").AddComponent<GhostCoroutineRunner>().StartStaggeredSpawn(position, num2);
				}
			}
		}

		private IEnumerator StaggeredGhostSpawn(Character player, int ghostCount)
		{
			Vector3 val = default(Vector3);
			for (int i = 0; i < ghostCount; i++)
			{
				Vector3 randomPositionAroundPlayer = GetRandomPositionAroundPlayer(player);
				if (!(randomPositionAroundPlayer == Vector3.zero))
				{
					((Vector3)(ref val))..ctor(Random.Range(-2f, 2f), Random.Range(-0.5f, 0.5f), Random.Range(-2f, 2f));
					randomPositionAroundPlayer += val;
					PhotonNetwork.Instantiate("GhostBall", randomPositionAroundPlayer, Quaternion.identity, (byte)0, (object[])null);
					if (i < ghostCount - 1)
					{
						yield return (object)new WaitForSeconds(0.8f);
					}
				}
			}
		}

		private Vector3 GetRandomPositionAroundPlayer(Character player)
		{
			//IL_0010: 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_0009: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_0086: 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_00cf: 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_0099: 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_00a8: 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)
			if ((Object)(object)player == (Object)null)
			{
				return Vector3.zero;
			}
			Vector3 center = player.Center;
			Vector3 val = default(Vector3);
			for (int i = 0; i < 10; i++)
			{
				float num = Random.Range(0f, 360f) * (MathF.PI / 180f);
				float num2 = Random.Range(12f, 15f);
				((Vector3)(ref val))..ctor(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2);
				RaycastHit groundPosRaycast = HelperFunctions.GetGroundPosRaycast(center + val + Vector3.up * 30f, (LayerType)1, 0f);
				if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null)
				{
					return ((RaycastHit)(ref groundPosRaycast)).point + Vector3.up * 0.5f;
				}
			}
			return center + new Vector3(0f, 5f, 0f);
		}
	}
	public class KickEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		public KickEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.KickKeywords.Value);
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.KickEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (Config.KickEnabled.Value && (Object)(object)player != (Object)null && !player.data.dead && !player.data.isKicking && !player.data.isClimbingAnything && player.data.isGrounded)
			{
				return !player.OutOfRegularStamina();
			}
			return false;
		}

		public override void PlayEffects(Character origin, Vector3 position)
		{
			if (!((Object)(object)origin == (Object)null) && !origin.data.dead && !origin.data.isKicking)
			{
				origin.data.isKicking = true;
				((MonoBehaviourPun)origin).photonView.RPC("RPCA_Kick", (RpcTarget)0, Array.Empty<object>());
				((MonoBehaviour)origin).StartCoroutine(ResetKick(origin));
			}
		}

		private IEnumerator ResetKick(Character character)
		{
			yield return (object)new WaitForSeconds(1f);
			if ((Object)(object)character != (Object)null)
			{
				character.data.isKicking = false;
			}
		}
	}
	public class LaunchEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords;

		private static GameObject? _cachedLaunchSFX;

		private static int _launchUseCount;

		public LaunchEvent(Config config)
			: base(config)
		{
			_keywords = VoiceEventBase.ParseKeywords(config.LaunchKeywords.Value);
		}

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

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0041: 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_0098: 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_00a3: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_01fb: Unknown result type 

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);
	}
}