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((FindObjectsSortMode)0); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val.GetComponent() != (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($"VoiceCurse 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 EnableDebugLogs { get; private set; } public ConfigEntry GlobalCooldown { get; private set; } public ConfigEntry ChatEnabled { get; private set; } public ConfigEntry FuzzyChatMatchingEnabled { get; private set; } public ConfigEntry LaunchEnabled { get; private set; } public ConfigEntry LaunchKeywords { get; private set; } public ConfigEntry LaunchForceLowerBound { get; private set; } public ConfigEntry LaunchForceHigherBound { get; private set; } public ConfigEntry LaunchStunDuration { get; private set; } public ConfigEntry AfflictionEnabled { get; private set; } public ConfigEntry AfflictionMinPercent { get; private set; } public ConfigEntry AfflictionMaxPercent { get; private set; } public ConfigEntry AfflictionTemperatureSwapEnabled { get; private set; } public ConfigEntry AfflictionKeywordsInjury { get; private set; } public ConfigEntry AfflictionKeywordsHunger { get; private set; } public ConfigEntry AfflictionKeywordsCold { get; private set; } public ConfigEntry AfflictionKeywordsHot { get; private set; } public ConfigEntry AfflictionKeywordsPoison { get; private set; } public ConfigEntry AfflictionKeywordsSpores { get; private set; } public ConfigEntry TransmuteEnabled { get; private set; } public ConfigEntry TransmuteDeathEnabled { get; private set; } public ConfigEntry TransmuteMilkEnabled { get; private set; } public ConfigEntry TransmuteCactusEnabled { get; private set; } public ConfigEntry TransmuteCoconutEnabled { get; private set; } public ConfigEntry TransmuteAppleEnabled { get; private set; } public ConfigEntry TransmuteBananaEnabled { get; private set; } public ConfigEntry TransmuteEggEnabled { get; private set; } public ConfigEntry TransmuteFruitEnabled { get; private set; } public ConfigEntry TransmuteMushroomEnabled { get; private set; } public ConfigEntry TransmuteBallEnabled { get; private set; } public ConfigEntry TransmuteBingBongEnabled { get; private set; } public ConfigEntry TransmuteKingberryEnabled { get; private set; } public ConfigEntry DeathEnabled { get; private set; } public ConfigEntry DeathKeywords { get; private set; } public ConfigEntry ZombifyEnabled { get; private set; } public ConfigEntry ZombifyKeywords { get; private set; } public ConfigEntry SleepEnabled { get; private set; } public ConfigEntry SleepKeywords { get; private set; } public ConfigEntry DropEnabled { get; private set; } public ConfigEntry DropKeywords { get; private set; } public ConfigEntry ExplodeEnabled { get; private set; } public ConfigEntry ExplodeKeywords { get; private set; } public ConfigEntry ExplodeRadius { get; private set; } public ConfigEntry ExplodeDamage { get; private set; } public ConfigEntry ExplodeStunDuration { get; private set; } public ConfigEntry ExplodeForceLowerBound { get; private set; } public ConfigEntry ExplodeForceHigherBound { get; private set; } public ConfigEntry SlipEnabled { get; private set; } public ConfigEntry SlipKeywords { get; private set; } public ConfigEntry SlipStunDuration { get; private set; } public ConfigEntry BananaBombEnabled { get; private set; } public ConfigEntry BananaBombChance { get; private set; } public ConfigEntry BananaBombAmount { get; private set; } public ConfigEntry SacrificeEnabled { get; private set; } public ConfigEntry SacrificeKeywords { get; private set; } public ConfigEntry SacrificeCooldown { get; private set; } public ConfigEntry BlindEnabled { get; private set; } public ConfigEntry BlindKeywords { get; private set; } public ConfigEntry BlindDuration { get; private set; } public ConfigEntry FartEnabled { get; private set; } public ConfigEntry FartKeywords { get; private set; } public ConfigEntry RandomCosmeticsEnabled { get; private set; } public ConfigEntry RandomCosmeticsKeywords { get; private set; } public ConfigEntry VineEnabled { get; private set; } public ConfigEntry VineKeywords { get; private set; } public ConfigEntry BeeEnabled { get; private set; } public ConfigEntry BeeKeywords { get; private set; } public ConfigEntry KickEnabled { get; private set; } public ConfigEntry KickKeywords { get; private set; } public ConfigEntry CannonEnabled { get; private set; } public ConfigEntry CannonKeywords { get; private set; } public ConfigEntry RocketEnabled { get; private set; } public ConfigEntry RocketKeywords { get; private set; } public ConfigEntry GhostEnabled { get; private set; } public ConfigEntry GhostKeywords { get; private set; } public ConfigEntry FrogEnabled { get; private set; } public ConfigEntry FrogKeywords { get; private set; } public ConfigEntry TumbleweedEnabled { get; private set; } public ConfigEntry TumbleweedKeywords { get; private set; } public ConfigEntry TornadoEnabled { get; private set; } public ConfigEntry TornadoKeywords { get; private set; } public ConfigEntry CleanupKey { get; private set; } public ConfigEntry PetrifyEnabled { get; private set; } public ConfigEntry PetrifyKeywords { get; private set; } public ConfigEntry PetrifyMinAmount { get; private set; } public ConfigEntry PetrifyMaxAmount { get; private set; } public ConfigEntry ArrowEnabled { get; private set; } public ConfigEntry ArrowKeywords { get; private set; } public ConfigEntry ArrowMinCount { get; private set; } public ConfigEntry ArrowMaxCount { get; private set; } public Config(ConfigFile config) { EnableDebugLogs = config.Bind("Global", "EnableDebugLogs", false, "Enable debug logs for speech detection."); GlobalCooldown = config.Bind("Global", "GlobalCooldown", 1f, "The time in seconds that must pass before another voice event can be triggered."); ChatEnabled = config.Bind("Global", "EnableTextChat", true, "Enables the voice curse system for text chat."); FuzzyChatMatchingEnabled = config.Bind("Global", "EnableFuzzyMatching", true, "Enable fuzzy word matching for the text chat, ie. 'dexth' -> 'death'."); LaunchEnabled = config.Bind("Event.Launch", "Enabled", true, "Enable the Launch event."); LaunchKeywords = config.Bind("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("Event.Launch", "ForceLowerBound", 1800f, "Lowest possible amount of force applied to the player upon launching."); LaunchForceHigherBound = config.Bind("Event.Launch", "ForceHigherBound", 1800f, "Highest possible amount of force applied to the player upon launching."); LaunchStunDuration = config.Bind("Event.Launch", "StunDuration", 3f, "Duration in seconds the player will be stunned/ragdolled after launching."); AfflictionEnabled = config.Bind("Event.Affliction", "Enabled", true, "Enable the Affliction event."); AfflictionMinPercent = config.Bind("Event.Affliction", "MinPercent", 0.2f, "The minimum percentage (0.0 to 1.0) of the status bar to fill when triggered."); AfflictionMaxPercent = config.Bind("Event.Affliction", "MaxPercent", 0.35f, "The maximum percentage (0.0 to 1.0) of the status bar to fill when triggered."); AfflictionTemperatureSwapEnabled = config.Bind("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("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("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("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("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("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("Event.Affliction", "KeywordsSpores", "spore, pink, bacterium, germ, microorganism", "Keywords that trigger spore status."); TransmuteEnabled = config.Bind("Event.Transmute", "Enabled", true, "Enable the Transmute event."); TransmuteDeathEnabled = config.Bind("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("Event.Transmute", "EnableMilk", true, "Enable 'milk/calcium' -> Fortified Milk"); TransmuteCactusEnabled = config.Bind("Event.Transmute", "EnableCactus", true, "Enable 'cactus' -> Cactus"); TransmuteCoconutEnabled = config.Bind("Event.Transmute", "EnableCoconut", true, "Enable 'coconut' -> Coconut"); TransmuteAppleEnabled = config.Bind("Event.Transmute", "EnableApple", true, "Enable 'apple/berry' -> Crispberries"); TransmuteBananaEnabled = config.Bind("Event.Transmute", "EnableBanana", true, "Enable 'banana' -> Peel"); TransmuteEggEnabled = config.Bind("Event.Transmute", "EnableEgg", true, "Enable 'egg' -> Egg"); TransmuteFruitEnabled = config.Bind("Event.Transmute", "EnableFruit", true, "Enable 'fruit' -> Random Fruit"); TransmuteMushroomEnabled = config.Bind("Event.Transmute", "EnableMushroom", true, "Enable 'mushroom/fungus' -> Mushroom"); TransmuteBallEnabled = config.Bind("Event.Transmute", "EnableBall", true, "Enable 'ball' -> Basketball"); TransmuteBingBongEnabled = config.Bind("Event.Transmute", "EnableBingBong", true, "Enable 'eyy waddup' -> Bing Bong"); TransmuteKingberryEnabled = config.Bind("Event.Transmute", "EnableKingberry", true, "Enable 'babydoll' -> Purple Kingberry"); DeathEnabled = config.Bind("Event.Death", "Enabled", true, "Enable the Death event."); DeathKeywords = config.Bind("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("Event.Zombify", "Enabled", true, "Enable the Zombify event."); ZombifyKeywords = config.Bind("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("Event.Sleep", "Enabled", true, "Enable the Sleep event."); SleepKeywords = config.Bind("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("Event.Drop", "Enabled", true, "Enable the Drop event."); DropKeywords = config.Bind("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("Event.Explode", "Enabled", true, "Enable the Explode event."); ExplodeKeywords = config.Bind("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("Event.Explode", "Radius", 6f, "The radius of the explosion effect and damage."); ExplodeStunDuration = config.Bind("Event.Explode", "StunDuration", 3f, "Duration in seconds the player will be stunned/ragdolled after explosion."); ExplodeForceLowerBound = config.Bind("Event.Explode", "ForceLowerBound", 800f, "Lowest possible amount of explosion force applied."); ExplodeForceHigherBound = config.Bind("Event.Explode", "ForceHigherBound", 1200f, "Highest possible amount of explosion force applied."); SlipEnabled = config.Bind("Event.Slip", "Enabled", true, "Enable the Slip event."); SlipKeywords = config.Bind("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("Event.Slip", "StunDuration", 2f, "Duration in seconds the player will be stunned/ragdolled after slipping."); BananaBombEnabled = config.Bind("Event.Slip", "BananaBombEnabled", true, "Enable the rare Banana Bomb easter egg on slip."); BananaBombChance = config.Bind("Event.Slip", "BananaBombChance", 0.05f, "Chance (0.0 - 1.0) for a slip to trigger a Banana Bomb."); BananaBombAmount = config.Bind("Event.Slip", "BananaBombAmount", 20, "Amount of bananas to spawn during a Banana Bomb."); SacrificeEnabled = config.Bind("Event.Sacrifice", "Enabled", true, "Enable the Sacrifice event."); SacrificeKeywords = config.Bind("Event.Sacrifice", "Keywords", "sacrifice, trade, revive, resurrect, exchange, soul, offer", "List of keywords that trigger the sacrifice event."); SacrificeCooldown = config.Bind("Event.Sacrifice", "Cooldown", 300f, "Cooldown in seconds for the sacrifice event."); BlindEnabled = config.Bind("Event.Blind", "Enabled", true, "Enable the Blind event."); BlindKeywords = config.Bind("Event.Blind", "Keywords", "blind, flash, eyes, vision, can't see, my eyes", "List of keywords that trigger the blind event."); BlindDuration = config.Bind("Event.Blind", "Duration", 45f, "Duration in seconds the player will be blinded."); FartEnabled = config.Bind("Event.Fart", "Enabled", true, "Enable the Fart event."); FartKeywords = config.Bind("Event.Fart", "Keywords", "million, gas, cloud, inhale, vapors, toot", "Keywords that trigger the fart event."); RandomCosmeticsEnabled = config.Bind("Event.RandomCosmetics", "Enabled", true, "Enable the Random Cosmetics event."); RandomCosmeticsKeywords = config.Bind("Event.RandomCosmetics", "Keywords", "rigor, creek, nigga", "Keywords that trigger random cosmetics."); VineEnabled = config.Bind("Event.Vine", "Enabled", true, "Enable the Vine event."); VineKeywords = config.Bind("Event.Vine", "Keywords", "tiktok, vine, creeper, plant, bean, seed, kernel, tendril", "Keywords that trigger the vine event."); BeeEnabled = config.Bind("Event.Bee", "Enabled", true, "Enable the Bee event."); BeeKeywords = config.Bind("Event.Bee", "Keywords", "buzz, peace, bees, rape, honey, drone, harvest, party, social, gathering", "Keywords that trigger the bee event."); KickEnabled = config.Bind("Event.Kick", "Enabled", true, "Enable the Kick event."); KickKeywords = config.Bind("Event.Kick", "Keywords", "puppies, piece, help, gamer, boot, punt, kick, peace", "Keywords that trigger the kick event."); CannonEnabled = config.Bind("Event.Cannon", "Enabled", true, "Enable the Cannon event."); CannonKeywords = config.Bind("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("Event.Rocket", "Enabled", true, "Enable the Rocket event."); RocketKeywords = config.Bind("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("Event.Ghost", "Enabled", true, "Enable the Ghost event."); GhostKeywords = config.Bind("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("Event.Frog", "Enabled", true, "Enable the Frog event."); FrogKeywords = config.Bind("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("Event.Tumbleweed", "Enabled", true, "Enable the Tumbleweed event."); TumbleweedKeywords = config.Bind("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("Event.Tornado", "Enabled", true, "Enable the Tornado event."); TornadoKeywords = config.Bind("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("Event.Petrify", "Enabled", true, "Enable the Petrify event."); PetrifyKeywords = config.Bind("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("Event.Petrify", "MinAmount", 5, "Minimum petrify amount (0-100)."); PetrifyMaxAmount = config.Bind("Event.Petrify", "MaxAmount", 15, "Maximum petrify amount (0-100)."); ArrowEnabled = config.Bind("Event.Arrow", "Enabled", true, "Enable the Arrow event."); ArrowKeywords = config.Bind("Event.Arrow", "Keywords", "arrow, arrows, archer, bow, shoot, quiver, bolt, dart, projectile, piercing, puncture, arrowed, pierce, tip", "Keywords that trigger arrows."); ArrowMinCount = config.Bind("Event.Arrow", "MinCount", 2, "Minimum number of arrows to spawn."); ArrowMaxCount = config.Bind("Event.Arrow", "MaxCount", 5, "Maximum number of arrows to spawn."); CleanupKey = config.Bind("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(); } if ((Object)(object)_connectionLog == (Object)null) { GameObject val = GameObject.Find("PlayerConnectionLog"); if ((Object)(object)val != (Object)null) { _connectionLog = val.GetComponent(); } } 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 + "" + text2 + "" + 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 + "" + text5 + " triggered " + eventName + ""; } else { string text7 = "#" + ColorUtility.ToHtmlStringRGB(color); text6 = "" + playerName + " triggered " + eventName + ""; } _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, 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 _audioQueue = new ConcurrentQueue(); private Thread? _workerThread; private volatile bool _isRunning; private const int MaxQueueSize = 50; public event Action? OnPhraseRecognized; public event Action? 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? OnPhraseRecognized; event Action? OnPartialResult; void FeedAudio(short[] pcmData, int length); void Start(); void Stop(); } } namespace VoiceCurseReborn.Handlers { public class EventHandler { public static readonly Dictionary Events = new Dictionary(); private readonly Dictionary _previousWordCounts = new Dictionary(); private readonly Config _config; public EventHandler(Config config) { _config = config; Events.Clear(); RegisterEvents(config); } private static void RegisterEvents(Config config) { IEnumerable 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 dictionary = new Dictionary(); string[] array2 = array; foreach (string key in array2) { dictionary.TryAdd(key, 0); dictionary[key]++; } foreach (KeyValuePair 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 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.AllCharacters).FirstOrDefault((Func)((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 _mainThreadActions = new ConcurrentQueue(); 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(); if ((Object)(object)component != (Object)null) { if ((Object)(object)component.RecorderInUse != (Object)null) { Recorder recorderInUse = component.RecorderInUse; VoiceHook voiceHook = ((Component)recorderInUse).gameObject.AddComponent(); voiceHook.Initialize(this, recorderInUse); _activeHook = voiceHook; _log.LogInfo((object)("[VoiceHandler] Hooked into Recorder on: " + ((Object)((Component)recorderInUse).gameObject).name)); } } else { PhotonVoiceView[] array = Object.FindObjectsByType((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 val) { ((LocalVoiceFramed)(object)val).AddPostProcessor(new IProcessor[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)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 _wordToType; public AfflictionEvent(Config config) : base(config) { _wordToType = new Dictionary(); 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 GetKeywords() { if (!Config.AfflictionEnabled.Value) { return Enumerable.Empty(); } 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 _keywords; public ArrowEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.ArrowKeywords?.Value); } protected override IEnumerable GetKeywords() { ConfigEntry arrowEnabled = Config.ArrowEnabled; if (arrowEnabled != null && !arrowEnabled.Value) { return Enumerable.Empty(); } return _keywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { ConfigEntry 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 _keywords; public BeeSwarmEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.BeeKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.BeeEnabled.Value) { return Enumerable.Empty(); } 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(); if (!((Object)(object)component == (Object)null)) { ((MonoBehaviourPun)component).photonView.RPC("SetBeesAngryRPC", (RpcTarget)0, new object[1] { true }); } } } } public class BlindEvent : VoiceEventBase { private readonly HashSet _keywords; private float _blindEndTime; private Coroutine? _blindRoutine; public BlindEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.BlindKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.BlindEnabled.Value) { return Enumerable.Empty(); } 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 _deathKeywords; public DeathEvent(Config config) : base(config) { _deathKeywords = VoiceEventBase.ParseKeywords(config.DeathKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.DeathEnabled.Value) { return Enumerable.Empty(); } 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 DeathLocations = new Dictionary(); [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 _keywords; public DropEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.DropKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.DropEnabled.Value) { return Enumerable.Empty(); } 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 _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 GetKeywords() { if (!Config.ExplodeEnabled.Value) { return Enumerable.Empty(); } 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(); if ((Object)(object)component != (Object)null) { ((MonoBehaviourPun)component).photonView.RPC("RPC_Explode", (RpcTarget)0, Array.Empty()); 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().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 _keywords; public FartEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.FartKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.FartEnabled.Value) { return Enumerable.Empty(); } 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 _keywords; public FrogEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.FrogKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.FrogEnabled.Value) { return Enumerable.Empty(); } 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(); 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 _keywords; public GhostEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.GhostKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.GhostEnabled.Value) { return Enumerable.Empty(); } 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(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().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 _keywords; public KickEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.KickKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.KickEnabled.Value) { return Enumerable.Empty(); } 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()); ((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 _keywords; private static GameObject? _cachedLaunchSFX; private static int _launchUseCount; public LaunchEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.LaunchKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.LaunchEnabled.Value) { return Enumerable.Empty(); } 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 (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) if (!Config.LaunchEnabled.Value) { return false; } if (player.data.dead || player.data.fullyPassedOut) { return false; } float explodeChance = GetExplodeChance(); if (Random.value < explodeChance) { DoExplosion(player.Center, player); return true; } _launchUseCount++; if ((Object)(object)_cachedLaunchSFX == (Object)null) { FindLaunchSFX(); } player.Fall(Config.LaunchStunDuration.Value); Vector3 normalized = ((Vector3)(ref player.data.lookDirection_Flat)).normalized; Vector3 val = Vector3.Cross(Vector3.up, normalized); Vector3 val2; if (fullSentence.Contains("left")) { base.ExecutionDetail = "Left"; val2 = -val + Vector3.up * 0.2f; } else if (fullSentence.Contains("right")) { base.ExecutionDetail = "Right"; val2 = val + Vector3.up * 0.2f; } else if (fullSentence.Contains("backward") || fullSentence.Contains("backwards") || fullSentence.Contains("back")) { base.ExecutionDetail = "Back"; val2 = -normalized + Vector3.up * 0.2f; } else if (fullSentence.Contains("forward") || fullSentence.Contains("forwards")) { base.ExecutionDetail = "Forward"; val2 = normalized + Vector3.up * 0.2f; } else if (fullSentence.Contains("up")) { base.ExecutionDetail = "Up"; val2 = Vector3.up; } else { base.ExecutionDetail = "Random"; val2 = GetRandomUpwardDirection(); } ((Vector3)(ref val2)).Normalize(); float num = Random.Range(Config.LaunchForceLowerBound.Value, Config.LaunchForceHigherBound.Value); player.AddForce(val2 * num); return true; } private float GetExplodeChance() { int launchUseCount = _launchUseCount; if (launchUseCount < 3) { return 0f; } if (launchUseCount < 6) { return Mathf.Lerp(0.1f, 0.3f, Mathf.InverseLerp(3f, 6f, (float)launchUseCount)); } if (launchUseCount < 10) { return Mathf.Lerp(0.3f, 0.6f, Mathf.InverseLerp(6f, 10f, (float)launchUseCount)); } return 0.6f; } private void DoExplosion(Vector3 position, Character target) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if (Config.EnableDebugLogs.Value) { Plugin.Log.LogInfo((object)$"[VoiceCurseReborn] Launch explosion at {position}"); } Dynamite val = Resources.FindObjectsOfTypeAll().FirstOrDefault(); if ((Object)(object)val != (Object)null && (Object)(object)val.explosionPrefab != (Object)null) { Object.Instantiate(val.explosionPrefab, position, Quaternion.identity); } if (!((Object)(object)target == (Object)null) && !target.data.dead) { if ((Object)(object)target.refs.afflictions != (Object)null) { target.refs.afflictions.AddStatus((STATUSTYPE)0, 0.25f, false, true, true, false); } target.Fall(3f); Vector3 val2 = target.Center - position; Vector3 val3 = ((Vector3)(ref val2)).normalized + Vector3.up * 0.6f; ((Vector3)(ref val3)).Normalize(); target.AddForce(val3 * 1000f); } } private static Vector3 GetRandomUpwardDirection() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Vector3 onUnitSphere = Random.onUnitSphere; onUnitSphere.y = Mathf.Abs(onUnitSphere.y); if (onUnitSphere.y < 0.5f) { onUnitSphere.y = 0.5f; } return onUnitSphere; } public override void PlayEffects(Vector3 position) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cachedLaunchSFX == (Object)null) { FindLaunchSFX(); } if ((Object)(object)_cachedLaunchSFX != (Object)null) { GameObject obj = Object.Instantiate(_cachedLaunchSFX, position, Quaternion.identity); obj.SetActive(true); Object.Destroy((Object)(object)obj, 5f); } } private static void FindLaunchSFX() { ScoutCannon val = Resources.FindObjectsOfTypeAll().FirstOrDefault(); if ((Object)(object)val != (Object)null) { _cachedLaunchSFX = val.fireSFX; } } } public class PetrifyEvent : VoiceEventBase { private readonly HashSet _keywords; public PetrifyEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.PetrifyKeywords?.Value ?? "petrify, stone, statue, petrified, fossil, rock, solid, freeze, turn to stone, medusa, gorgon, gaze, basilisk, cockatrice"); } protected override IEnumerable GetKeywords() { ConfigEntry petrifyEnabled = Config.PetrifyEnabled; if (petrifyEnabled != null && !petrifyEnabled.Value) { return Enumerable.Empty(); } return _keywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { ConfigEntry petrifyEnabled = Config.PetrifyEnabled; if (petrifyEnabled != null && !petrifyEnabled.Value) { return false; } if (player.data.dead) { return false; } int num = Random.Range(5, 15); if (fullSentence.Contains("fully") || fullSentence.Contains("complete") || fullSentence.Contains("all the way")) { num = 100; } player.data.SetPetrify(player.data.petrifyAmount + num); player.refs.afflictions.PlayParticle((STATUSTYPE)13); base.ExecutionDetail = num.ToString(); return true; } public override void PlayEffects(Character origin, Vector3 position, string detail) { if ((Object)(object)origin != (Object)null && !origin.data.dead) { origin.refs.afflictions.PlayParticle((STATUSTYPE)13); } } } public class RandomCosmeticsEvent : VoiceEventBase { private readonly HashSet _keywords; public RandomCosmeticsEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.RandomCosmeticsKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.RandomCosmeticsEnabled.Value) { return Enumerable.Empty(); } return _keywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { if (Config.RandomCosmeticsEnabled.Value && (Object)(object)player != (Object)null) { return !player.data.dead; } return false; } public override void PlayEffects(Character origin, Vector3 position) { if (!((Object)(object)origin == (Object)null) && !origin.data.dead && !((Object)(object)origin.refs.customization == (Object)null)) { origin.refs.customization.RandomizeCosmetics(); } } } public class RocketEvent : VoiceEventBase { private readonly HashSet _keywords; public RocketEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.RocketKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.RocketEnabled.Value) { return Enumerable.Empty(); } return _keywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { if (!Config.RocketEnabled.Value) { return false; } if (player.data.dead) { return false; } Plugin.Log.LogInfo((object)"[VoiceCurseReborn] RocketEvent: Triggered!"); player.PassOutInstantly(); return true; } public override void PlayEffects(Character origin, Vector3 position, string detail) { if (PhotonNetwork.IsMasterClient && !((Object)(object)origin == (Object)null) && !origin.data.dead) { HandleRocketLogic(origin); } } private void HandleRocketLogic(Character player) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 if (!PhotonNetwork.IsMasterClient) { return; } ItemSlot itemSlot = player.player.GetItemSlot((byte)3); if (itemSlot.IsEmpty()) { SpawnAndEquipRocketpack(player); return; } BackpackSlot val = (BackpackSlot)(object)((itemSlot is BackpackSlot) ? itemSlot : null); if (val != null) { if ((int)val.backpackType == 4) { LightRocketpack(player); } else { ReplaceBackpackWithRocketpack(player, val); } } else { SpawnAndEquipRocketpack(player); } } private void SpawnAndEquipRocketpack(Character player) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) Item val = default(Item); if (!PhotonNetwork.IsMasterClient || !ItemDatabase.TryGetItem("Rocketpack", ref val)) { return; } ItemSlot itemSlot = player.player.GetItemSlot((byte)3); BackpackSlot val2 = (BackpackSlot)(object)((itemSlot is BackpackSlot) ? itemSlot : null); if (val2 != null) { ItemInstanceData val3 = new ItemInstanceData(Guid.NewGuid()); ItemInstanceDataHandler.AddInstanceData(val3); val2.backpackType = (BackpackType)4; ((ItemSlot)val2).SetItem(val, val3); BackpackData val4 = default(BackpackData); if (!((ItemSlot)val2).data.TryGetDataEntry((DataEntryKey)7, ref val4)) { val4 = ((ItemSlot)val2).data.RegisterNewEntry((DataEntryKey)7); } player.data.PushAll(); ((MonoBehaviour)player).StartCoroutine(DelayedLightRocket(player)); } } private void ReplaceBackpackWithRocketpack(Character player, BackpackSlot currentSlot) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) Item val = default(Item); if (PhotonNetwork.IsMasterClient && ItemDatabase.TryGetItem("Rocketpack", ref val)) { ((ItemSlot)currentSlot).EmptyOut(); ItemInstanceData val2 = new ItemInstanceData(Guid.NewGuid()); ItemInstanceDataHandler.AddInstanceData(val2); currentSlot.backpackType = (BackpackType)4; ((ItemSlot)currentSlot).SetItem(val, val2); BackpackData val3 = default(BackpackData); if (!((ItemSlot)currentSlot).data.TryGetDataEntry((DataEntryKey)7, ref val3)) { val3 = ((ItemSlot)currentSlot).data.RegisterNewEntry((DataEntryKey)7); } Plugin.Log.LogInfo((object)"[VoiceCurseReborn] RocketEvent: Replaced backpack with Rocketpack!"); player.data.PushAll(); ((MonoBehaviour)player).StartCoroutine(DelayedLightRocket(player)); } } private IEnumerator DelayedLightRocket(Character player) { yield return (object)new WaitForSeconds(1.6f); LightRocketpack(player); } private void LightRocketpack(Character player) { if ((Object)(object)player == (Object)null || player.data.dead) { return; } ((MonoBehaviourPun)player).photonView.RPC("RPCA_Light", (RpcTarget)0, new object[1] { 1.6f }); if (!((Object)(object)player.refs.backpackHandler != (Object)null)) { return; } try { MethodInfo method = typeof(CharacterBackpackHandler).GetMethod("LightRocket", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(player.refs.backpackHandler, new object[1] { 1.6f }); } } catch (Exception) { } } } public class SacrificeEvent : VoiceEventBase { private readonly HashSet _sacrificeKeywords; private float _lastSacrificeTime = -999f; public SacrificeEvent(Config config) : base(config) { _sacrificeKeywords = VoiceEventBase.ParseKeywords(config.SacrificeKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.SacrificeEnabled.Value) { return Enumerable.Empty(); } return _sacrificeKeywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { //IL_0044: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (!Config.SacrificeEnabled.Value) { return false; } if (player.data.dead) { return false; } if (Time.time < _lastSacrificeTime + Config.SacrificeCooldown.Value) { return false; } Vector3 deathPos; Character closestDeadPlayer = DeathTracker.GetClosestDeadPlayer(player.Center, out deathPos); if ((Object)(object)closestDeadPlayer == (Object)null) { return false; } _lastSacrificeTime = Time.time; Vector3 val = deathPos + Vector3.up * 1f; base.ExecutionDetail = "Reviving " + closestDeadPlayer.characterName; ((MonoBehaviourPun)closestDeadPlayer).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { val, true, -1 }); DeathTracker.RemoveDeath(closestDeadPlayer); player.DieInstantly(); return true; } } public class CannonEvent : VoiceEventBase { [Serializable] private class CannonPayload { public Vector3 centerPos; public Vector3 hipPos; public Vector3 lookDir; public int playerViewID; } private readonly HashSet _keywords; public CannonEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.CannonKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.CannonEnabled.Value) { return Enumerable.Empty(); } return _keywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0061: 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) if (!Config.CannonEnabled.Value) { return false; } if (player.data.dead) { return false; } Plugin.Log.LogInfo((object)"[VoiceCurseReborn] CannonEvent: Triggered!"); CannonPayload cannonPayload = new CannonPayload { centerPos = player.Center, hipPos = player.GetBodypart((BodypartType)0).transform.position, lookDir = player.data.lookDirection_Flat, playerViewID = ((MonoBehaviourPun)player).photonView.ViewID }; base.ExecutionPayload = JsonUtility.ToJson((object)cannonPayload); player.Fall(6f); return true; } public override void PlayEffects(Character origin, Vector3 position, string detail) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } CannonPayload cannonPayload = null; if (!string.IsNullOrEmpty(detail)) { try { cannonPayload = JsonUtility.FromJson(detail); } catch (Exception) { } } Character player = default(Character); if (cannonPayload == null || cannonPayload.playerViewID == 0) { if (!((Object)(object)origin == (Object)null)) { StartCannonSpawning(origin, origin.Center, origin.GetBodypart((BodypartType)0).transform.position, origin.data.lookDirection_Flat); } } else if (Character.GetCharacterWithPhotonID(cannonPayload.playerViewID, ref player)) { StartCannonSpawning(player, cannonPayload.centerPos, cannonPayload.hipPos, cannonPayload.lookDir); } } private void StartCannonSpawning(Character player, Vector3 centerPos, Vector3 hipPos, Vector3 lookDir) { //IL_0020: 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_0037: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } int num = Random.Range(4, 6); Plugin.Log.LogInfo((object)$"[VoiceCurseReborn] CannonEvent: Spawning {num} cannon(s) at position {centerPos}"); Vector3 groundPosition = GetGroundPosition(hipPos); if (groundPosition == Vector3.zero) { groundPosition = GetGroundPosition(centerPos); } Vector3 zero = default(Vector3); for (int i = 0; i < num; i++) { float num2 = Random.Range(0f, 360f) * (MathF.PI / 180f); float num3 = Random.Range(0.3f, 1.5f); ((Vector3)(ref zero))..ctor(Mathf.Cos(num2) * num3, 0f, Mathf.Sin(num2) * num3); if (num == 1) { zero = Vector3.zero; } Vector3 val = groundPosition + zero + Vector3.up * 0.5f; Vector3 val2 = lookDir; if (((Vector3)(ref val2)).magnitude < 0.1f) { val2 = Vector3.forward; } Quaternion val3 = Quaternion.LookRotation(val2); val3 *= Quaternion.Euler(-55f, 0f, 0f); GameObject val4; try { val4 = PhotonNetwork.Instantiate("ScoutCannon_Placed", val, val3, (byte)0, (object[])null); } catch (Exception) { continue; } if (!((Object)(object)val4 == (Object)null)) { Transform val5 = val4.transform.Find("Cannon/Entry"); if ((Object)(object)val5 != (Object)null) { Vector3 val6 = val5.position - val4.transform.position; val4.transform.position = val - val6; } else { val4.transform.position = val + Vector3.up * 0.5f; } ScoutCannon component = val4.GetComponent(); if ((Object)(object)component != (Object)null) { component.Light(); } RemoveAfterSeconds obj = val4.AddComponent(); obj.photonRemove = true; obj.seconds = 15f; } } if ((Object)(object)player != (Object)null && !player.data.dead) { player.PassOutInstantly(); ((MonoBehaviour)player).StartCoroutine(EnsurePassedOut(player)); } } private IEnumerator EnsurePassedOut(Character player) { for (int i = 0; i < 5; i++) { yield return (object)new WaitForSeconds(0.2f); if ((Object)(object)player != (Object)null && !player.data.dead && !player.data.fullyPassedOut) { player.PassOutInstantly(); } } } 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_0039: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0070: 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) RaycastHit groundPosRaycast = HelperFunctions.GetGroundPosRaycast(position + Vector3.up * 5f, (LayerType)1, 0f); if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null) { return ((RaycastHit)(ref groundPosRaycast)).point; } 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 position; } } public class SleepEvent : VoiceEventBase { private readonly HashSet _sleepKeywords; public SleepEvent(Config config) : base(config) { _sleepKeywords = VoiceEventBase.ParseKeywords(config.SleepKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.SleepEnabled.Value) { return Enumerable.Empty(); } return _sleepKeywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { if (!Config.SleepEnabled.Value) { return false; } if (player.data.passedOut || player.data.dead) { return false; } player.PassOutInstantly(); return true; } } public class SlipEvent : VoiceEventBase { private readonly HashSet _keywords; private static AudioClip? _cachedTripSound; private Item? _cachedBananaItem; private static readonly Regex NameCleaner = new Regex("\\s*\\((\\d+|Clone)\\)", RegexOptions.Compiled); public SlipEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.SlipKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.SlipEnabled.Value) { return Enumerable.Empty(); } return _keywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { //IL_0085: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if (!Config.SlipEnabled.Value) { return false; } if (player.data.dead || player.data.fullyPassedOut) { return false; } if (Config.BananaBombEnabled.Value && Random.value <= Config.BananaBombChance.Value) { base.ExecutionDetail = "BananaBomb"; } player.Fall(Config.SlipStunDuration.Value); Vector3 lookDirection_Flat = player.data.lookDirection_Flat; ApplyForceToPart(player, (BodypartType)16, (lookDirection_Flat + Vector3.up) * 200f); ApplyForceToPart(player, (BodypartType)13, (lookDirection_Flat + Vector3.up) * 200f); ApplyForceToPart(player, (BodypartType)0, Vector3.up * 1500f); ApplyForceToPart(player, (BodypartType)4, lookDirection_Flat * -300f); return true; } private static void ApplyForceToPart(Character player, BodypartType partType, Vector3 force) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) Rigidbody bodypartRig = player.GetBodypartRig(partType); if ((Object)(object)bodypartRig != (Object)null) { bodypartRig.AddForce(force, (ForceMode)1); } } public override void PlayEffects(Character origin, Vector3 position, string detail) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) base.PlayEffects(origin, position, detail); if (detail == "BananaBomb") { SpawnBananaBomb(position); } } public override void PlayEffects(Vector3 position) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) AudioClip tripSound = GetTripSound(); if ((Object)(object)tripSound != (Object)null) { AudioSource.PlayClipAtPoint(tripSound, position); } } private void SpawnBananaBomb(Vector3 origin) { //IL_0075: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } Item bananaItem = GetBananaItem(); if ((Object)(object)bananaItem == (Object)null) { if (Config.EnableDebugLogs.Value) { Debug.LogWarning((object)"[VoiceCurseReborn] Could not find 'Berrynana Peel Yellow' for Banana Bomb."); } return; } string text = NameCleaner.Replace(((Object)bananaItem).name, "").Trim(); string text2 = "0_Items/" + text; int value = Config.BananaBombAmount.Value; PhotonView val3 = default(PhotonView); Rigidbody val4 = default(Rigidbody); for (int i = 0; i < value; i++) { Vector3 val = origin + Random.insideUnitSphere * 3f; val.y = origin.y + 1.5f; GameObject val2 = PhotonNetwork.Instantiate(text2, val, Quaternion.identity, (byte)0, (object[])null); if ((Object)(object)val2 != (Object)null && val2.TryGetComponent(ref val3)) { val3.RPC("SetKinematicRPC", (RpcTarget)0, new object[3] { false, val, Quaternion.identity }); if (val2.TryGetComponent(ref val4)) { val4.isKinematic = false; Vector3 randomUpwardDirection = GetRandomUpwardDirection(); float num = Random.Range(25f, 200f); val4.AddForce(randomUpwardDirection * num, (ForceMode)1); } } } } private static Vector3 GetRandomUpwardDirection() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) Vector3 onUnitSphere = Random.onUnitSphere; onUnitSphere.y = Mathf.Abs(onUnitSphere.y); if (onUnitSphere.y < 0.2f) { onUnitSphere.y = 0.5f; } return ((Vector3)(ref onUnitSphere)).normalized; } private Item? GetBananaItem() { if ((Object)(object)_cachedBananaItem != (Object)null) { return _cachedBananaItem; } _cachedBananaItem = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)((Item i) => ((Object)i).name.Contains("Berrynana Peel Yellow"))); return _cachedBananaItem; } private static AudioClip? GetTripSound() { if ((Object)(object)_cachedTripSound == (Object)null) { _cachedTripSound = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)((AudioClip c) => ((Object)c).name == "Au_Slip1")); } return _cachedTripSound; } } public class TornadoEvent : VoiceEventBase { [Serializable] private class TornadoPayload { public int playerViewID; public Vector3 playerPosition; } private readonly HashSet _keywords; private static int _tornadoUseCount; private static float TORNADO_RANGE = 25f; private static float TORNADO_CAPTURE_DISTANCE = 10f; private static float TORNADO_LIFETIME_MIN = 4f; private static float TORNADO_LIFETIME_MAX = 6f; private static float TORNADO_SPAWN_MIN_DIST = 15f; private static float TORNADO_SPAWN_MAX_DIST = 25f; public TornadoEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.TornadoKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.TornadoEnabled.Value) { return Enumerable.Empty(); } 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.TornadoEnabled.Value) { return false; } if (player.data.dead) { return false; } TornadoPayload tornadoPayload = new TornadoPayload { playerViewID = ((MonoBehaviourPun)player).photonView.ViewID, playerPosition = player.Center }; base.ExecutionPayload = JsonUtility.ToJson((object)tornadoPayload); 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; } TornadoPayload tornadoPayload = null; Character val = origin; if (!string.IsNullOrEmpty(detail)) { try { tornadoPayload = JsonUtility.FromJson(detail); Character val2 = default(Character); if (tornadoPayload != null && tornadoPayload.playerViewID != 0 && Character.GetCharacterWithPhotonID(tornadoPayload.playerViewID, ref val2)) { val = val2; } } catch (Exception) { } } if ((Object)(object)val == (Object)null) { StartTornadoSpawning(null, position); } else { StartTornadoSpawning(val, val.Center); } } private void StartTornadoSpawning(Character player, Vector3 position) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } _tornadoUseCount++; float num = Random.Range(0f, 360f) * (MathF.PI / 180f); float num2 = Random.Range(TORNADO_SPAWN_MIN_DIST, TORNADO_SPAWN_MAX_DIST); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2); Vector3 val2 = GetGroundPosition(position + val); if (val2 == Vector3.zero) { val2 = position + val; } GameObject val3 = PhotonNetwork.Instantiate("Tornado", val2, Quaternion.identity, (byte)0, (object[])null); if ((Object)(object)val3 == (Object)null) { return; } Tornado component = val3.GetComponent(); if ((Object)(object)component == (Object)null) { return; } component.range = TORNADO_RANGE; component.captureDistance = TORNADO_CAPTURE_DISTANCE; component.tornadoLifetimeMin = TORNADO_LIFETIME_MIN; component.tornadoLifetimeMax = TORNADO_LIFETIME_MAX; GameObject val4 = new GameObject("TornadoTarget"); val4.transform.position = val2; GameObject val5 = new GameObject("TornadoPoints"); val5.transform.SetParent(val4.transform); val5.transform.position = val2; for (int i = 0; i < 5; i++) { GameObject val6 = new GameObject($"Target{i}"); val6.transform.SetParent(val5.transform); val6.transform.position = val2 + new Vector3(Random.Range(-10f, 10f), 0f, Random.Range(-10f, 10f)); if (i == 0 && (Object)(object)player != (Object)null) { val6.AddComponent().Target = player; } } FieldInfo field = typeof(Tornado).GetField("targetParent", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(component, val5.transform); } ((MonoBehaviour)component).StartCoroutine(ReselectTargetsRoutine(component, val5.transform)); ((MonoBehaviour)component).StartCoroutine(CleanupTarget(val4, TORNADO_LIFETIME_MAX + 5f)); } private IEnumerator ReselectTargetsRoutine(Tornado tornado, Transform pointsContainer) { while ((Object)(object)tornado != (Object)null && (Object)(object)pointsContainer != (Object)null && pointsContainer.childCount > 0) { yield return (object)new WaitForSeconds(Random.Range(5f, 10f)); if ((Object)(object)tornado == (Object)null || (Object)(object)pointsContainer == (Object)null) { break; } int num = Random.Range(0, pointsContainer.childCount); PhotonView component = ((Component)tornado).GetComponent(); if ((Object)(object)component != (Object)null) { component.RPC("RPCA_SelectTargetPos", (RpcTarget)0, new object[1] { num }); } } } private IEnumerator CleanupTarget(GameObject target, float delay) { yield return (object)new WaitForSeconds(delay); if ((Object)(object)target != (Object)null) { Object.Destroy((Object)(object)target); } } 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 * 30f, (LayerType)1, 0f); if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null) { return ((RaycastHit)(ref groundPosRaycast)).point; } return Vector3.zero; } } [Serializable] public class TransmutePayload { public string? ruleName; public bool isDeath; public int spawnCount; public Vector3 deathPosition; } public class TransmuteEvent : VoiceEventBase { private readonly List<(string Name, string[] Triggers, string[] Targets, Func IsEnabled)> _definitions; private readonly Dictionary IsEnabled)> _transmuteLookup; private readonly Dictionary _itemCache; private static readonly Regex NameCleaner = new Regex("\\s*\\((\\d+|Clone)\\)", RegexOptions.Compiled); public TransmuteEvent(Config config) : base(config) { _itemCache = new Dictionary(); _transmuteLookup = new Dictionary)>(); _definitions = new List<(string, string[], string[], Func)> { ("Milk", new string[2] { "milk", "calcium" }, new string[1] { "Fortified Milk" }, () => config.TransmuteMilkEnabled.Value), ("Cactus", new string[2] { "cactus", "cacti" }, new string[1] { "Cactus" }, () => config.TransmuteCactusEnabled.Value), ("Coconut", new string[1] { "coconut" }, new string[1] { "Coconut" }, () => config.TransmuteCoconutEnabled.Value), ("Apple", new string[3] { "apple", "berry", "berries" }, new string[3] { "Red Crispberry", "Yellow Crispberry", "Green Crispberry" }, () => config.TransmuteAppleEnabled.Value), ("Banana", new string[1] { "banana" }, new string[1] { "Berrynana Peel Yellow" }, () => config.TransmuteBananaEnabled.Value), ("Egg", new string[1] { "egg" }, new string[1] { "Egg" }, () => config.TransmuteEggEnabled.Value), ("Fruit", new string[1] { "fruit" }, new string[10] { "Red Crispberry", "Yellow Crispberry", "Green Crispberry", "Kingberry Purple", "Kingberry Yellow", "Kingberry Green", "Berrynana Brown", "Berrynana Yellow", "Berrynana Pink", "Berrynana Blue" }, () => config.TransmuteFruitEnabled.Value), ("Mushroom", new string[5] { "fungus", "mushroom", "fungi", "funghi", "shroom" }, new string[1] { "Mushroom Normie" }, () => config.TransmuteMushroomEnabled.Value), ("Ball", new string[1] { "ball" }, new string[1] { "Basketball" }, () => config.TransmuteBallEnabled.Value), ("Bing Bong", new string[5] { "a what up", "a what a", "ey waddup", "eyy waddup", "eyyy waddup" }, new string[1] { "Bing Bong" }, () => config.TransmuteBingBongEnabled.Value), ("Kingberrry", new string[4] { "baby doll", "baby girl", "babydoll", "babygirl" }, new string[1] { "Kingberry Purple" }, () => config.TransmuteKingberryEnabled.Value) }; foreach (var definition in _definitions) { string[] item = definition.Triggers; foreach (string key in item) { _transmuteLookup[key] = (definition.Name, definition.Targets, definition.IsEnabled); } } } protected override IEnumerable GetKeywords() { if (!Config.TransmuteEnabled.Value) { return Enumerable.Empty(); } return _definitions.Where<(string, string[], string[], Func)>(((string Name, string[] Triggers, string[] Targets, Func IsEnabled) d) => d.IsEnabled()).SelectMany<(string, string[], string[], Func), string>(((string Name, string[] Triggers, string[] Targets, Func IsEnabled) d) => d.Triggers); } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if (!Config.TransmuteEnabled.Value) { return false; } if (player.data.dead) { return false; } string text = null; string[] array = null; if (_transmuteLookup.TryGetValue(matchedKeyword, out (string, string[], Func) value) && value.Item3()) { (text, array, _) = value; } else { string text2 = _transmuteLookup.Keys.FirstOrDefault((string k) => fullSentence.Contains(k) && _transmuteLookup[k].IsEnabled()); if (text2 != null) { (text, array, _) = _transmuteLookup[text2]; } } if (array == null || array.Length == 0) { return false; } bool value2 = Config.TransmuteDeathEnabled.Value; Vector3 center = player.Center; TransmutePayload transmutePayload = new TransmutePayload { ruleName = text, isDeath = value2, spawnCount = 0, deathPosition = center }; if (value2) { player.DieInstantly(); int spawnCount = CountAndClearDroppedItems(player); transmutePayload.spawnCount = spawnCount; } base.ExecutionDetail = text; base.ExecutionPayload = JsonUtility.ToJson((object)transmutePayload); Plugin.Log.LogInfo((object)("[VoiceCurse] TransmuteEvent - ExecutionPayload set: " + base.ExecutionPayload)); return true; } private static int CountAndClearDroppedItems(Character player) { int num = 1; List droppedItems = player.refs.items.droppedItems; if (droppedItems != null) { num += droppedItems.Count; foreach (PhotonView item in droppedItems) { if ((Object)(object)item != (Object)null && (Object)(object)((Component)item).gameObject != (Object)null) { PhotonNetwork.Destroy(((Component)item).gameObject); } } droppedItems.Clear(); } return num; } private static IEnumerator DelayedClearItems(Character player, string ruleName) { yield return null; int num = 1; List droppedItems = player.refs.items.droppedItems; if (droppedItems != null) { num += droppedItems.Count; foreach (PhotonView item in droppedItems) { if ((Object)(object)item != (Object)null && (Object)(object)((Component)item).gameObject != (Object)null) { PhotonNetwork.Destroy(((Component)item).gameObject); } } droppedItems.Clear(); } TransmutePayload transmutePayload = new TransmutePayload { ruleName = ruleName, isDeath = true, spawnCount = num, deathPosition = player.Center }; NetworkHandler.SendCurseEvent("", ruleName, "Transmute", ruleName, JsonUtility.ToJson((object)transmutePayload), player.Center); } public override void PlayEffects(Character origin, Vector3 position, string detail) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)"[VoiceCurse] TransmuteEvent.PlayEffects CALLED!"); Plugin.Log.LogInfo((object)("[VoiceCurse] - detail: '" + detail + "'")); Plugin.Log.LogInfo((object)$"[VoiceCurse] - IsMasterClient: {PhotonNetwork.IsMasterClient}"); Plugin.Log.LogInfo((object)"[VoiceCurse] TransmuteEvent.PlayEffects - START"); Plugin.Log.LogInfo((object)$"[VoiceCurse] - origin: {(Object)(object)origin != (Object)null}, position: {position}, detail: '{detail}'"); Plugin.Log.LogInfo((object)$"[VoiceCurse] - detail length: {detail?.Length ?? 0}"); if (string.IsNullOrEmpty(detail) && !string.IsNullOrEmpty(base.ExecutionPayload)) { detail = base.ExecutionPayload; Plugin.Log.LogInfo((object)("[VoiceCurse] - Using ExecutionPayload: " + detail)); } if (!PhotonNetwork.IsMasterClient) { Plugin.Log.LogInfo((object)"[VoiceCurse] - Not master client, skipping PlayEffects"); return; } if ((Object)(object)origin == (Object)null) { Plugin.Log.LogInfo((object)"[VoiceCurse] - origin is null, skipping"); return; } if (string.IsNullOrEmpty(detail)) { Plugin.Log.LogInfo((object)"[VoiceCurse] - detail is empty, skipping"); return; } Plugin.Log.LogInfo((object)("[VoiceCurse] - Deserializing payload: " + detail)); TransmutePayload payload; try { payload = JsonUtility.FromJson(detail); Plugin.Log.LogInfo((object)$"[VoiceCurse] - Payload deserialized: ruleName={payload?.ruleName}, isDeath={payload?.isDeath}, spawnCount={payload?.spawnCount}"); } catch (Exception ex) { Plugin.Log.LogError((object)("[VoiceCurse] - Failed to deserialize payload: " + ex.Message)); return; } if (payload == null) { Plugin.Log.LogInfo((object)"[VoiceCurse] - payload is null, skipping"); return; } if (string.IsNullOrEmpty(payload.ruleName)) { Plugin.Log.LogInfo((object)"[VoiceCurse] - ruleName is empty, skipping"); return; } (string, string[], string[], Func) tuple = _definitions.FirstOrDefault<(string, string[], string[], Func)>(((string Name, string[] Triggers, string[] Targets, Func IsEnabled) d) => d.Name == payload.ruleName); ManualLogSource log = Plugin.Log; var (arg, _, array, _) = tuple; log.LogInfo((object)$"[VoiceCurse] - Found definition: {arg}, Targets: {((array != null) ? array.Length : 0)}"); if (tuple.Item3 == null || tuple.Item3.Length == 0) { Plugin.Log.LogInfo((object)"[VoiceCurse] - No targets found, skipping"); return; } if (payload.isDeath) { Vector3 val = ((payload.deathPosition != Vector3.zero) ? payload.deathPosition : origin.Center); Plugin.Log.LogInfo((object)$"[VoiceCurse] - Death mode, spawning {payload.spawnCount} items at {val}"); if (payload.spawnCount <= 0) { payload.spawnCount = 1; Plugin.Log.LogInfo((object)("[VoiceCurse] - " + payload.ruleName + ": spawnCount was 0, forcing to 1")); } SpawnTransmutedItems(val, payload.spawnCount, tuple.Item3); } else { Plugin.Log.LogInfo((object)"[VoiceCurse] - Alive mode, transmuting inventory"); TransmuteInventoryAlive(origin, tuple.Item3); float num = Random.Range(Config.AfflictionMinPercent.Value, Config.AfflictionMaxPercent.Value); if ((Object)(object)origin.refs.afflictions != (Object)null) { Plugin.Log.LogInfo((object)$"[VoiceCurse] - Adding injury: {num}"); origin.refs.afflictions.AddStatus((STATUSTYPE)0, num, false, true, true, false); } } Plugin.Log.LogInfo((object)"[VoiceCurse] TransmuteEvent.PlayEffects - END"); } private void TransmuteInventoryAlive(Character player, string[] possibleTargets) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0f, -5000f, 0f); Vector3 center = player.Center; ((MonoBehaviourPun)player.refs.items).photonView.RPC("EquipSlotRpc", (RpcTarget)0, new object[2] { -1, -1 }); for (byte b = 0; b < 3; b++) { ItemSlot itemSlot = player.player.GetItemSlot(b); if (itemSlot != null && !itemSlot.IsEmpty()) { ((MonoBehaviourPun)player.refs.items).photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val }); SpawnTransmutedItems(center, 1, possibleTargets); } } ItemSlot itemSlot2 = player.player.GetItemSlot((byte)3); if (itemSlot2 != null && !itemSlot2.IsEmpty()) { int num = 1; BackpackData val2 = default(BackpackData); if (itemSlot2.data.TryGetDataEntry((DataEntryKey)7, ref val2)) { num += val2.FilledSlotCount(); } ((MonoBehaviourPun)player.refs.items).photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { (byte)3, val }); SpawnTransmutedItems(center, num, possibleTargets); } player.refs.afflictions?.UpdateWeight(); } private void SpawnTransmutedItems(Vector3 origin, int count, string[] targets) { //IL_0010: 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) Plugin.Log.LogInfo((object)$"[VoiceCurse] SpawnTransmutedItems - Spawning {count} items at {origin}"); for (int i = 0; i < count; i++) { Plugin.Log.LogInfo((object)$"[VoiceCurse] SpawnTransmutedItems - Spawning item {i + 1}/{count}"); SpawnItem(origin, targets, autoPickup: false, null); } } private void SpawnItem(Vector3 origin, string[] targets, bool autoPickup, Character? picker) { //IL_006c: 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) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) string text = targets[Random.Range(0, targets.Length)]; Plugin.Log.LogInfo((object)("[VoiceCurse] SpawnItem - Searching for: '" + text + "'")); Item orFindItem = GetOrFindItem(text); if ((Object)(object)orFindItem == (Object)null) { Plugin.Log.LogWarning((object)("[VoiceCurse] SpawnItem - Item not found: '" + text + "'")); return; } Plugin.Log.LogInfo((object)("[VoiceCurse] SpawnItem - Found item: " + ((Object)orFindItem).name)); Vector3 val = origin + Random.insideUnitSphere * 0.5f; val.y = origin.y + 1.5f; RaycastHit groundPosRaycast = HelperFunctions.GetGroundPosRaycast(val + Vector3.up * 10f, (LayerType)1, 0f); if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null) { val = ((RaycastHit)(ref groundPosRaycast)).point + Vector3.up * 0.5f; } Plugin.Log.LogInfo((object)$"[VoiceCurse] SpawnItem - Position: {val}"); string text2 = NameCleaner.Replace(((Object)orFindItem).name, "").Trim(); string text3 = "0_Items/" + text2; Plugin.Log.LogInfo((object)("[VoiceCurse] SpawnItem - Prefab: '" + text3 + "'")); GameObject val2 = PhotonNetwork.Instantiate(text3, val, Quaternion.identity, (byte)0, (object[])null); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogError((object)("[VoiceCurse] SpawnItem - Failed to instantiate: '" + text3 + "'")); return; } Plugin.Log.LogInfo((object)$"[VoiceCurse] SpawnItem - Instantiated: {((Object)val2).name} at {val}"); PhotonView val3 = default(PhotonView); if (!val2.TryGetComponent(ref val3)) { Plugin.Log.LogWarning((object)"[VoiceCurse] SpawnItem - No PhotonView on instantiated object"); return; } val3.RPC("SetKinematicRPC", (RpcTarget)0, new object[3] { false, val, Quaternion.identity }); Plugin.Log.LogInfo((object)"[VoiceCurse] SpawnItem - SetKinematicRPC called"); Item val4 = default(Item); if (autoPickup && (Object)(object)picker != (Object)null && val2.TryGetComponent(ref val4)) { Plugin.Log.LogInfo((object)"[VoiceCurse] SpawnItem - Auto-pickup for picker"); if ((Object)(object)picker.refs?.items != (Object)null) { picker.refs.items.lastEquippedSlotTime = 0f; } val4.Interact(picker); } } private Item? GetOrFindItem(string searchName) { Plugin.Log.LogInfo((object)("[VoiceCurse] GetOrFindItem - Searching for: '" + searchName + "'")); if (_itemCache.TryGetValue(searchName, out Item value) && (Object)(object)value != (Object)null) { Plugin.Log.LogInfo((object)("[VoiceCurse] GetOrFindItem - Found in cache: " + ((Object)value).name)); return value; } if ((Object)(object)value == (Object)null) { _itemCache.Remove(searchName); } Item val = null; try { Item val2 = default(Item); if (ItemDatabase.TryGetItem(searchName, ref val2)) { val = val2; Plugin.Log.LogInfo((object)("[VoiceCurse] GetOrFindItem - Found in ItemDatabase: " + ((Object)val2).name)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[VoiceCurse] GetOrFindItem - ItemDatabase lookup failed: " + ex.Message)); } if ((Object)(object)val == (Object)null) { Item[] array = Resources.FindObjectsOfTypeAll(); Plugin.Log.LogInfo((object)$"[VoiceCurse] GetOrFindItem - Searching {array.Length} items in Resources"); val = ((IEnumerable)array).FirstOrDefault((Func)((Item i) => ((Object)i).name.Contains(searchName) || (i.UIData != null && i.UIData.itemName.Contains(searchName)))); if ((Object)(object)val != (Object)null) { Plugin.Log.LogInfo((object)("[VoiceCurse] GetOrFindItem - Found in Resources: " + ((Object)val).name)); } } _itemCache[searchName] = val; if ((Object)(object)val == (Object)null && Config.EnableDebugLogs.Value) { Debug.LogWarning((object)("[VoiceCurse] Could not find item matching '" + searchName + "'")); } return val; } } public class TumbleweedEvent : VoiceEventBase { [Serializable] private class TumbleweedPayload { public int playerViewID; public Vector3 playerPosition; } private class TumbleweedCoroutineRunner : MonoBehaviour { public void StartTumbleweedCascade(Character player, Vector3 position, int waves, int tumbleweedsPerWave, float waveInterval, float tumbleweedLifetime) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) ((MonoBehaviour)this).StartCoroutine(RunCascade(player, position, waves, tumbleweedsPerWave, waveInterval, tumbleweedLifetime)); } private IEnumerator RunCascade(Character player, Vector3 position, int waves, int tumbleweedsPerWave, float waveInterval, float tumbleweedLifetime) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) yield return TumbleweedCascadeStatic(player, position, waves, tumbleweedsPerWave, waveInterval, tumbleweedLifetime); Object.Destroy((Object)(object)((Component)this).gameObject); } private IEnumerator TumbleweedCascadeStatic(Character player, Vector3 position, int waves, int tumbleweedsPerWave, float waveInterval, float tumbleweedLifetime) { //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) if (!PhotonNetwork.IsMasterClient) { yield break; } List allTumbleweeds = new List(); Vector3 val = default(Vector3); for (int wave = 0; wave < waves; wave++) { List list = new List(); for (int i = 0; i < tumbleweedsPerWave; i++) { float num = Random.Range(0f, 360f) * (MathF.PI / 180f); float num2 = Random.Range(8f, 25f); ((Vector3)(ref val))..ctor(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2); Vector3 groundPositionStatic = GetGroundPositionStatic(position + val); groundPositionStatic = ((!(groundPositionStatic == Vector3.zero)) ? (groundPositionStatic + Vector3.up * 2f) : (position + val + Vector3.up * 2f)); GameObject val2; try { val2 = PhotonNetwork.Instantiate("tumbleweed", groundPositionStatic, Quaternion.identity, (byte)0, (object[])null); } catch (Exception ex) { Plugin.Log.LogError((object)("[TumbleweedEvent] Failed to spawn tumbleweed: " + ex.Message)); continue; } if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"[TumbleweedEvent] Tumbleweed spawn returned null"); continue; } list.Add(val2); allTumbleweeds.Add(val2); RemoveAfterSeconds val3 = val2.GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent(); } val3.photonRemove = true; val3.seconds = tumbleweedLifetime; } Plugin.Log.LogInfo((object)$"[TumbleweedEvent] Wave {wave + 1}/{waves} spawned ({list.Count} tumbleweeds)"); yield return (object)new WaitForSeconds(waveInterval); } Plugin.Log.LogInfo((object)$"[TumbleweedEvent] All {waves} waves completed. Total tumbleweeds: {allTumbleweeds.Count}"); } private Vector3 GetGroundPositionStatic(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 * 30f, (LayerType)1, 0f); if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null) { return ((RaycastHit)(ref groundPosRaycast)).point; } return Vector3.zero; } } private readonly HashSet _keywords; public TumbleweedEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.TumbleweedKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.TumbleweedEnabled.Value) { return Enumerable.Empty(); } return _keywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { //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) if (!Config.TumbleweedEnabled.Value) { return false; } if (player.data.dead) { return false; } Plugin.Log.LogInfo((object)"[TumbleweedEvent] Triggered!"); TumbleweedPayload tumbleweedPayload = new TumbleweedPayload { playerViewID = ((MonoBehaviourPun)player).photonView.ViewID, playerPosition = player.Center }; base.ExecutionPayload = JsonUtility.ToJson((object)tumbleweedPayload); return true; } public override void PlayEffects(Character origin, Vector3 position, string detail) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } TumbleweedPayload tumbleweedPayload = null; Character val = origin; if (!string.IsNullOrEmpty(detail)) { try { tumbleweedPayload = JsonUtility.FromJson(detail); Plugin.Log.LogInfo((object)$"[TumbleweedEvent] Payload deserialized - playerViewID: {tumbleweedPayload?.playerViewID}"); Character val2 = default(Character); if (tumbleweedPayload != null && tumbleweedPayload.playerViewID != 0 && Character.GetCharacterWithPhotonID(tumbleweedPayload.playerViewID, ref val2)) { val = val2; } } catch (Exception ex) { Plugin.Log.LogError((object)("[TumbleweedEvent] Failed to deserialize payload: " + ex.Message)); } } if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"[TumbleweedEvent] No player found, using origin position"); StartTumbleweedSpawning(null, position); } else { StartTumbleweedSpawning(val, val.Center); } } private void StartTumbleweedSpawning(Character player, Vector3 position) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.IsMasterClient) { int waves = 10; int num = Mathf.Max(4, Character.AllCharacters.Count((Character c) => !c.data.dead) * 3); num = Mathf.Min(num, 3); float waveInterval = 3.5f; float tumbleweedLifetime = 4f; new GameObject("TumbleweedCoroutineHost").AddComponent().StartTumbleweedCascade(player, position, waves, num, waveInterval, tumbleweedLifetime); } } private IEnumerator TumbleweedCascade(Character player, Vector3 position, int waves, int tumbleweedsPerWave, float waveInterval, float tumbleweedLifetime) { //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) if (!PhotonNetwork.IsMasterClient) { yield break; } List allTumbleweeds = new List(); Vector3 val = default(Vector3); for (int wave = 0; wave < waves; wave++) { List list = new List(); for (int i = 0; i < tumbleweedsPerWave; i++) { float num = Random.Range(0f, 360f) * (MathF.PI / 180f); float num2 = Random.Range(8f, 25f); ((Vector3)(ref val))..ctor(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2); Vector3 groundPosition = GetGroundPosition(position + val); groundPosition = ((!(groundPosition == Vector3.zero)) ? (groundPosition + Vector3.up * 2f) : (position + val + Vector3.up * 2f)); GameObject val2; try { val2 = PhotonNetwork.Instantiate("tumbleweed", groundPosition, Quaternion.identity, (byte)0, (object[])null); } catch (Exception ex) { Plugin.Log.LogError((object)("[TumbleweedEvent] Failed to spawn tumbleweed: " + ex.Message)); continue; } if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"[TumbleweedEvent] Tumbleweed spawn returned null"); continue; } list.Add(val2); allTumbleweeds.Add(val2); RemoveAfterSeconds val3 = val2.GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent(); } val3.photonRemove = true; val3.seconds = tumbleweedLifetime; } Plugin.Log.LogInfo((object)$"[TumbleweedEvent] Wave {wave + 1}/{waves} spawned ({list.Count} tumbleweeds)"); yield return (object)new WaitForSeconds(waveInterval); } Plugin.Log.LogInfo((object)$"[TumbleweedEvent] All {waves} waves completed. Total tumbleweeds: {allTumbleweeds.Count}"); } 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 * 30f, (LayerType)1, 0f); if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null) { return ((RaycastHit)(ref groundPosRaycast)).point; } return Vector3.zero; } } public class VineEvent : VoiceEventBase { private readonly HashSet _keywords; private static GameObject? _cachedExplosionPrefab; private static int _vineUseCount; private static float VINE_LIFETIME = 15f; public VineEvent(Config config) : base(config) { _keywords = VoiceEventBase.ParseKeywords(config.VineKeywords.Value); } protected override IEnumerable GetKeywords() { if (!Config.VineEnabled.Value) { return Enumerable.Empty(); } return _keywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (!Config.VineEnabled.Value || (Object)(object)player == (Object)null || player.data.dead) { return false; } float explodeChance = GetExplodeChance(); if (Random.value < explodeChance) { Debug.Log((object)$"[VoiceCurseReborn] Vine turned into EXPLOSION (chance={explodeChance:P}, uses={_vineUseCount})"); DoExplosion(player.Center, player); return true; } return true; } public override void PlayEffects(Character origin, Vector3 position) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_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_009d: 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) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0148: 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) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient || (Object)(object)origin == (Object)null || origin.data.dead) { return; } _vineUseCount++; Vector3 val = Random.onUnitSphere; val.y = 0f; ((Vector3)(ref val)).Normalize(); float num = Random.Range(-15f, -5f); Vector3 val2 = Vector3.down * Mathf.Tan(num * (MathF.PI / 180f)); Vector3 val3 = val + val2; val = ((Vector3)(ref val3)).normalized; float num2 = Random.Range(40f, 60f); Vector3 val4 = origin.Center + val * num2; RaycastHit groundPosRaycast = HelperFunctions.GetGroundPosRaycast(val4 + Vector3.up * 20f, (LayerType)1, 0f); val4 = ((!((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null)) ? (origin.Center + val * num2) : ((RaycastHit)(ref groundPosRaycast)).point); Plugin.Log.LogInfo((object)$"[VoiceCurseReborn] Growing vine at {val4} (direction: {val}, distance: {num2})"); GameObject val5 = Resources.Load("MagicBeanVine"); if ((Object)(object)val5 != (Object)null) { Vector3 val6 = (((Object)(object)((RaycastHit)(ref groundPosRaycast)).collider != (Object)null) ? ((RaycastHit)(ref groundPosRaycast)).normal : Vector3.up); Quaternion val7 = Quaternion.LookRotation(Vector3.Cross(val6, Vector3.right), val6); GameObject val8 = PhotonNetwork.InstantiateRoomObject(((Object)val5).name, val4, val7, (byte)0, (object[])null); if ((Object)(object)val8 != (Object)null) { MagicBeanVine component = val8.GetComponent(); if ((Object)(object)component != (Object)null) { component.maxLength = Random.Range(1f, 5f); component.growingSpeed = Random.Range(0.1f, 0.3f); component.maxWidth = Random.Range(0.2f, 4f); Plugin.Log.LogInfo((object)$"[VoiceCurseReborn] Vine spawned! maxLength: {component.maxLength}, growingSpeed: {component.growingSpeed}"); } RemoveAfterSeconds obj = val8.AddComponent(); obj.photonRemove = true; obj.seconds = VINE_LIFETIME; Plugin.Log.LogInfo((object)$"[VoiceCurseReborn] Vine will auto-destroy in {VINE_LIFETIME} seconds"); } return; } Debug.LogWarning((object)"[VoiceCurseReborn] MagicBeanVine prefab not found!"); Vector3 val9 = origin.Center + val * 3f + Vector3.up * 1f; GameObject val10 = PhotonNetwork.Instantiate("0_Items/MagicBean", val9, Quaternion.identity, (byte)0, (object[])null); if ((Object)(object)val10 != (Object)null) { Item component2 = val10.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.SetKinematicNetworked(false, val9, Quaternion.identity); } RemoveAfterSeconds obj2 = val10.AddComponent(); obj2.photonRemove = true; obj2.seconds = VINE_LIFETIME; } } private float GetExplodeChance() { int vineUseCount = _vineUseCount; if (vineUseCount < 5) { return 0f; } if (vineUseCount < 10) { return Mathf.Lerp(0.1f, 0.4f, Mathf.InverseLerp(5f, 10f, (float)vineUseCount)); } if (vineUseCount < 15) { return Mathf.Lerp(0.4f, 0.8f, Mathf.InverseLerp(10f, 15f, (float)vineUseCount)); } return 0.8f; } private void FindExplosionPrefab() { Dynamite val = Resources.FindObjectsOfTypeAll().FirstOrDefault(); if ((Object)(object)val != (Object)null && (Object)(object)val.explosionPrefab != (Object)null) { _cachedExplosionPrefab = val.explosionPrefab; } else { Debug.LogWarning((object)"[VoiceCurseReborn] No Dynamite found for explosion prefab cache."); } } private void DoExplosion(Vector3 position, Character target) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (Config.EnableDebugLogs.Value) { Debug.Log((object)$"[VoiceCurseReborn] Vine explosion at {position}"); } if (!PhotonNetwork.IsMasterClient) { return; } if ((Object)(object)_cachedExplosionPrefab == (Object)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(); if ((Object)(object)component != (Object)null) { ((MonoBehaviourPun)component).photonView.RPC("RPC_Explode", (RpcTarget)0, Array.Empty()); if (Config.EnableDebugLogs.Value) { Debug.Log((object)"[VoiceCurseReborn] Vine: Spawned Dynamite and exploded via RPC"); } } } catch (Exception ex) { if (Config.EnableDebugLogs.Value) { Debug.LogWarning((object)("[VoiceCurseReborn] Vine: Failed to spawn Dynamite: " + ex.Message)); } } } } public abstract class VoiceEventBase(Config config) : IVoiceEvent { protected readonly Config Config = config; private float _lastExecutionTime = -999f; private float Cooldown => config.GlobalCooldown.Value; protected string? ExecutionDetail { get; set; } protected string? ExecutionPayload { get; set; } protected abstract IEnumerable GetKeywords(); protected abstract bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword); protected static HashSet ParseKeywords(string configLine) { return (from k in configLine.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select k.Trim().ToLowerInvariant() into k where !string.IsNullOrWhiteSpace(k) select k).ToHashSet(); } public bool TryExecute(string spokenWord, string fullSentence) { //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) if (Time.time < _lastExecutionTime + Cooldown) { if (config.EnableDebugLogs.Value) { Debug.Log((object)("[VoiceCurseReborn] " + GetType().Name + ": On cooldown")); } Plugin.Log.LogInfo((object)("[VoiceCurseReborn] " + GetType().Name + ": On cooldown")); return false; } string text = GetKeywords().FirstOrDefault((string k) => spokenWord.Contains(k) || (fullSentence.Contains(k) && k.EndsWith(" " + spokenWord, StringComparison.OrdinalIgnoreCase))); if (text == null) { return false; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !((Component)localCharacter).gameObject.activeInHierarchy) { Plugin.Log.LogInfo((object)("[VoiceEventBase] " + GetType().Name + ": No local character!")); return false; } Plugin.Log.LogInfo((object)("[VoiceEventBase] " + GetType().Name + ": Executing OnExecute...")); ExecutionDetail = null; ExecutionPayload = null; bool flag = false; try { flag = OnExecute(localCharacter, spokenWord, fullSentence, text); Plugin.Log.LogInfo((object)$"[VoiceEventBase] {GetType().Name}: OnExecute returned {flag}"); } catch (Exception ex) { Plugin.Log.LogError((object)("[VoiceEventBase] " + GetType().Name + ": EXCEPTION: " + ex.Message + "\n" + ex.StackTrace)); if (config.EnableDebugLogs.Value) { Debug.LogWarning((object)("[VoiceEventBase] Failed to execute " + GetType().Name + ": " + ex.Message)); } } if (!flag) { return false; } _lastExecutionTime = Time.time; if (config.EnableDebugLogs.Value) { Debug.Log((object)("[VoiceCurseReborn] " + GetType().Name + " executed locally. Broadcasting event...")); } string eventName = GetType().Name.Replace("Event", ""); string spokenWord2 = fullSentence; int num = fullSentence.LastIndexOf(text, StringComparison.OrdinalIgnoreCase); if (num != -1) { int num2 = num; int num3 = num + text.Length; while (num2 > 0 && fullSentence[num2 - 1] != ' ') { num2--; } for (; num3 < fullSentence.Length && fullSentence[num3] != ' '; num3++) { } spokenWord2 = fullSentence.Substring(num2, num3 - num2); } Plugin.Log.LogInfo((object)("[VoiceCurseReborn] " + GetType().Name + ": ExecutionPayload before send: '" + ExecutionPayload + "'")); NetworkHandler.SendCurseEvent(spokenWord2, text, eventName, ExecutionDetail, ExecutionPayload, localCharacter.Center); if (!PhotonNetwork.IsMasterClient && (Object)(object)localCharacter != (Object)null) { string detail = ((!string.IsNullOrEmpty(ExecutionPayload)) ? ExecutionPayload : (ExecutionDetail ?? "")); PlayEffects(localCharacter, localCharacter.Center, detail); } return true; } public virtual void PlayEffects(Character origin, Vector3 position, string detail) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) PlayEffects(origin, position); } public virtual void PlayEffects(Character origin, Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) PlayEffects(position); } public virtual void PlayEffects(Vector3 position) { } } public class ZombifyEvent : VoiceEventBase { [Serializable] private class ZombifyPayload { public int playerViewID; public Vector3 deathPosition; public Quaternion rotation; } private readonly HashSet _zombifyKeywords; public ZombifyEvent(Config config) : base(config) { _zombifyKeywords = VoiceEventBase.ParseKeywords(config.ZombifyKeywords.Value); } protected override IEnumerable GetKeywords() { if (!config.ZombifyEnabled.Value) { return Enumerable.Empty(); } return _zombifyKeywords; } protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword) { //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_0073: 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) if (!config.ZombifyEnabled.Value) { return false; } if (player.data.dead || player.data.zombified) { return false; } Plugin.Log.LogInfo((object)("[VoiceCurseReborn] ZombifyEvent: Triggered by " + player.characterName)); ZombifyPayload zombifyPayload = new ZombifyPayload { playerViewID = ((MonoBehaviourPun)player).photonView.ViewID, deathPosition = player.Center, rotation = ((Component)player).transform.rotation }; base.ExecutionPayload = JsonUtility.ToJson((object)zombifyPayload); return true; } public override void PlayEffects(Character origin, Vector3 position, string detail) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { Plugin.Log.LogInfo((object)"[VoiceCurseReborn] ZombifyEvent: Not master client, skipping PlayEffects"); return; } ZombifyPayload zombifyPayload = null; if (!string.IsNullOrEmpty(detail)) { try { zombifyPayload = JsonUtility.FromJson(detail); Plugin.Log.LogInfo((object)$"[VoiceCurseReborn] ZombifyEvent: Payload deserialized - playerViewID: {zombifyPayload?.playerViewID}"); } catch (Exception ex) { Plugin.Log.LogError((object)("[VoiceCurseReborn] ZombifyEvent: Failed to deserialize payload: " + ex.Message)); } } Character player = default(Character); if (zombifyPayload == null || zombifyPayload.playerViewID == 0) { if ((Object)(object)origin == (Object)null) { Plugin.Log.LogWarning((object)"[VoiceCurseReborn] ZombifyEvent: No payload and no origin!"); return; } Plugin.Log.LogInfo((object)"[VoiceCurseReborn] ZombifyEvent: Using origin character"); ProcessZombification(origin, origin.Center, ((Component)origin).transform.rotation); } else if (!Character.GetCharacterWithPhotonID(zombifyPayload.playerViewID, ref player)) { Plugin.Log.LogWarning((object)$"[VoiceCurseReborn] ZombifyEvent: Could not find player with view ID {zombifyPayload.playerViewID}"); } else { ProcessZombification(player, zombifyPayload.deathPosition, zombifyPayload.rotation); } } private void ProcessZombification(Character player, Vector3 deathPosition, Quaternion rotation) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { Plugin.Log.LogWarning((object)"[VoiceCurseReborn] ZombifyEvent: ProcessZombification called on non-master client!"); return; } if ((Object)(object)player == (Object)null || player.data.dead || player.data.zombified) { Plugin.Log.LogWarning((object)"[VoiceCurseReborn] ZombifyEvent: Player is null, dead, or already zombified!"); return; } Plugin.Log.LogInfo((object)("[VoiceCurseReborn] ZombifyEvent: Processing zombification for " + player.characterName)); Plugin.Log.LogInfo((object)"[VoiceCurseReborn] ZombifyEvent: Spawning zombie..."); try { GameObject val = PhotonNetwork.Instantiate("MushroomZombie_Player", deathPosition, rotation, (byte)0, (object[])null); if ((Object)(object)val != (Object)null) { val.GetComponent().RPC("RPC_Arise", (RpcTarget)0, new object[1] { ((MonoBehaviourPun)player).photonView.ViewID }); Plugin.Log.LogInfo((object)"[VoiceCurseReborn] ZombifyEvent: Zombie spawned successfully!"); } else { Plugin.Log.LogError((object)"[VoiceCurseReborn] ZombifyEvent: Failed to spawn zombie!"); } } catch (Exception ex) { Plugin.Log.LogError((object)("[VoiceCurseReborn] ZombifyEvent: Exception spawning zombie: " + ex.Message)); } ((MonoBehaviourPun)player).photonView.RPC("RPC_FinishZombifying", (RpcTarget)0, Array.Empty()); } [PunRPC] private void RPC_FinishZombifying() { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { Plugin.Log.LogWarning((object)"[VoiceCurseReborn] ZombifyEvent: RPC_FinishZombifying called but no local character!"); return; } if (!((MonoBehaviourPun)localCharacter).photonView.IsMine) { Plugin.Log.LogInfo((object)"[VoiceCurseReborn] ZombifyEvent: RPC_FinishZombifying received but not for local player"); return; } Plugin.Log.LogInfo((object)"[VoiceCurseReborn] ZombifyEvent: RPC_FinishZombifying - finishing zombification..."); try { localCharacter.FinishZombifying(); Plugin.Log.LogInfo((object)"[VoiceCurseReborn] ZombifyEvent: FinishZombifying completed!"); } catch (Exception ex) { Plugin.Log.LogError((object)("[VoiceCurseReborn] ZombifyEvent: Exception in FinishZombifying: " + ex.Message)); } } } }