Decompiled source of WandFusion v0.4.0

WandFusion.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using YAPYAP;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("WandFusion")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WandFusion")]
[assembly: AssemblyTitle("WandFusion")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 WandFusion
{
	internal static class FusionVfx
	{
		private static Material _cachedMaterial;

		public static void Play(NetworkPuppetWandProp host, NetworkPuppetWandProp absorbed, Vector3 absorbedStartPos)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_005f: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c2: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00d0: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)host.VFXTip != (Object)null) ? host.VFXTip : host.WandTip);
			Vector3 position = val.position;
			List<Color> list = CollectColors(host, absorbed);
			Color val2 = (Color)((list.Count > 0) ? list[0] : new Color(0.6f, 0.3f, 1f));
			Color val3 = (Color)((list.Count > 1) ? list[list.Count - 1] : new Color(0.3f, 0.9f, 1f));
			SpawnGameVfx(host, absorbed, position, val.rotation);
			Material particleMaterial = GetParticleMaterial(host, absorbed);
			if ((Object)(object)particleMaterial != (Object)null)
			{
				SparkStream(absorbedStartPos, position, val2, val3, particleMaterial);
				SparkBurst(position, val2, val3, particleMaterial);
				Fog(position, val2, val3, particleMaterial);
			}
			else
			{
				WandFusionPlugin.Log.LogWarning((object)"Не нашёл материал для частиц - будет только свет.");
			}
			LightFlash(position, Color.Lerp(val2, val3, 0.5f));
		}

		private static List<Color> CollectColors(params NetworkPuppetWandProp[] wands)
		{
			//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_0080: Unknown result type (might be due to invalid IL or missing references)
			List<Color> list = new List<Color>();
			foreach (NetworkPuppetWandProp val in wands)
			{
				Spell spell = val.Spell;
				VoiceSpell val2 = (VoiceSpell)(object)((spell is VoiceSpell) ? spell : null);
				if (val2 == null)
				{
					continue;
				}
				Spell[] array = (Spell[])(((object)VoiceSpellAccess.Spells.Invoke(val2)) ?? ((object)new Spell[0]));
				foreach (Spell val3 in array)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						Color chargeableColor = val3.ChargeableColor;
						chargeableColor.a = 1f;
						list.Add(chargeableColor);
					}
				}
			}
			return list;
		}

		private static void SpawnGameVfx(NetworkPuppetWandProp host, NetworkPuppetWandProp absorbed, Vector3 pos, Quaternion rot)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)VfxManager.Instance == (Object)null)
			{
				return;
			}
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			NetworkPuppetWandProp[] array = (NetworkPuppetWandProp[])(object)new NetworkPuppetWandProp[2] { absorbed, host };
			foreach (NetworkPuppetWandProp val in array)
			{
				Spell spell = val.Spell;
				VoiceSpell val2 = (VoiceSpell)(object)((spell is VoiceSpell) ? spell : null);
				if (val2 == null)
				{
					continue;
				}
				Spell[] array2 = (Spell[])(((object)VoiceSpellAccess.Spells.Invoke(val2)) ?? ((object)new Spell[0]));
				foreach (Spell val3 in array2)
				{
					if ((Object)(object)val3 == (Object)null || (Object)(object)val3.SpellData == (Object)null)
					{
						continue;
					}
					GameObject[] array3 = (GameObject[])(object)new GameObject[2]
					{
						val3.SpellData.impactVFXPrefab,
						val3.SpellData.spawnVFXPrefab
					};
					foreach (GameObject val4 in array3)
					{
						if (!((Object)(object)val4 == (Object)null) && hashSet.Count < 4 && hashSet.Add(val4))
						{
							VfxManager.Instance.SpawnVfx(val4, pos, rot, (Transform)null, 2f);
						}
					}
				}
			}
		}

		private static Material GetParticleMaterial(params NetworkPuppetWandProp[] wands)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			foreach (NetworkPuppetWandProp val in wands)
			{
				ParticleSystemRenderer componentInChildren = ((Component)val).GetComponentInChildren<ParticleSystemRenderer>(true);
				if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Renderer)componentInChildren).sharedMaterial != (Object)null)
				{
					return ((Renderer)componentInChildren).sharedMaterial;
				}
			}
			if ((Object)(object)_cachedMaterial != (Object)null)
			{
				return _cachedMaterial;
			}
			ParticleSystemRenderer[] array = Object.FindObjectsOfType<ParticleSystemRenderer>();
			foreach (ParticleSystemRenderer val2 in array)
			{
				if ((Object)(object)((Renderer)val2).sharedMaterial != (Object)null)
				{
					_cachedMaterial = ((Renderer)val2).sharedMaterial;
					return _cachedMaterial;
				}
			}
			string[] array2 = new string[2] { "Universal Render Pipeline/Particles/Unlit", "Sprites/Default" };
			foreach (string text in array2)
			{
				Shader val3 = Shader.Find(text);
				if ((Object)(object)val3 != (Object)null)
				{
					_cachedMaterial = new Material(val3);
					return _cachedMaterial;
				}
			}
			return null;
		}

		private static ParticleSystem NewSystem(string name, Vector3 pos, Material mat, out ParticleSystemRenderer renderer)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0062: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.position = pos;
			ParticleSystem val2 = val.AddComponent<ParticleSystem>();
			val2.Stop(true, (ParticleSystemStopBehavior)0);
			MainModule main = val2.main;
			((MainModule)(ref main)).loop = false;
			((MainModule)(ref main)).playOnAwake = false;
			((MainModule)(ref main)).duration = 1f;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			EmissionModule emission = val2.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f);
			renderer = val.GetComponent<ParticleSystemRenderer>();
			((Renderer)renderer).sharedMaterial = mat;
			Object.Destroy((Object)(object)val, 4f);
			return val2;
		}

		private static Gradient Fade(Color a, Color b, float startAlpha)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0045: 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_0057: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			Gradient val = new Gradient();
			val.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(a, 0f),
				new GradientColorKey(b, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[3]
			{
				new GradientAlphaKey(startAlpha, 0f),
				new GradientAlphaKey(startAlpha, 0.4f),
				new GradientAlphaKey(0f, 1f)
			});
			return val;
		}

		private static void SparkStream(Vector3 from, Vector3 to, Color a, Color b, Material mat)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0093: 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_0095: 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_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_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_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_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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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_0143: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = to - from;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (!(magnitude < 0.05f))
			{
				ParticleSystemRenderer renderer;
				ParticleSystem val2 = NewSystem("WandFusion_Stream", from, mat, out renderer);
				((Component)val2).transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized);
				MainModule main = val2.main;
				((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.35f);
				((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(magnitude / 0.35f);
				((MainModule)(ref main)).startSize = new MinMaxCurve(0.015f, 0.035f);
				((MainModule)(ref main)).startColor = new MinMaxGradient(a, b);
				((MainModule)(ref main)).maxParticles = 100;
				EmissionModule emission = val2.emission;
				((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[3]
				{
					new Burst(0f, (short)15),
					new Burst(0.08f, (short)15),
					new Burst(0.16f, (short)15)
				});
				ShapeModule shape = val2.shape;
				((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)4;
				((ShapeModule)(ref shape)).angle = 4f;
				((ShapeModule)(ref shape)).radius = 0.04f;
				ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
				((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
				((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(Fade(a, b, 1f));
				renderer.renderMode = (ParticleSystemRenderMode)1;
				renderer.velocityScale = 0.04f;
				renderer.lengthScale = 1f;
				val2.Play();
			}
		}

		private static void SparkBurst(Vector3 pos, Color a, Color b, Material mat)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0070: 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_0084: 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_00b4: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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)
			//IL_00e8: 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_0105: 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)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystemRenderer renderer;
			ParticleSystem val = NewSystem("WandFusion_Burst", pos, mat, out renderer);
			MainModule main = val.main;
			((MainModule)(ref main)).startDelay = MinMaxCurve.op_Implicit(0.3f);
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.4f, 1f);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(1.5f, 4.5f);
			((MainModule)(ref main)).startSize = new MinMaxCurve(0.02f, 0.05f);
			((MainModule)(ref main)).startColor = new MinMaxGradient(a, b);
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0.4f);
			((MainModule)(ref main)).maxParticles = 200;
			EmissionModule emission = val.emission;
			((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1]
			{
				new Burst(0f, (short)90)
			});
			ShapeModule shape = val.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
			((ShapeModule)(ref shape)).radius = 0.05f;
			ColorOverLifetimeModule colorOverLifetime = val.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(Fade(Color.white, b, 1f));
			LimitVelocityOverLifetimeModule limitVelocityOverLifetime = val.limitVelocityOverLifetime;
			((LimitVelocityOverLifetimeModule)(ref limitVelocityOverLifetime)).enabled = true;
			((LimitVelocityOverLifetimeModule)(ref limitVelocityOverLifetime)).dampen = 0.15f;
			((LimitVelocityOverLifetimeModule)(ref limitVelocityOverLifetime)).limit = MinMaxCurve.op_Implicit(6f);
			renderer.renderMode = (ParticleSystemRenderMode)1;
			renderer.velocityScale = 0.05f;
			renderer.lengthScale = 1f;
			val.Play();
		}

		private static void Fog(Vector3 pos, Color a, Color b, Material mat)
		{
			//IL_0006: 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_0011: 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_0021: 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_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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_007e: 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_00ac: 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_00ba: 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_00cd: 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)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystemRenderer renderer;
			ParticleSystem val = NewSystem("WandFusion_Fog", pos, mat, out renderer);
			Color val2 = Color.Lerp(a, Color.white, 0.3f);
			Color val3 = Color.Lerp(b, new Color(0.4f, 0.4f, 0.5f), 0.4f);
			MainModule main = val.main;
			((MainModule)(ref main)).startDelay = MinMaxCurve.op_Implicit(0.25f);
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(1.6f, 2.6f);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(0.1f, 0.45f);
			((MainModule)(ref main)).startSize = new MinMaxCurve(0.25f, 0.5f);
			((MainModule)(ref main)).startRotation = new MinMaxCurve(0f, (float)Math.PI * 2f);
			((MainModule)(ref main)).startColor = new MinMaxGradient(val2, val3);
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(-0.03f);
			((MainModule)(ref main)).maxParticles = 40;
			EmissionModule emission = val.emission;
			((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1]
			{
				new Burst(0f, (short)18)
			});
			ShapeModule shape = val.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
			((ShapeModule)(ref shape)).radius = 0.15f;
			ColorOverLifetimeModule colorOverLifetime = val.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(Fade(val2, val3, 0.35f));
			SizeOverLifetimeModule sizeOverLifetime = val.sizeOverLifetime;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, AnimationCurve.Linear(0f, 0.6f, 1f, 2.2f));
			RotationOverLifetimeModule rotationOverLifetime = val.rotationOverLifetime;
			((RotationOverLifetimeModule)(ref rotationOverLifetime)).enabled = true;
			((RotationOverLifetimeModule)(ref rotationOverLifetime)).z = new MinMaxCurve(-0.6f, 0.6f);
			renderer.renderMode = (ParticleSystemRenderMode)0;
			val.Play();
		}

		private static void LightFlash(Vector3 pos, Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0012: 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)
			GameObject val = new GameObject("WandFusion_Light");
			val.transform.position = pos;
			Light val2 = val.AddComponent<Light>();
			val2.type = (LightType)2;
			val2.color = color;
			val2.range = 5f;
			val2.intensity = 0f;
			val.AddComponent<FlashFader>().Init(val2, 0.3f, 8f, 0.9f);
		}
	}
	internal class FlashFader : MonoBehaviour
	{
		private Light _light;

		private float _delay;

		private float _peak;

		private float _duration;

		private float _t;

		public void Init(Light light, float delay, float peak, float duration)
		{
			_light = light;
			_delay = delay;
			_peak = peak;
			_duration = duration;
		}

		private void Update()
		{
			_t += Time.deltaTime;
			float num = (_t - _delay) / _duration;
			if (num >= 1f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
			else if (num < 0f)
			{
				_light.intensity = 0f;
			}
			else
			{
				_light.intensity = _peak * ((num < 0.12f) ? (num / 0.12f) : (1f - (num - 0.12f) / 0.88f));
			}
		}
	}
	[BepInPlugin("yapyap.wandfusion", "Wand Fusion", "0.4.0")]
	public class WandFusionPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<string> PhraseRussian;

		internal static ConfigEntry<string> PhraseEnglish;

		internal static string CurrentLanguage = "en";

		private bool _serverHandlersSet;

		private bool _clientHandlersSet;

		private bool _clientSynced;

		private float _ensureTimer;

		internal static string CurrentPhrase => (CurrentLanguage == "ru") ? PhraseRussian.Value : PhraseEnglish.Value;

		private void Awake()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			PhraseRussian = ((BaseUnityPlugin)this).Config.Bind<string>("Voice", "PhraseRussian", "соедини-тус", "Фраза слияния, когда в игре выбран русский язык распознавания. Каждый кусочек между дефисами должен быть словом из словаря Vosk.");
			PhraseEnglish = ((BaseUnityPlugin)this).Config.Bind<string>("Voice", "PhraseEnglish", "fuse-ana", "Fusion phrase when the game's voice language is English (also used for other languages). Each dash-separated part must be a word known to Vosk.");
			FusionNet.RegisterSerializers();
			new Harmony("yapyap.wandfusion").PatchAll();
			Log.LogInfo((object)("Wand Fusion загружен. RU: \"" + PhraseRussian.Value + "\", EN: \"" + PhraseEnglish.Value + "\""));
		}

		private void Update()
		{
			if (NetworkServer.active && !_serverHandlersSet)
			{
				NetworkServer.ReplaceHandler<FuseRequestMsg>((Action<NetworkConnectionToClient, FuseRequestMsg>)FusionNet.OnServerFuseRequest, true);
				NetworkServer.ReplaceHandler<FuseSyncRequestMsg>((Action<NetworkConnectionToClient, FuseSyncRequestMsg>)FusionNet.OnServerSyncRequest, true);
				_serverHandlersSet = true;
			}
			else if (!NetworkServer.active && _serverHandlersSet)
			{
				_serverHandlersSet = false;
				FusionRegistry.Clear();
			}
			if (NetworkClient.active && !_clientHandlersSet)
			{
				NetworkClient.ReplaceHandler<FuseStateMsg>((Action<FuseStateMsg>)FusionNet.OnClientFuseState, true);
				_clientHandlersSet = true;
			}
			else if (!NetworkClient.active && _clientHandlersSet)
			{
				_clientHandlersSet = false;
				_clientSynced = false;
				FusionRegistry.Clear();
			}
			if (NetworkClient.active && NetworkClient.ready && !NetworkServer.active && !_clientSynced)
			{
				NetworkClient.Send<FuseSyncRequestMsg>(default(FuseSyncRequestMsg), 0);
				_clientSynced = true;
			}
			_ensureTimer -= Time.deltaTime;
			if (_ensureTimer <= 0f)
			{
				_ensureTimer = 0.5f;
				FusionNet.EnsureHiders();
			}
		}
	}
	internal static class FusionRegistry
	{
		private static readonly Dictionary<uint, List<uint>> Absorbed = new Dictionary<uint, List<uint>>();

		public static void Add(uint host, uint absorbed)
		{
			if (Absorbed.TryGetValue(absorbed, out var value))
			{
				Absorbed.Remove(absorbed);
				foreach (uint item in value)
				{
					Add(host, item);
				}
			}
			if (!Absorbed.TryGetValue(host, out var value2))
			{
				value2 = new List<uint>();
				Absorbed[host] = value2;
			}
			if (!value2.Contains(absorbed))
			{
				value2.Add(absorbed);
			}
		}

		public static IReadOnlyList<uint> Get(uint host)
		{
			List<uint> value;
			return Absorbed.TryGetValue(host, out value) ? value : null;
		}

		public static bool TryGetHost(uint absorbed, out uint host)
		{
			foreach (KeyValuePair<uint, List<uint>> item in Absorbed)
			{
				if (item.Value.Contains(absorbed))
				{
					host = item.Key;
					return true;
				}
			}
			host = 0u;
			return false;
		}

		public static IEnumerable<KeyValuePair<uint, uint>> AllPairs()
		{
			foreach (KeyValuePair<uint, List<uint>> kv in Absorbed)
			{
				using List<uint>.Enumerator enumerator2 = kv.Value.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					yield return new KeyValuePair<uint, uint>(value: enumerator2.Current, key: kv.Key);
				}
			}
		}

		public static void Clear()
		{
			Absorbed.Clear();
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct FuseRequestMsg : NetworkMessage
	{
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct FuseSyncRequestMsg : NetworkMessage
	{
	}
	public struct FuseStateMsg : NetworkMessage
	{
		public uint hostWand;

		public uint absorbedWand;

		public bool playEffect;
	}
	internal static class FusionNet
	{
		public static void RegisterSerializers()
		{
			Writer<FuseRequestMsg>.write = delegate
			{
			};
			Reader<FuseRequestMsg>.read = (NetworkReader r) => default(FuseRequestMsg);
			Writer<FuseSyncRequestMsg>.write = delegate
			{
			};
			Reader<FuseSyncRequestMsg>.read = (NetworkReader r) => default(FuseSyncRequestMsg);
			Writer<FuseStateMsg>.write = delegate(NetworkWriter w, FuseStateMsg m)
			{
				NetworkWriterExtensions.WriteUInt(w, m.hostWand);
				NetworkWriterExtensions.WriteUInt(w, m.absorbedWand);
				NetworkWriterExtensions.WriteBool(w, m.playEffect);
			};
			Reader<FuseStateMsg>.read = (NetworkReader r) => new FuseStateMsg
			{
				hostWand = NetworkReaderExtensions.ReadUInt(r),
				absorbedWand = NetworkReaderExtensions.ReadUInt(r),
				playEffect = NetworkReaderExtensions.ReadBool(r)
			};
		}

		public static void RequestFuse()
		{
			if (NetworkClient.active)
			{
				NetworkClient.Send<FuseRequestMsg>(default(FuseRequestMsg), 0);
			}
		}

		public static void OnServerFuseRequest(NetworkConnectionToClient conn, FuseRequestMsg msg)
		{
			//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 ((Object)(object)((conn != null) ? ((NetworkConnection)conn).identity : null) == (Object)null)
			{
				return;
			}
			Pawn component = ((Component)((NetworkConnection)conn).identity).GetComponent<Pawn>();
			PawnPropInteractions val = (((Object)(object)component != (Object)null) ? component.PropInteractions : null);
			if (!((Object)(object)val == (Object)null))
			{
				NetworkPuppetProp networkCurrentRightHandNetworkProp = val.NetworkCurrentRightHandNetworkProp;
				NetworkPuppetWandProp val2 = (NetworkPuppetWandProp)(object)((networkCurrentRightHandNetworkProp is NetworkPuppetWandProp) ? networkCurrentRightHandNetworkProp : null);
				NetworkPuppetProp networkCurrentLeftHandNetworkProp = val.NetworkCurrentLeftHandNetworkProp;
				NetworkPuppetWandProp val3 = (NetworkPuppetWandProp)(object)((networkCurrentLeftHandNetworkProp is NetworkPuppetWandProp) ? networkCurrentLeftHandNetworkProp : null);
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null) && !((Object)(object)val2 == (Object)(object)val3) && val2.Spell is VoiceSpell && val3.Spell is VoiceSpell && !val2.IsSameTypeWand(((NetworkBehaviour)val3).netIdentity))
				{
					uint netId = ((NetworkBehaviour)val2).netIdentity.netId;
					uint netId2 = ((NetworkBehaviour)val3).netIdentity.netId;
					PlayFusionEffects(val2, val3);
					((NetworkPuppetProp)val3).ServerHandleDrop(true, default(Vector3));
					FusionRegistry.Add(netId, netId2);
					NetworkServer.SendToAll<FuseStateMsg>(new FuseStateMsg
					{
						hostWand = netId,
						absorbedWand = netId2,
						playEffect = true
					}, 0, false);
					EnsureHiders();
					RefreshWand(netId);
					WandFusionPlugin.Log.LogInfo((object)$"Слияние: палка {netId2} поглощена палкой {netId}");
				}
			}
		}

		public static void OnServerSyncRequest(NetworkConnectionToClient conn, FuseSyncRequestMsg msg)
		{
			foreach (KeyValuePair<uint, uint> item in FusionRegistry.AllPairs())
			{
				((NetworkConnection)conn).Send<FuseStateMsg>(new FuseStateMsg
				{
					hostWand = item.Key,
					absorbedWand = item.Value
				}, 0);
			}
		}

		public static void OnClientFuseState(FuseStateMsg msg)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (msg.playEffect)
			{
				NetworkPuppetWandProp val = FindWand(msg.hostWand);
				NetworkPuppetWandProp val2 = FindWand(msg.absorbedWand);
				if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
				{
					try
					{
						FusionVfx.Play(val, val2, ((Component)val2).transform.position);
					}
					catch (Exception ex)
					{
						WandFusionPlugin.Log.LogError((object)("Ошибка эффекта слияния: " + ex));
					}
				}
			}
			FusionRegistry.Add(msg.hostWand, msg.absorbedWand);
			EnsureHiders();
			RefreshWand(msg.hostWand);
		}

		private static void RefreshWand(uint wandNetId)
		{
			NetworkPuppetWandProp val = FindWand(wandNetId);
			if ((Object)(object)val != (Object)null && (Object)(object)val.Spell != (Object)null)
			{
				val.Spell.OnPickedUpWandsChanged();
			}
		}

		public static void EnsureHiders()
		{
			if (!NetworkServer.active && !NetworkClient.active)
			{
				return;
			}
			foreach (KeyValuePair<uint, uint> item in FusionRegistry.AllPairs().ToList())
			{
				NetworkPuppetWandProp val = FindWand(item.Value);
				if (!((Object)(object)val == (Object)null))
				{
					FusedWandHider fusedWandHider = ((Component)val).GetComponent<FusedWandHider>() ?? ((Component)val).gameObject.AddComponent<FusedWandHider>();
					fusedWandHider.HostNetId = item.Key;
				}
			}
		}

		private static void PlayFusionEffects(NetworkPuppetWandProp host, NetworkPuppetWandProp absorbed)
		{
			//IL_008c: 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)
			Transform val = (((Object)(object)host.VFXTip != (Object)null) ? host.VFXTip : host.WandTip);
			NetworkPuppetWandProp[] array = (NetworkPuppetWandProp[])(object)new NetworkPuppetWandProp[2] { absorbed, host };
			foreach (NetworkPuppetWandProp val2 in array)
			{
				Spell spell = val2.Spell;
				VoiceSpell val3 = (VoiceSpell)(object)((spell is VoiceSpell) ? spell : null);
				if (val3 == null)
				{
					continue;
				}
				Spell[] array2 = VoiceSpellAccess.Spells.Invoke(val3) ?? Array.Empty<Spell>();
				foreach (Spell val4 in array2)
				{
					if ((Object)(object)val4 != (Object)null)
					{
						val4.RpcPlayEffect((SpellEffectType)0, val.position, val.rotation);
					}
				}
			}
		}

		internal static NetworkPuppetWandProp FindWand(uint netId)
		{
			Dictionary<uint, NetworkIdentity> dictionary = (NetworkServer.active ? NetworkServer.spawned : NetworkClient.spawned);
			if (!dictionary.TryGetValue(netId, out var value) || (Object)(object)value == (Object)null)
			{
				return null;
			}
			return ((Component)value).GetComponent<NetworkPuppetWandProp>();
		}
	}
	internal class FusedWandHider : MonoBehaviour
	{
		public uint HostNetId;

		private MeshRenderer[] _meshes;

		private SkinnedMeshRenderer[] _skinned;

		private Collider[] _colliders;

		private Rigidbody[] _bodies;

		private void Awake()
		{
			_meshes = ((Component)this).GetComponentsInChildren<MeshRenderer>(true);
			_skinned = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			_colliders = ((Component)this).GetComponentsInChildren<Collider>(true);
			_bodies = ((Component)this).GetComponentsInChildren<Rigidbody>(true);
		}

		private void LateUpdate()
		{
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			MeshRenderer[] meshes = _meshes;
			foreach (MeshRenderer val in meshes)
			{
				if ((Object)(object)val != (Object)null)
				{
					((Renderer)val).enabled = false;
				}
			}
			SkinnedMeshRenderer[] skinned = _skinned;
			foreach (SkinnedMeshRenderer val2 in skinned)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					((Renderer)val2).enabled = false;
				}
			}
			Collider[] colliders = _colliders;
			foreach (Collider val3 in colliders)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					val3.enabled = false;
				}
			}
			Rigidbody[] bodies = _bodies;
			foreach (Rigidbody val4 in bodies)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					val4.isKinematic = true;
					val4.detectCollisions = false;
				}
			}
			NetworkPuppetWandProp val5 = FusionNet.FindWand(HostNetId);
			if ((Object)(object)val5 == (Object)null)
			{
				if (NetworkServer.active)
				{
					NetworkServer.Destroy(((Component)this).gameObject);
				}
			}
			else
			{
				Transform val6 = (((Object)(object)val5.VFXTip != (Object)null) ? val5.VFXTip : val5.WandTip);
				((Component)this).transform.SetPositionAndRotation(val6.position, val6.rotation);
			}
		}
	}
	internal static class VoiceSpellAccess
	{
		public static readonly FieldRef<VoiceSpell, Spell[]> Spells = AccessTools.FieldRefAccess<VoiceSpell, Spell[]>("spells");

		public static readonly FieldRef<VoiceSpell, List<Spell>> AllSpells = AccessTools.FieldRefAccess<VoiceSpell, List<Spell>>("allSpells");

		public static readonly Action<VoiceSpell> SortSpells = AccessTools.MethodDelegate<Action<VoiceSpell>>(AccessTools.Method(typeof(VoiceSpell), "SortSpells", (Type[])null, (Type[])null), (object)null, true);
	}
	[HarmonyPatch(typeof(VoiceSpell), "CollectHeldSpells")]
	internal static class CollectHeldSpellsPatch
	{
		private static void Postfix(VoiceSpell __instance)
		{
			IReadOnlyList<uint> readOnlyList = FusionRegistry.Get(((NetworkBehaviour)__instance).netIdentity.netId);
			if (readOnlyList == null)
			{
				return;
			}
			List<Spell> list = VoiceSpellAccess.AllSpells.Invoke(__instance);
			if (list == null || list.Count == 0)
			{
				return;
			}
			NetworkIdentity casterIdentity = ((Spell)__instance).CasterIdentity;
			bool flag = false;
			foreach (uint item in readOnlyList)
			{
				NetworkPuppetWandProp val = FusionNet.FindWand(item);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Spell spell = val.Spell;
				VoiceSpell val2 = (VoiceSpell)(object)((spell is VoiceSpell) ? spell : null);
				if (val2 == null)
				{
					continue;
				}
				Spell[] array = VoiceSpellAccess.Spells.Invoke(val2) ?? Array.Empty<Spell>();
				foreach (Spell val3 in array)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						if (NetworkServer.active && (Object)(object)casterIdentity != (Object)null && (Object)(object)val3.CasterIdentity != (Object)(object)casterIdentity)
						{
							val3.Initialize(casterIdentity);
						}
						if (!list.Contains(val3))
						{
							list.Add(val3);
							flag = true;
						}
					}
				}
			}
			if (flag)
			{
				VoiceSpellAccess.SortSpells(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(VoskSpeechToText), "UpdateGrammar", new Type[] { typeof(List<string>) })]
	internal static class UpdateGrammarPatch
	{
		private static void Prefix(ref List<string> keyPhrases)
		{
			keyPhrases = PhraseUtil.WithPhraseWords(keyPhrases);
		}
	}
	[HarmonyPatch(typeof(VoskSpeechToText), "StartVosk")]
	internal static class StartVoskPatch
	{
		private static void Prefix(VoskSpeechToText __instance, ref List<string> grammer, string modelPath)
		{
			string text = (modelPath ?? __instance.ModelPath ?? "").ToLowerInvariant();
			WandFusionPlugin.CurrentLanguage = (text.Contains("-ru-") ? "ru" : "en");
			WandFusionPlugin.Log.LogInfo((object)("Язык распознавания: " + WandFusionPlugin.CurrentLanguage + ", фраза: \"" + WandFusionPlugin.CurrentPhrase + "\""));
			grammer = PhraseUtil.WithPhraseWords(grammer);
		}
	}
	internal static class PhraseUtil
	{
		public static string[] Words()
		{
			return (WandFusionPlugin.CurrentPhrase ?? "").ToLowerInvariant().Split(new char[2] { ' ', '-' }, StringSplitOptions.RemoveEmptyEntries);
		}

		public static List<string> WithPhraseWords(List<string> list)
		{
			if (list == null || list.Count == 0)
			{
				return list;
			}
			List<string> list2 = new List<string>(list);
			string[] array = Words();
			foreach (string item in array)
			{
				if (!list2.Contains(item))
				{
					list2.Add(item);
				}
			}
			return list2;
		}

		public static bool Matches(string input)
		{
			if (string.IsNullOrEmpty(input))
			{
				return false;
			}
			string text = input.ToLowerInvariant();
			string[] array = Words();
			int num = -1;
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				int num2 = text.IndexOf(text2, num + 1, StringComparison.Ordinal);
				if (num2 == -1)
				{
					return false;
				}
				num = num2 + text2.Length - 1;
			}
			return array.Length != 0;
		}
	}
	[HarmonyPatch(typeof(PawnVoiceCommands), "Start")]
	internal static class ListenVoicePatch
	{
		private static readonly FieldRef<PawnVoiceCommands, Pawn> PawnRef = AccessTools.FieldRefAccess<PawnVoiceCommands, Pawn>("_pawn");

		private static void Postfix(PawnVoiceCommands __instance)
		{
			Pawn val = PawnRef.Invoke(__instance);
			if ((Object)(object)val == (Object)null || !((NetworkBehaviour)val).isLocalPlayer || (Object)(object)val.Voice == (Object)null)
			{
				return;
			}
			PawnVoice voice = val.Voice;
			voice.OnVoiceResult = (Action<string>)Delegate.Combine(voice.OnVoiceResult, (Action<string>)delegate(string input)
			{
				if (PhraseUtil.Matches(input))
				{
					FusionNet.RequestFuse();
				}
			});
		}
	}
}