Decompiled source of Deathsquito Lightning Tower v0.3.7

BepInEx/plugins/LightningTower/LightningTower.dll

Decompiled 20 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("LightningTower")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A storm-powered lightning tower for Valheim.")]
[assembly: AssemblyFileVersion("0.3.7.0")]
[assembly: AssemblyInformationalVersion("0.3.7")]
[assembly: AssemblyProduct("LightningTower")]
[assembly: AssemblyTitle("LightningTower")]
[assembly: AssemblyVersion("0.3.7.0")]
[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 LightningTower
{
	public sealed class ChargedHum : MonoBehaviour
	{
		private readonly AudioSource[] voices = (AudioSource[])(object)new AudioSource[2];

		private readonly double[] starts = new double[2] { -100.0, -100.0 };

		private float sectionDuration;

		private float gain;

		private static AudioClip? humLoop;

		private AudioSource drone;

		private double nextVoice;

		private int voiceIndex;

		private bool charged;

		private const float Crossfade = 0.35f;

		private const float Pitch = 0.75f;

		internal bool Active
		{
			get
			{
				if (Object.op_Implicit((Object)(object)drone))
				{
					if (!drone.isPlaying && !voices[0].isPlaying)
					{
						return voices[1].isPlaying;
					}
					return true;
				}
				return false;
			}
		}

		internal AudioSource[] Voices => voices;

		internal AudioSource Drone => drone;

		internal void Initialize(AudioClip clip, AudioMixerGroup mixer)
		{
			sectionDuration = clip.length / 0.75f;
			if (!Object.op_Implicit((Object)(object)humLoop))
			{
				float[] array = HumSignal.CreateLoop();
				humLoop = AudioClip.Create("LightningTower_ElectricalHum", array.Length, 1, 22050, false);
				if (!(bool)typeof(AudioClip).GetMethod("SetData", new Type[2]
				{
					typeof(float[]),
					typeof(int)
				}).Invoke(humLoop, new object[2] { array, 0 }))
				{
					throw new InvalidOperationException("Could not initialize the electrical hum audio.");
				}
			}
			drone = CreateSource("ElectricalHum", humLoop, mixer);
			drone.loop = true;
			for (int i = 0; i < voices.Length; i++)
			{
				voices[i] = CreateSource("ObliteratorCrackle_" + i, clip, mixer);
				AudioSource obj = voices[i];
				obj.pitch = 0.75f;
				((Component)obj).gameObject.AddComponent<AudioLowPassFilter>().cutoffFrequency = 2800f;
			}
		}

		private AudioSource CreateSource(string name, AudioClip clip, AudioMixerGroup mixer)
		{
			//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)
			GameObject val = new GameObject(name);
			val.transform.SetParent(((Component)this).transform, false);
			AudioSource obj = val.AddComponent<AudioSource>();
			obj.clip = clip;
			obj.outputAudioMixerGroup = mixer;
			obj.playOnAwake = false;
			obj.volume = 0f;
			obj.spatialBlend = 0f;
			obj.dopplerLevel = 0f;
			obj.reverbZoneMix = 0f;
			obj.bypassReverbZones = true;
			return obj;
		}

		internal void SetCharged(bool value)
		{
			charged = value;
		}

		internal static float DistanceGain(float distance, float range)
		{
			return HumSignal.DistanceGain(distance, range);
		}

		private void Update()
		{
			//IL_0028: 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)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)voices[0]))
			{
				return;
			}
			float num = DistanceGain(Object.op_Implicit((Object)(object)Player.m_localPlayer) ? Vector3.Distance(((Character)Player.m_localPlayer).GetCenterPoint(), ((Component)this).transform.position) : float.PositiveInfinity, Plugin.Settings.HumRange.Value);
			gain = Mathf.MoveTowards(gain, (float)(charged ? 1 : 0), Time.unscaledDeltaTime * 4f);
			if (num <= 0f || gain <= 0f)
			{
				StopVoices();
				return;
			}
			Camera mainCamera = Utils.GetMainCamera();
			float num2;
			if (!Object.op_Implicit((Object)(object)mainCamera) || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				num2 = 0f;
			}
			else
			{
				Vector3 right = ((Component)mainCamera).transform.right;
				Vector3 val = ((Component)this).transform.position - ((Character)Player.m_localPlayer).GetCenterPoint();
				num2 = Mathf.Clamp(Vector3.Dot(right, ((Vector3)(ref val)).normalized), -0.75f, 0.75f);
			}
			float panStereo = num2;
			float num3 = gain * num * Plugin.Settings.HumVolume.Value;
			drone.volume = num3;
			drone.panStereo = panStereo;
			if (!drone.isPlaying)
			{
				drone.Play();
			}
			double dspTime = AudioSettings.dspTime;
			if (dspTime >= nextVoice)
			{
				AudioSource obj = voices[voiceIndex];
				obj.Stop();
				obj.timeSamples = 0;
				starts[voiceIndex] = dspTime + 0.02;
				obj.PlayScheduled(starts[voiceIndex]);
				nextVoice = starts[voiceIndex] + (double)sectionDuration - 0.3499999940395355;
				voiceIndex = 1 - voiceIndex;
			}
			for (int i = 0; i < voices.Length; i++)
			{
				float num4 = (float)(dspTime - starts[i]);
				float num5 = Mathf.Clamp01(num4 / 0.35f) * Mathf.Clamp01((sectionDuration - num4) / 0.35f);
				voices[i].volume = Mathf.Sqrt(num5) * num3 * 0.35f;
				voices[i].panStereo = panStereo;
				if (num4 >= sectionDuration)
				{
					voices[i].Stop();
				}
			}
		}

		private void StopVoices()
		{
			if (Object.op_Implicit((Object)(object)drone))
			{
				drone.volume = 0f;
				drone.Stop();
			}
			AudioSource[] array = voices;
			foreach (AudioSource val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					val.volume = 0f;
					val.Stop();
				}
			}
			starts[0] = (starts[1] = -100.0);
			nextVoice = 0.0;
			voiceIndex = 0;
		}

		private void OnDisable()
		{
			StopVoices();
		}
	}
	internal static class ChargeRules
	{
		internal static int Clamp(int charge, int capacity)
		{
			return Math.Max(0, Math.Min(Math.Max(1, capacity), charge));
		}

		internal static int Add(int charge, int amount, int capacity)
		{
			return (int)Math.Min(Math.Max(1, capacity), (long)Clamp(charge, capacity) + (long)Math.Max(0, amount));
		}

		internal static bool InRange(float distanceSquared, float range)
		{
			if (distanceSquared >= 0f)
			{
				return distanceSquared <= range * range;
			}
			return false;
		}

		internal static long NextTick(long now, float seconds)
		{
			return now + (long)(seconds * 10000000f);
		}

		internal static bool IsDue(long now, long deadline)
		{
			if (deadline > 0)
			{
				return now >= deadline;
			}
			return false;
		}
	}
	internal static class ConfiguredTargets
	{
		private static string? previous;

		private static ZNetScene? scene;

		private static TargetList? targets;

		internal static bool Contains(int prefab)
		{
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return false;
			}
			string value = Plugin.Settings.TargetPrefabs.Value;
			if (targets == null || previous != value || (Object)(object)scene != (Object)(object)ZNetScene.instance)
			{
				previous = value;
				scene = ZNetScene.instance;
				targets = new TargetList(value, delegate(string name)
				{
					GameObject prefab2 = ZNetScene.instance.GetPrefab(name);
					return (!Object.op_Implicit((Object)(object)prefab2) || !Object.op_Implicit((Object)(object)prefab2.GetComponent<Character>()) || Object.op_Implicit((Object)(object)prefab2.GetComponent<Player>())) ? ((int?)null) : new int?(StringExtensionMethods.GetStableHashCode(name));
				}, delegate(string name)
				{
					Plugin.Log.LogWarning((object)("TargetPrefabs: ignoring '" + name + "'; use the exact prefab name of a non-player creature."));
				});
			}
			return targets.Contains(prefab);
		}
	}
	public sealed class CrownLightning : MonoBehaviour
	{
		private Transform[] tips = Array.Empty<Transform>();

		private Transform orb;

		private readonly LineRenderer[] lines = (LineRenderer[])(object)new LineRenderer[2];

		private readonly LineRenderer[] glows = (LineRenderer[])(object)new LineRenderer[2];

		private readonly int[] selected = new int[2] { -1, -1 };

		private readonly Vector3[] points = (Vector3[])(object)new Vector3[13];

		private Random random;

		private bool charged;

		private float nextPulse;

		private float endPulse;

		private float nextShape;

		private float started;

		private int pulsesUntilDouble;

		internal int PulseCount { get; private set; }

		internal int ActiveBoltCount { get; private set; }

		internal bool Flashing => ActiveBoltCount > 0;

		internal LineRenderer Line => lines[0];

		internal Transform? SelectedTip => TipAt(0);

		internal LineRenderer LineAt(int index)
		{
			return lines[index];
		}

		internal Transform? TipAt(int index)
		{
			if (selected[index] < 0)
			{
				return null;
			}
			return tips[selected[index]];
		}

		internal void Initialize(Transform orbTransform, Material material)
		{
			orb = orbTransform;
			tips = (from t in ((Component)((Component)this).transform).GetComponentsInChildren<Transform>(true)
				where ((Object)t).name.StartsWith("LightningTower_BranchTip_")
				select t).ToArray();
			random = new Random(((Object)this).GetInstanceID());
			pulsesUntilDouble = random.Next(2, 5);
			for (int num = 0; num < lines.Length; num++)
			{
				glows[num] = CreateLine("LightningTower_CrownGlow_" + num, material, 0.12f);
				lines[num] = CreateLine("LightningTower_CrownArc_" + num, material, 0.05f);
			}
		}

		private LineRenderer CreateLine(string name, Material material, float width)
		{
			//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_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_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_008e: 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_00a4: 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_00b8: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.SetParent(((Component)this).transform, false);
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			((Renderer)val2).sharedMaterial = material;
			val2.useWorldSpace = false;
			val2.positionCount = points.Length;
			val2.alignment = (LineAlignment)0;
			val2.textureMode = (LineTextureMode)0;
			val2.widthMultiplier = width;
			val2.widthCurve = new AnimationCurve((Keyframe[])(object)new Keyframe[4]
			{
				new Keyframe(0f, 0.5f),
				new Keyframe(0.15f, 1f),
				new Keyframe(0.8f, 1f),
				new Keyframe(1f, 0.4f)
			});
			val2.numCapVertices = 2;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			((Renderer)val2).enabled = false;
			return val2;
		}

		internal void SetCharged(bool value)
		{
			if (charged != value)
			{
				charged = value;
				if (value)
				{
					nextPulse = Time.time + 0.35f + (float)random.NextDouble() * 0.3f;
				}
				else
				{
					HidePulse();
				}
			}
		}

		private void Update()
		{
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			if (!charged || tips.Length == 0 || !Object.op_Implicit((Object)(object)lines[0]))
			{
				return;
			}
			float time = Time.time;
			if (Flashing && time >= endPulse)
			{
				HidePulse();
			}
			if (!Flashing && time >= nextPulse)
			{
				selected[0] = PickTip(selected[0]);
				bool flag = --pulsesUntilDouble == 0 && tips.Length > 1;
				ActiveBoltCount = ((!flag) ? 1 : 2);
				if (flag)
				{
					selected[1] = PickTip(selected[0]);
					pulsesUntilDouble = random.Next(2, 5);
				}
				started = time;
				endPulse = time + 0.32f + (float)random.NextDouble() * 0.13f;
				nextPulse = time + 2f + (float)random.NextDouble();
				nextShape = time;
				for (int i = 0; i < ActiveBoltCount; i++)
				{
					LineRenderer obj = lines[i];
					bool enabled = (((Renderer)glows[i]).enabled = true);
					((Renderer)obj).enabled = enabled;
				}
				PulseCount++;
			}
			if (!Flashing)
			{
				return;
			}
			if (time >= nextShape)
			{
				for (int j = 0; j < ActiveBoltCount; j++)
				{
					Reshape(j);
				}
				nextShape = time + 0.055f;
			}
			float num = Mathf.Clamp01((endPulse - time) / 0.08f) * ((Mathf.FloorToInt((time - started) / 0.055f) % 3 == 1) ? 0.75f : 1f);
			Color val = default(Color);
			for (int k = 0; k < ActiveBoltCount; k++)
			{
				LineRenderer obj2 = lines[k];
				LineRenderer obj3 = lines[k];
				((Color)(ref val))..ctor(1f, 1f, 1f, num);
				obj3.endColor = val;
				obj2.startColor = val;
				LineRenderer obj4 = glows[k];
				LineRenderer obj5 = glows[k];
				((Color)(ref val))..ctor(0.35f, 0.7f, 1f, num * 0.22f);
				obj5.endColor = val;
				obj4.startColor = val;
			}
		}

		private int PickTip(int excluded)
		{
			if (tips.Length < 2)
			{
				return 0;
			}
			int num = random.Next(tips.Length - ((excluded >= 0) ? 1 : 0));
			if (excluded < 0 || num < excluded)
			{
				return num;
			}
			return num + 1;
		}

		private void Reshape(int index)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003e: 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_0048: 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_0062: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0076: 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_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_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_008d: 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_00a8: 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_00be: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_013f: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.InverseTransformPoint(tips[selected[index]].position);
			Vector3 val2 = ((Component)this).transform.InverseTransformPoint(orb.position);
			Vector3 val3 = val2 - val;
			Vector3 normalized = ((Vector3)(ref val3)).normalized;
			val3 = Vector3.Cross(normalized, (Math.Abs(normalized.y) > 0.9f) ? Vector3.forward : Vector3.up);
			Vector3 normalized2 = ((Vector3)(ref val3)).normalized;
			val3 = Vector3.Cross(normalized2, normalized);
			Vector3 normalized3 = ((Vector3)(ref val3)).normalized;
			float num = Mathf.Min(0.18f, Vector3.Distance(val, val2) * 0.14f);
			points[0] = val;
			points[points.Length - 1] = val2;
			for (int i = 1; i < points.Length - 1; i++)
			{
				float num2 = (float)i / (float)(points.Length - 1);
				float num3 = (float)((i % 2 == 0) ? 1 : (-1)) * (0.4f + (float)random.NextDouble() * 0.6f);
				float num4 = ((float)random.NextDouble() - 0.5f) * 0.6f;
				points[i] = Vector3.Lerp(val, val2, num2) + (normalized2 * num3 + normalized3 * num4) * (num * Mathf.Sin(num2 * (float)Math.PI));
			}
			lines[index].SetPositions(points);
			glows[index].SetPositions(points);
		}

		private void HidePulse()
		{
			ActiveBoltCount = 0;
			for (int i = 0; i < lines.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)lines[i]))
				{
					((Renderer)lines[i]).enabled = false;
				}
				if (Object.op_Implicit((Object)(object)glows[i]))
				{
					((Renderer)glows[i]).enabled = false;
				}
			}
		}

		private void OnDisable()
		{
			HidePulse();
		}

		private void OnDestroy()
		{
			foreach (LineRenderer item in lines.Concat(glows))
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					Object.Destroy((Object)(object)((Component)item).gameObject);
				}
			}
		}
	}
	internal static class HumSignal
	{
		internal const int SampleRate = 22050;

		internal static float DistanceGain(float distance, float range)
		{
			if (range <= 0f || distance >= range || float.IsNaN(distance))
			{
				return 0f;
			}
			float num = Math.Min(1f, range * 0.4f);
			if (distance <= num)
			{
				return 1f;
			}
			float num2 = (distance - num) / (range - num);
			return 1f - num2 * num2 * (3f - 2f * num2);
		}

		internal static float[] CreateLoop()
		{
			float[] array = new float[44100];
			for (int i = 0; i < array.Length; i++)
			{
				double num = (double)i / 22050.0;
				double num2 = Math.PI * 2.0 * num;
				array[i] = (float)((0.45 * Math.Sin(100.0 * num2) + 0.2 * Math.Sin(150.0 * num2) + 0.12 * Math.Sin(200.0 * num2) + 0.08 * Math.Sin(300.0 * num2)) * (0.9 + 0.1 * Math.Sin(3.0 * num2)));
			}
			return array;
		}
	}
	public sealed class JaggedBolt : MonoBehaviour
	{
		private LineRenderer line;

		private Vector3 origin;

		private Vector3 target;

		private Vector3 side;

		private Vector3 up;

		private Vector3[] points = Array.Empty<Vector3>();

		private Random random;

		private float started;

		private float nextShape;

		private float amplitude;

		internal LineRenderer Line => line;

		internal void Initialize(Vector3 from, Vector3 to, Material material)
		{
			//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_0008: 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_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)
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0039: 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_003e: 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_0046: 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_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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_00d0: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Expected O, but got Unknown
			origin = from;
			target = to;
			Vector3 val = to - from;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			val = Vector3.Cross(normalized, (Math.Abs(normalized.y) > 0.9f) ? Vector3.forward : Vector3.up);
			side = ((Vector3)(ref val)).normalized;
			val = Vector3.Cross(side, normalized);
			up = ((Vector3)(ref val)).normalized;
			float num = Vector3.Distance(from, to);
			points = (Vector3[])(object)new Vector3[Mathf.Clamp(Mathf.CeilToInt(num / 0.6f), 8, 64) + 1];
			amplitude = Mathf.Min(Plugin.Settings.BoltJaggedness.Value, num * 0.12f);
			random = new Random(((Object)this).GetInstanceID());
			GameObject val2 = new GameObject("LightningTower_JaggedPath");
			line = val2.AddComponent<LineRenderer>();
			((Renderer)line).sharedMaterial = material;
			line.useWorldSpace = true;
			line.positionCount = points.Length;
			line.textureMode = (LineTextureMode)0;
			line.alignment = (LineAlignment)0;
			line.numCapVertices = 2;
			line.numCornerVertices = 0;
			((Renderer)line).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)line).receiveShadows = false;
			line.widthMultiplier = Plugin.Settings.BoltWidth.Value;
			line.widthCurve = new AnimationCurve((Keyframe[])(object)new Keyframe[4]
			{
				new Keyframe(0f, 0.55f),
				new Keyframe(0.18f, 1f),
				new Keyframe(0.8f, 0.8f),
				new Keyframe(1f, 0.3f)
			});
			started = Time.time;
			Reshape();
		}

		private void Update()
		{
			//IL_0092: 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)
			if (!Object.op_Implicit((Object)(object)line))
			{
				return;
			}
			float num = Time.time - started;
			if (num >= 0.4f)
			{
				((Renderer)line).enabled = false;
				return;
			}
			if (Time.time >= nextShape)
			{
				Reshape();
			}
			float num2 = (1f - num / 0.4f) * ((Mathf.FloorToInt(num / 0.045f) % 3 == 1) ? 0.65f : 1f);
			LineRenderer obj = line;
			LineRenderer obj2 = line;
			Color val = default(Color);
			((Color)(ref val))..ctor(1f, 1f, 1f, num2);
			obj2.endColor = val;
			obj.startColor = val;
		}

		private void Reshape()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00a8: 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_00b4: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			points[0] = origin;
			points[points.Length - 1] = target;
			for (int i = 1; i < points.Length - 1; i++)
			{
				float num = (float)i / (float)(points.Length - 1);
				float num2 = Mathf.Sin(num * (float)Math.PI);
				float num3 = (float)((i % 2 == 0) ? 1 : (-1)) * (0.35f + (float)random.NextDouble() * 0.65f);
				float num4 = ((float)random.NextDouble() - 0.5f) * 0.7f;
				points[i] = Vector3.Lerp(origin, target, num) + (side * num3 + up * num4) * (amplitude * num2);
			}
			line.SetPositions(points);
			nextShape = Time.time + 0.065f;
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)line))
			{
				Object.Destroy((Object)(object)((Component)line).gameObject);
			}
		}
	}
	internal static class LightningEffects
	{
		private static GameObject? storage;

		private static GameObject? bolt;

		private static GameObject? halo;

		private static GameObject? sound;

		private static Material jaggedMaterial;

		private static Material crownMaterial;

		private static AudioClip humClip;

		private static AudioMixerGroup humMixer;

		private static float soundLifetime;

		private static Bounds boltBounds;

		private static bool ready;

		internal static bool Ready => ready;

		internal static void Discover()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: 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)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: 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_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Expected O, but got Unknown
			//IL_061b: Unknown result type (might be due to invalid IL or missing references)
			//IL_062a: Unknown result type (might be due to invalid IL or missing references)
			if (Ready)
			{
				return;
			}
			storage = new GameObject("LightningTower_EffectTemplates");
			storage.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)storage);
			GameObject prefab = PrefabManager.Instance.GetPrefab("fx_chainlightning_spread");
			Transform obj = (Object.op_Implicit((Object)(object)prefab) ? prefab.transform.Find("Lightning") : null);
			if (!Object.op_Implicit((Object)(object)obj))
			{
				throw new InvalidOperationException("Missing fx_chainlightning_spread/Lightning.");
			}
			bolt = CopyVisual(((Component)obj).gameObject, "LightningTower_Bolt");
			for (int num = bolt.transform.childCount - 1; num >= 0; num--)
			{
				Object.DestroyImmediate((Object)(object)((Component)bolt.transform.GetChild(num)).gameObject);
			}
			ParticleSystem component = bolt.GetComponent<ParticleSystem>();
			ParticleSystemRenderer component2 = bolt.GetComponent<ParticleSystemRenderer>();
			if (!Object.op_Implicit((Object)(object)component2.mesh))
			{
				throw new InvalidOperationException("The chain-lightning effect has no bolt mesh.");
			}
			boltBounds = component2.mesh.bounds;
			if (((Bounds)(ref boltBounds)).size.x < 0.001f)
			{
				throw new InvalidOperationException("The lightning mesh has no length along its firing axis.");
			}
			component2.alignment = (ParticleSystemRenderSpace)2;
			MainModule main = component.main;
			((MainModule)(ref main)).loop = false;
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.4f);
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f);
			((MainModule)(ref main)).startSize3D = false;
			((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(1f);
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.5f, 0.65f, 0.8f, 0.25f));
			((MainModule)(ref main)).startRotation3D = true;
			MinMaxCurve val = (((MainModule)(ref main)).startRotationZ = MinMaxCurve.op_Implicit(0f));
			MinMaxCurve startRotationX = (((MainModule)(ref main)).startRotationY = val);
			((MainModule)(ref main)).startRotationX = startRotationX;
			((MainModule)(ref main)).maxParticles = 1;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
			((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
			EmissionModule emission = component.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f);
			((EmissionModule)(ref emission)).rateOverDistance = MinMaxCurve.op_Implicit(0f);
			((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1]
			{
				new Burst(0f, (short)1)
			});
			ShapeModule shape = component.shape;
			((ShapeModule)(ref shape)).enabled = false;
			VelocityOverLifetimeModule velocityOverLifetime = component.velocityOverLifetime;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = false;
			NoiseModule noise = component.noise;
			((NoiseModule)(ref noise)).enabled = false;
			SubEmittersModule subEmitters = component.subEmitters;
			((SubEmittersModule)(ref subEmitters)).enabled = false;
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("StaffLightning");
			Transform val4 = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.transform.Find("attach/Loaded/Lightning") : null);
			if (!Object.op_Implicit((Object)(object)val4))
			{
				throw new InvalidOperationException("Missing StaffLightning loaded lightning effect.");
			}
			Incinerator component3 = PrefabManager.Instance.GetPrefab("incinerator").GetComponent<Incinerator>();
			GameObject lightingAOEs = component3.m_lightingAOEs;
			sound = CopyVisual(((Component)lightingAOEs.GetComponentsInChildren<ZSFX>(true).First((ZSFX sfx) => sfx.m_audioClips.Any((AudioClip clip) => Object.op_Implicit((Object)(object)clip) && ((Object)clip).name.StartsWith("Obliterator_Lightning_")))).gameObject, "LightningTower_ObliteratorThunder");
			ZSFX component4 = sound.GetComponent<ZSFX>();
			component4.m_minDelay = (component4.m_maxDelay = 0f);
			component4.m_minVol *= Plugin.Settings.StrikeVolume.Value;
			component4.m_maxVol *= Plugin.Settings.StrikeVolume.Value;
			component4.m_maxConcurrentSources = 3;
			soundLifetime = component4.m_audioClips.Max((AudioClip clip) => clip.length) / Mathf.Max(0.1f, Mathf.Min(component4.m_minPitch, component4.m_maxPitch)) + 0.5f;
			ZSFX obj2 = component3.m_leverEffects.m_effectPrefabs.Where((EffectData effect) => Object.op_Implicit((Object)(object)effect.m_prefab)).SelectMany((EffectData effect) => effect.m_prefab.GetComponentsInChildren<ZSFX>(true)).First((ZSFX effect) => effect.m_audioClips.Any((AudioClip clip) => Object.op_Implicit((Object)(object)clip) && ((Object)clip).name.StartsWith("Obliterator_Electricity_Start_")));
			humClip = obj2.m_audioClips.OrderByDescending((AudioClip clip) => clip.length).First();
			humMixer = ((Component)obj2).GetComponent<AudioSource>().outputAudioMixerGroup;
			halo = new GameObject("LightningTower_ChargedHalo");
			halo.transform.SetParent(storage.transform, false);
			GameObject obj3 = CopyVisual(((Component)val4).gameObject, "WhiteElectricalArcs");
			obj3.transform.SetParent(halo.transform, false);
			ConfigureHaloParticles(obj3.GetComponent<ParticleSystem>(), stars: false);
			ParticleSystem val5 = component3.m_leverEffects.m_effectPrefabs.Where((EffectData effect) => Object.op_Implicit((Object)(object)effect.m_prefab)).SelectMany((EffectData effect) => effect.m_prefab.GetComponentsInChildren<ParticleSystem>(true)).FirstOrDefault((Func<ParticleSystem, bool>)((ParticleSystem effect) => ((Object)effect).name.IndexOf("spar", StringComparison.OrdinalIgnoreCase) >= 0 && ((Renderer)((Component)effect).GetComponent<ParticleSystemRenderer>()).sharedMaterials.Any((Material material) => Object.op_Implicit((Object)(object)material) && Object.op_Implicit((Object)(object)material.mainTexture) && ((Object)material.mainTexture).name == "spark")));
			Transform val6 = (Object.op_Implicit((Object)(object)val5) ? ((Component)val5).transform : lightingAOEs.transform.Find("Sparcs"));
			if (!Object.op_Implicit((Object)(object)val6))
			{
				throw new InvalidOperationException("Missing Obliterator star particles.");
			}
			GameObject obj4 = CopyVisual(((Component)val6).gameObject, "ObliteratorStars");
			obj4.transform.SetParent(halo.transform, false);
			ConfigureHaloParticles(obj4.GetComponent<ParticleSystem>(), stars: true);
			jaggedMaterial = WhiteMaterial(((Renderer)((Component)val4).GetComponent<ParticleSystemRenderer>()).sharedMaterials.First((Material material) => Object.op_Implicit((Object)(object)material)));
			crownMaterial = WhiteMaterial(jaggedMaterial);
			((Object)crownMaterial).name = "LightningTower_CrownArcWhite";
			crownMaterial.mainTexture = (Texture)(object)Texture2D.whiteTexture;
			crownMaterial.mainTextureScale = Vector2.one;
			crownMaterial.mainTextureOffset = Vector2.zero;
			ready = true;
			Plugin.Log.LogInfo((object)string.Format("Visuals: jagged overlay + chain-lightning core; white halo radius={0}m; stars={1}/{2}.", Plugin.Settings.HaloRadius.Value, Object.op_Implicit((Object)(object)val5) ? "Obliterator charging" : "Obliterator lightning", ((Object)val6).name));
			Plugin.Log.LogInfo((object)$"Audio: Obliterator_Lightning_01/02/03; electrical hum + {((Object)humClip).name}, pitch=0.75, crossfade=0.35s, radius={Plugin.Settings.HumRange.Value}m.");
		}

		private static Material WhiteMaterial(Material original)
		{
			//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_001d: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(original)
			{
				name = ((Object)original).name + "_LightningTowerWhite"
			};
			string[] array = new string[3] { "_Color", "_TintColor", "_EmissionColor" };
			foreach (string text in array)
			{
				if (val.HasProperty(text))
				{
					val.SetColor(text, Color.white);
				}
			}
			return val;
		}

		private static void ConfigureHaloParticles(ParticleSystem particles, bool stars)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00c2: 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_00f6: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: 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_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: 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_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Expected O, but got Unknown
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
			particles.Stop(true, (ParticleSystemStopBehavior)0);
			float num = Plugin.Settings.HaloRadius.Value / 3f;
			MainModule main = particles.main;
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).duration = 3f;
			((MainModule)(ref main)).prewarm = true;
			((MainModule)(ref main)).playOnAwake = true;
			((MainModule)(ref main)).cullingMode = (ParticleSystemCullingMode)3;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
			((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(stars ? 0.35f : 0.65f, stars ? 0.8f : 1.15f);
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f);
			((MainModule)(ref main)).startSize = new MinMaxCurve(stars ? 0.03f : 0.007f, stars ? 0.07f : 0.015f);
			((MainModule)(ref main)).startSize3D = false;
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.white);
			((MainModule)(ref main)).maxParticles = (stars ? 48 : 120);
			ShapeModule shape = particles.shape;
			((ShapeModule)(ref shape)).enabled = true;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
			((ShapeModule)(ref shape)).radius = num * (stars ? 1.15f : 1f);
			((ShapeModule)(ref shape)).radiusThickness = 0f;
			((ShapeModule)(ref shape)).position = Vector3.zero;
			((ShapeModule)(ref shape)).rotation = Vector3.zero;
			((ShapeModule)(ref shape)).scale = Vector3.one;
			EmissionModule emission = particles.emission;
			((EmissionModule)(ref emission)).enabled = true;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit((float)(stars ? 18 : 70));
			((EmissionModule)(ref emission)).rateOverDistance = MinMaxCurve.op_Implicit(0f);
			((EmissionModule)(ref emission)).SetBursts(Array.Empty<Burst>());
			VelocityOverLifetimeModule velocityOverLifetime = particles.velocityOverLifetime;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = !stars;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)0;
			MinMaxCurve val = (((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z = MinMaxCurve.op_Implicit(0f));
			MinMaxCurve x = (((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y = val);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x = x;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalX = new MinMaxCurve(1f, 2f);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalY = new MinMaxCurve(2f, 4f);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalZ = new MinMaxCurve(0f, 0f);
			val = (((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalOffsetZ = MinMaxCurve.op_Implicit(0f));
			x = (((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalOffsetY = val);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalOffsetX = x;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).radial = MinMaxCurve.op_Implicit(0f);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).speedModifier = MinMaxCurve.op_Implicit(1f);
			ForceOverLifetimeModule forceOverLifetime = particles.forceOverLifetime;
			((ForceOverLifetimeModule)(ref forceOverLifetime)).enabled = false;
			ExternalForcesModule externalForces = particles.externalForces;
			((ExternalForcesModule)(ref externalForces)).enabled = false;
			CollisionModule collision = particles.collision;
			((CollisionModule)(ref collision)).enabled = false;
			ColorBySpeedModule colorBySpeed = particles.colorBySpeed;
			((ColorBySpeedModule)(ref colorBySpeed)).enabled = false;
			SizeOverLifetimeModule sizeOverLifetime = particles.sizeOverLifetime;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = false;
			NoiseModule noise = particles.noise;
			((NoiseModule)(ref noise)).enabled = !stars;
			((NoiseModule)(ref noise)).strength = MinMaxCurve.op_Implicit(num * 0.06f);
			((NoiseModule)(ref noise)).frequency = 4f;
			((NoiseModule)(ref noise)).scrollSpeed = MinMaxCurve.op_Implicit(0.7f);
			ColorOverLifetimeModule colorOverLifetime = particles.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val6 = new Gradient();
			val6.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(Color.white, 0f),
				new GradientColorKey(Color.white, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
			{
				new GradientAlphaKey(0f, 0f),
				new GradientAlphaKey(1f, 0.15f),
				new GradientAlphaKey(0.85f, 0.7f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val6);
			TrailModule trails = particles.trails;
			if (!stars)
			{
				((TrailModule)(ref trails)).enabled = true;
				((TrailModule)(ref trails)).mode = (ParticleSystemTrailMode)0;
				((TrailModule)(ref trails)).ratio = 1f;
				((TrailModule)(ref trails)).lifetime = MinMaxCurve.op_Implicit(0.25f);
				((TrailModule)(ref trails)).minVertexDistance = 0.006f;
				((TrailModule)(ref trails)).worldSpace = false;
				((TrailModule)(ref trails)).dieWithParticles = true;
				((TrailModule)(ref trails)).inheritParticleColor = true;
				((TrailModule)(ref trails)).colorOverLifetime = MinMaxGradient.op_Implicit(val6);
				((TrailModule)(ref trails)).colorOverTrail = new MinMaxGradient(Color.white);
			}
			else
			{
				((TrailModule)(ref trails)).enabled = false;
			}
			ParticleSystemRenderer component = ((Component)particles).GetComponent<ParticleSystemRenderer>();
			if (stars)
			{
				component.renderMode = (ParticleSystemRenderMode)0;
				component.alignment = (ParticleSystemRenderSpace)0;
				component.lengthScale = 0f;
				component.velocityScale = 0f;
			}
			Material fallback = ((Renderer)component).sharedMaterials.First((Material material) => Object.op_Implicit((Object)(object)material));
			((Renderer)component).sharedMaterials = ((Renderer)component).sharedMaterials.Select((Material material) => WhiteMaterial(Object.op_Implicit((Object)(object)material) ? material : fallback)).ToArray();
			((Renderer)component).localBounds = new Bounds(Vector3.zero, Vector3.one * (num * 2f + 1f));
			particles.Play();
		}

		private static GameObject CopyVisual(GameObject source, string name)
		{
			//IL_0088: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(source, storage.transform);
			((Object)val).name = name;
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren)
			{
				if (!(val2 is ZSFX))
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			Collider[] componentsInChildren2 = val.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			Rigidbody[] componentsInChildren3 = val.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			val.SetActive(true);
			return val;
		}

		internal static GameObject AttachHalo(Transform tip)
		{
			//IL_0012: 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_0032: 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)
			GameObject obj = Object.Instantiate<GameObject>(halo, tip, false);
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = Vector3.one * (3f / TowerGeometry.Scale);
			obj.SetActive(false);
			return obj;
		}

		internal static ChargedHum AttachHum(Transform tower)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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)
			//IL_001d: 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)
			GameObject val = new GameObject("LightningTower_ChargedHum");
			val.transform.SetParent(tower, false);
			val.transform.localPosition = Vector3.up * (1.2f / TowerGeometry.Scale);
			ChargedHum chargedHum = val.AddComponent<ChargedHum>();
			chargedHum.Initialize(humClip, humMixer);
			return chargedHum;
		}

		internal static CrownLightning AttachCrownLightning(Transform tower, Transform tip)
		{
			CrownLightning crownLightning = ((Component)tower).gameObject.AddComponent<CrownLightning>();
			crownLightning.Initialize(tip, crownMaterial);
			return crownLightning;
		}

		internal static GameObject? Play(Vector3 origin, Vector3 target)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0021: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0054: 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_008a: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_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_00b8: 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_00c9: 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_00d7: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready)
			{
				return null;
			}
			Vector3 val = target - origin;
			if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
			{
				return null;
			}
			Quaternion val2 = Quaternion.FromToRotation(Vector3.right, val);
			float num = ((Vector3)(ref val)).magnitude / ((Bounds)(ref boltBounds)).size.x;
			float num2 = 0.09f / Mathf.Max(0.01f, Mathf.Max(((Bounds)(ref boltBounds)).size.y, ((Bounds)(ref boltBounds)).size.z));
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(num, num2, num2);
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(((Bounds)(ref boltBounds)).min.x, 0f, 0f);
			GameObject obj = Object.Instantiate<GameObject>(bolt, origin - val2 * Vector3.Scale(val4, val3), val2);
			obj.transform.localScale = val3;
			obj.AddComponent<JaggedBolt>().Initialize(origin, target, jaggedMaterial);
			Object.Destroy((Object)(object)obj, 0.6f);
			if (Object.op_Implicit((Object)(object)sound))
			{
				Object.Destroy((Object)(object)Object.Instantiate<GameObject>(sound, origin, Quaternion.identity), soundLifetime);
			}
			return obj;
		}
	}
	internal static class NorseTowerModel
	{
		internal const float Height = 6f;

		internal const float BurialDepth = 0.45f;

		internal const float OrbRadius = 0.34f;

		internal const float TipHeight = 5.28f;

		internal const string ModelName = "LightningTower_NorseModel";

		internal const string MetalworkName = "CopperPillar";

		internal const string RunePrefix = "RuneFace";

		internal const string BranchTipPrefix = "LightningTower_BranchTip_";

		internal static readonly Color RuneGlow = new Color(0.21f, 1.95f, 3f);

		internal static GameObject Build(Transform parent)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_005d: 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_006e: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04da: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_0532: Unknown result type (might be due to invalid IL or missing references)
			//IL_053c: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Expected O, but got Unknown
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0593: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Expected O, but got Unknown
			GameObject val = new GameObject("LightningTower_NorseModel");
			val.transform.SetParent(parent, false);
			val.layer = LayerMask.NameToLayer("piece");
			Material sharedMaterial = ((Renderer)PrefabManager.Instance.GetPrefab("Copper").GetComponentInChildren<MeshRenderer>(true)).sharedMaterial;
			Material val2 = new Material(((Renderer)PrefabManager.Instance.GetPrefab("BlackMetal").GetComponentInChildren<MeshRenderer>(true)).sharedMaterial)
			{
				name = "LightningTower_BlackMetal"
			};
			Shader shader = sharedMaterial.shader;
			if (!Object.op_Implicit((Object)(object)shader))
			{
				throw new InvalidOperationException("Standard copper shader is unavailable.");
			}
			Material[] array = (Material[])(object)new Material[7]
			{
				new Material(sharedMaterial)
				{
					name = "LightningTower_Copper"
				},
				new Material(sharedMaterial)
				{
					name = "LightningTower_CopperWeathered"
				},
				new Material(sharedMaterial)
				{
					name = "LightningTower_CopperBright"
				},
				Metal(shader, "RuneInlay", new Color(0.12f, 0.55f, 0.67f), 0.35f, 0.48f),
				Metal(shader, "OrbPreviewSlot", new Color(0.22f, 0.73f, 0.9f), 0.15f, 0.68f),
				val2,
				val2
			};
			array[3].EnableKeyword("_EMISSION");
			array[3].SetColor("_EmissionColor", Color.black);
			using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("LightningTower.CopperSurface") ?? throw new InvalidOperationException("Embedded copper texture is missing."))
			{
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				Texture2D val3 = new Texture2D(2, 2, (TextureFormat)4, true)
				{
					name = "LightningTower_AuthoredCopper",
					wrapMode = (TextureWrapMode)0
				};
				if (!(bool)(typeof(ImageConversion).GetMethod("LoadImage", new Type[3]
				{
					typeof(Texture2D),
					typeof(byte[]),
					typeof(bool)
				}) ?? throw new MissingMethodException("Unity's byte-array image loader is unavailable.")).Invoke(null, new object[3]
				{
					val3,
					memoryStream.ToArray(),
					true
				}))
				{
					throw new InvalidDataException("Copper texture could not be loaded.");
				}
				for (int i = 0; i < 3; i++)
				{
					array[i].mainTexture = (Texture)(object)val3;
				}
			}
			using Stream input = Assembly.GetExecutingAssembly().GetManifestResourceStream("LightningTower.CopperTowerMesh") ?? throw new InvalidOperationException("Embedded copper tower mesh is missing.");
			using BinaryReader binaryReader = new BinaryReader(input);
			if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "LT08")
			{
				throw new InvalidDataException("Unsupported tower mesh format.");
			}
			int num = binaryReader.ReadInt32();
			int num2 = 0;
			for (int j = 0; j < num; j++)
			{
				string text = Encoding.UTF8.GetString(binaryReader.ReadBytes(binaryReader.ReadInt32()));
				int num3 = binaryReader.ReadInt32();
				num2 += num3;
				Vector3[] array2 = (Vector3[])(object)new Vector3[num3 * 3];
				Vector2[] array3 = (Vector2[])(object)new Vector2[array2.Length];
				List<int>[] array4 = new List<int>[array.Length];
				for (int k = 0; k < array4.Length; k++)
				{
					array4[k] = new List<int>();
				}
				for (int l = 0; l < num3; l++)
				{
					int num4 = binaryReader.ReadInt32();
					for (int m = 0; m < 3; m++)
					{
						int num5 = l * 3 + m;
						array2[num5] = ReadVector(binaryReader);
						array3[num5] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
						array4[num4].Add(num5);
					}
				}
				Mesh val4 = new Mesh
				{
					name = "LightningTower_" + text,
					vertices = array2,
					uv = array3,
					subMeshCount = array.Length
				};
				for (int n = 0; n < array4.Length; n++)
				{
					val4.SetTriangles(array4[n], n);
				}
				val4.RecalculateNormals();
				val4.RecalculateBounds();
				GameObject val5 = new GameObject(text);
				val5.layer = val.layer;
				val5.transform.SetParent(val.transform, false);
				val5.AddComponent<MeshFilter>().sharedMesh = val4;
				((Renderer)val5.AddComponent<MeshRenderer>()).sharedMaterials = array;
				if (text == "CopperPillar")
				{
					MeshCollider obj = val5.AddComponent<MeshCollider>();
					obj.sharedMesh = val4;
					obj.convex = true;
				}
			}
			int num6 = binaryReader.ReadInt32();
			for (int num7 = 0; num7 < num6; num7++)
			{
				Vector3 val6 = ReadVector(binaryReader);
				Vector3 val7 = ReadVector(binaryReader);
				float num8 = binaryReader.ReadSingle();
				GameObject val8 = new GameObject("ConductorCollision")
				{
					layer = val.layer
				};
				val8.transform.SetParent(val.transform, false);
				val8.transform.localPosition = (val6 + val7) * 0.5f;
				val8.transform.localRotation = Quaternion.FromToRotation(Vector3.up, val7 - val6);
				CapsuleCollider obj2 = val8.AddComponent<CapsuleCollider>();
				obj2.radius = num8;
				obj2.height = Vector3.Distance(val6, val7) + num8 * 2f;
			}
			CapsuleCollider obj3 = val.AddComponent<CapsuleCollider>();
			obj3.center = Vector3.up * 4.68f;
			obj3.height = 1.12f;
			obj3.radius = 0.13f;
			int num9 = binaryReader.ReadInt32();
			for (int num10 = 0; num10 < num9; num10++)
			{
				Transform transform = new GameObject("LightningTower_BranchTip_" + num10).transform;
				transform.SetParent(val.transform, false);
				transform.localPosition = ReadVector(binaryReader);
			}
			SphereCollider obj4 = val.AddComponent<SphereCollider>();
			obj4.center = Vector3.up * 5.28f;
			obj4.radius = 0.34f;
			Plugin.Log.LogInfo((object)$"Copper concept model: {num} authored parts, {num2} authored triangles, 3 rune faces, 2 raised-rim riveted bands, {num9} crown tips, height={6f}m above / {0.45f}m below ground, orb centre={5.28f}m.");
			return val;
		}

		private static Vector3 ReadVector(BinaryReader reader)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
		}

		private static Material Metal(Shader shader, string name, Color color, float metallic, float smoothness)
		{
			//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_0017: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			Material val = new Material(shader)
			{
				name = "LightningTower_" + name,
				color = color
			};
			val.SetFloat("_Metallic", metallic);
			val.SetFloat("_Glossiness", smoothness);
			return val;
		}
	}
	[BepInPlugin("valheim.lightningtower", "Lightning Tower", "0.3.7")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "valheim.lightningtower";

		public const string Version = "0.3.7";

		public const string PrefabName = "piece_lightningtower";

		internal static TowerSettings Settings { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new TowerSettings(((BaseUnityPlugin)this).Config);
			PrefabManager.OnVanillaPrefabsAvailable += RegisterTower;
			SynchronizationManager.OnConfigurationSynchronized += ConfigurationSynchronized;
			((Component)this).gameObject.AddComponent<RefillClient>();
			((Component)this).gameObject.AddComponent<TargetCoordinator>();
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TowerCommand());
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Lightning Tower {0} loaded. Range={1}m; capacity={2}.", "0.3.7", Settings.Range.Value, Settings.Capacity.Value));
		}

		private void RegisterTower()
		{
			try
			{
				TowerPrefab.Register();
				PrefabManager.OnVanillaPrefabsAvailable -= RegisterTower;
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Tower registration failed: {arg}");
			}
		}

		private void ConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs args)
		{
			TowerPrefab.RefreshConfiguration();
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterTower;
			SynchronizationManager.OnConfigurationSynchronized -= ConfigurationSynchronized;
		}
	}
	internal sealed class RefillClient : MonoBehaviour
	{
		[Serializable]
		private sealed class Journal
		{
			public long World;

			public long TowerUser;

			public uint TowerId;

			public string Token = "";

			public bool StoneRemoved;
		}

		private const string JournalKey = "lightningtower.pendingRefill";

		private static float retryAt;

		internal static bool Begin(TowerBehaviour tower, Humanoid user)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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)
			Player val = (Player)(object)((user is Player) ? user : null);
			if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)tower.View) || !tower.View.IsValid())
			{
				return false;
			}
			if (Read(val) != null)
			{
				((Character)val).Message((MessageType)2, "A refill is pending. Stay near that tower until it finishes.", 0, (Sprite)null, false);
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)tower).transform.position, 0f, true, false))
			{
				return false;
			}
			if (tower.Charge >= Plugin.Settings.Capacity.Value)
			{
				((Character)val).Message((MessageType)2, "The tower is already full.", 0, (Sprite)null, false);
				return false;
			}
			if (FindStone(val) == null)
			{
				((Character)val).Message((MessageType)2, "You need one Thunder Stone.", 0, (Sprite)null, false);
				return false;
			}
			ZDOID uid = tower.View.GetZDO().m_uid;
			Journal journal = new Journal
			{
				World = ZNet.World.m_uid,
				TowerUser = ((ZDOID)(ref uid)).UserID,
				TowerId = ((ZDOID)(ref uid)).ID,
				Token = Guid.NewGuid().ToString("N")
			};
			Write(val, journal);
			Send(tower, val, journal);
			return true;
		}

		private void Update()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)ZNet.instance) || Time.unscaledTime < retryAt)
			{
				return;
			}
			retryAt = Time.unscaledTime + 1f;
			Journal journal = Read(localPlayer);
			if (journal != null && journal.World == ZNet.World.m_uid)
			{
				ZNetScene instance = ZNetScene.instance;
				GameObject obj = ((instance != null) ? instance.FindInstance(new ZDOID(journal.TowerUser, journal.TowerId)) : null);
				TowerBehaviour towerBehaviour = ((obj != null) ? obj.GetComponent<TowerBehaviour>() : null);
				if (Object.op_Implicit((Object)(object)towerBehaviour) && Object.op_Implicit((Object)(object)towerBehaviour.View) && towerBehaviour.View.IsValid())
				{
					Send(towerBehaviour, localPlayer, journal);
				}
			}
		}

		private static void Send(TowerBehaviour tower, Player player, Journal journal)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			retryAt = Time.unscaledTime + 1f;
			tower.View.InvokeRPC(journal.StoneRemoved ? "LT_Commit" : "LT_Request", new object[2]
			{
				((Character)player).GetZDOID(),
				journal.Token
			});
		}

		internal static void Grant(TowerBehaviour tower, long peer, string token)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || peer != tower.View.GetZDO().GetOwner())
			{
				return;
			}
			Journal journal = Read(localPlayer);
			if (!Matches(tower, journal, token))
			{
				return;
			}
			if (!journal.StoneRemoved)
			{
				ItemData val = FindStone(localPlayer);
				if (val == null || !PrivateArea.CheckAccess(((Component)tower).transform.position, 0f, true, false))
				{
					localPlayer.m_customData.Remove("lightningtower.pendingRefill");
					((Character)localPlayer).Message((MessageType)2, "Refill cancelled. The tower will unlock shortly.", 0, (Sprite)null, false);
					return;
				}
				if (!((Humanoid)localPlayer).GetInventory().RemoveItem(val, 1))
				{
					return;
				}
				journal.StoneRemoved = true;
				Write(localPlayer, journal);
			}
			Send(tower, localPlayer, journal);
		}

		internal static void Result(TowerBehaviour tower, long peer, string token, bool accepted, string message)
		{
			//IL_007b: 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)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || peer != tower.View.GetZDO().GetOwner())
			{
				return;
			}
			Journal journal = Read(localPlayer);
			if (!Matches(tower, journal, token))
			{
				return;
			}
			if (!accepted && journal.StoneRemoved)
			{
				ItemData val = ObjectDB.instance.GetItemPrefab("Thunderstone").GetComponent<ItemDrop>().m_itemData.Clone();
				val.m_stack = 1;
				if (!((Humanoid)localPlayer).GetInventory().AddItem(val))
				{
					ItemDrop.DropItem(val, 1, ((Component)localPlayer).transform.position + Vector3.up, Quaternion.identity);
				}
			}
			localPlayer.m_customData.Remove("lightningtower.pendingRefill");
			((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false);
		}

		private static ItemData? FindStone(Player player)
		{
			return ((IEnumerable<ItemData>)((Humanoid)player).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => item.m_stack > 0 && Object.op_Implicit((Object)(object)item.m_dropPrefab) && ((Object)item.m_dropPrefab).name == "Thunderstone"));
		}

		private static bool Matches(TowerBehaviour tower, Journal? journal, string token)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (journal != null && journal.Token == token && journal.World == ZNet.World.m_uid)
			{
				return tower.View.GetZDO().m_uid == new ZDOID(journal.TowerUser, journal.TowerId);
			}
			return false;
		}

		private static void Write(Player player, Journal journal)
		{
			player.m_customData["lightningtower.pendingRefill"] = JsonUtility.ToJson((object)journal);
		}

		private static Journal? Read(Player player)
		{
			if (!player.m_customData.TryGetValue("lightningtower.pendingRefill", out var value))
			{
				return null;
			}
			try
			{
				return JsonUtility.FromJson<Journal>(value);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not read pending refill. Preserve character data for recovery: " + ex.Message));
				return null;
			}
		}
	}
	internal static class StormWeather
	{
		private static readonly MethodInfo SelectWeather = AccessTools.Method(typeof(EnvMan), "SelectWeightedEnvironment", (Type[])null, (Type[])null);

		internal static bool IsThunderstorm(Vector3 position)
		{
			//IL_01ce: 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_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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: 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_0188: Unknown result type (might be due to invalid IL or missing references)
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null || WorldGenerator.instance == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (!ZNet.instance.IsDedicated() && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() == 0 && !string.IsNullOrEmpty(instance.m_debugEnv))
			{
				return IsStormName(instance.m_debugEnv);
			}
			BiomeSector biomeSector = WorldGenerator.instance.GetBiomeSector(position, false);
			foreach (AltBiome altBiome in biomeSector.AltBiomes)
			{
				if (!string.IsNullOrEmpty(altBiome.m_forceEnvironment))
				{
					return IsStormName(altBiome.m_forceEnvironment);
				}
			}
			string text = (Object.op_Implicit((Object)(object)PersistentEventSystem.instance) ? PersistentEventSystem.instance.GetEnvironmentOverride() : null);
			if (!string.IsNullOrEmpty(text))
			{
				return IsStormName(text);
			}
			List<EnvEntry> availableEnvironments = instance.GetAvailableEnvironments(biomeSector);
			if (availableEnvironments == null || availableEnvironments.Count == 0)
			{
				return false;
			}
			State state = Random.state;
			try
			{
				Random.InitState((int)((long)ZNet.instance.GetTimeSeconds() / Math.Max(1L, instance.m_environmentDuration)));
				EnvSetup val = (EnvSetup)SelectWeather.Invoke(instance, new object[1] { availableEnvironments });
				foreach (EnvEntry item in availableEnvironments)
				{
					if (item.m_ashlandsOverride && WorldGenerator.IsAshlands(position.x, position.z))
					{
						val = item.m_env;
					}
					if (item.m_deepnorthOverride && WorldGenerator.IsDeepnorth(position.x, position.z))
					{
						val = item.m_env;
					}
				}
				return val != null && IsStormName(val.m_name);
			}
			finally
			{
				Random.state = state;
			}
		}

		private static bool IsStormName(string? name)
		{
			return string.Equals(name, "ThunderStorm", StringComparison.OrdinalIgnoreCase);
		}
	}
	internal static class TargetAssignment
	{
		internal static int[] Match(double[,] distances)
		{
			int length = distances.GetLength(0);
			int length2 = distances.GetLength(1);
			int num = length2 + length;
			int[] array = new int[length];
			for (int i = 0; i < length; i++)
			{
				array[i] = -1;
			}
			if (length == 0 || length2 == 0)
			{
				return array;
			}
			double num2 = 0.0;
			foreach (double num3 in distances)
			{
				if (Valid(num3))
				{
					num2 = Math.Max(num2, num3);
				}
			}
			double num4 = (num2 + 1.0) * (double)(length + 1);
			double[] array2 = new double[length + 1];
			double[] array3 = new double[num + 1];
			int[] array4 = new int[num + 1];
			int[] array5 = new int[num + 1];
			for (int l = 1; l <= length; l++)
			{
				array4[0] = l;
				double[] array6 = new double[num + 1];
				bool[] array7 = new bool[num + 1];
				for (int m = 1; m <= num; m++)
				{
					array6[m] = double.PositiveInfinity;
				}
				int num5 = 0;
				do
				{
					array7[num5] = true;
					int num6 = array4[num5];
					int num7 = 0;
					double num8 = double.PositiveInfinity;
					for (int n = 1; n <= num; n++)
					{
						if (!array7[n])
						{
							double num9 = ((n <= length2) ? distances[num6 - 1, n - 1] : num4);
							if (!Valid(num9))
							{
								num9 = num4 * 2.0;
							}
							double num10 = num9 - array2[num6] - array3[n];
							if (num10 < array6[n])
							{
								array6[n] = num10;
								array5[n] = num5;
							}
							if (array6[n] < num8)
							{
								num8 = array6[n];
								num7 = n;
							}
						}
					}
					for (int num11 = 0; num11 <= num; num11++)
					{
						if (array7[num11])
						{
							array2[array4[num11]] += num8;
							array3[num11] -= num8;
						}
						else
						{
							array6[num11] -= num8;
						}
					}
					num5 = num7;
				}
				while (array4[num5] != 0);
				do
				{
					int num12 = array5[num5];
					array4[num5] = array4[num12];
					num5 = num12;
				}
				while (num5 != 0);
			}
			for (int num13 = 1; num13 <= length2; num13++)
			{
				if (array4[num13] != 0 && Valid(distances[array4[num13] - 1, num13 - 1]))
				{
					array[array4[num13] - 1] = num13 - 1;
				}
			}
			return array;
		}

		private static bool Valid(double cost)
		{
			if (cost >= 0.0 && !double.IsNaN(cost))
			{
				return !double.IsInfinity(cost);
			}
			return false;
		}
	}
	internal sealed class TargetCoordinator : MonoBehaviour
	{
		private sealed class Report
		{
			internal ZDOID Tower;

			internal long Owner;

			internal float Received;

			internal readonly Dictionary<ZDOID, float> Distances = new Dictionary<ZDOID, float>();
		}

		private const string ReportRpc = "LightningTower_TargetReport";

		private const string GrantRpc = "LightningTower_TargetGrant";

		private const string ResultRpc = "LightningTower_TargetResult";

		private readonly Dictionary<ZDOID, Report> reports = new Dictionary<ZDOID, Report>();

		private TargetReservations<ZDOID> reservations = new TargetReservations<ZDOID>();

		private ZRoutedRpc? rpc;

		private float nextReport;

		private float nextRound;

		private readonly Dictionary<ZDOID, long> lastGrants = new Dictionary<ZDOID, long>();

		private static readonly HashSet<TowerBehaviour> towers = new HashSet<TowerBehaviour>();

		private static double Now => (double)ZNet.instance.GetTime().Ticks / 10000000.0;

		private static long Server
		{
			get
			{
				if (!ZNet.instance.IsServer())
				{
					return ZNet.instance.GetServerPeer()?.m_uid ?? 0;
				}
				return ZNet.GetUID();
			}
		}

		internal static void Add(TowerBehaviour tower)
		{
			towers.Add(tower);
		}

		internal static void Remove(TowerBehaviour tower)
		{
			towers.Remove(tower);
		}

		private void Update()
		{
			if (rpc != ZRoutedRpc.instance)
			{
				rpc = ZRoutedRpc.instance;
				reports.Clear();
				reservations = new TargetReservations<ZDOID>();
				lastGrants.Clear();
				nextReport = 0f;
				nextRound = Time.time + Plugin.Settings.ScanInterval.Value;
				if (rpc != null)
				{
					rpc.Register<ZDOID, ZPackage>("LightningTower_TargetReport", (Action<long, ZDOID, ZPackage>)ReceiveReport);
					rpc.Register<ZPackage>("LightningTower_TargetGrant", (Action<long, ZPackage>)ReceiveGrant);
					rpc.Register<long, bool>("LightningTower_TargetResult", (Action<long, long, bool>)ReceiveResult);
				}
			}
		}

		private void LateUpdate()
		{
			if (rpc != null && Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)ZNetScene.instance) && Server != 0L)
			{
				if (Time.time >= nextReport)
				{
					nextReport = Time.time + Plugin.Settings.ScanInterval.Value;
					SendReports();
				}
				if (ZNet.instance.IsServer() && !(Time.time < nextRound))
				{
					nextRound = Time.time + Plugin.Settings.ScanInterval.Value;
					AssignRound();
				}
			}
		}

		private void SendReports()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_009e: 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_00b7: 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)
			Character[] source = Character.GetAllCharacters().Where(TowerBehaviour.Eligible).ToArray();
			TowerBehaviour[] array = towers.ToArray();
			foreach (TowerBehaviour towerBehaviour in array)
			{
				if (!Object.op_Implicit((Object)(object)towerBehaviour) || !towerBehaviour.CanFire())
				{
					continue;
				}
				Character[] array2 = source.Where(towerBehaviour.CanHit).ToArray();
				if (array2.Length != 0)
				{
					ZPackage val = new ZPackage();
					val.Write(array2.Length);
					Character[] array3 = array2;
					foreach (Character val2 in array3)
					{
						val.Write(val2.GetZDOID());
						val.Write(Vector3.Distance(((Component)towerBehaviour).transform.position, val2.GetCenterPoint()));
					}
					rpc.InvokeRoutedRPC(Server, "LightningTower_TargetReport", new object[2]
					{
						towerBehaviour.View.GetZDO().m_uid,
						val
					});
				}
			}
		}

		private void ReceiveReport(long sender, ZDOID tower, ZPackage package)
		{
			//IL_000c: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			if (!ZNet.instance.IsServer() || !ValidTower(tower, sender))
			{
				return;
			}
			Report report = new Report
			{
				Tower = tower,
				Owner = sender,
				Received = Time.time
			};
			int num = package.ReadInt();
			if (num < 0 || num > 4096)
			{
				return;
			}
			for (int i = 0; i < num; i++)
			{
				ZDOID val = package.ReadZDOID();
				float num2 = package.ReadSingle();
				if (num2 >= 0f && num2 <= Plugin.Settings.Range.Value && ValidTarget(val))
				{
					report.Distances[val] = num2;
				}
			}
			reports[tower] = report;
		}

		private void AssignRound()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_02a2: 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)
			double now = Now;
			reservations.Expire(now);
			float maxAge = Mathf.Max(1f, Plugin.Settings.ScanInterval.Value * 2f);
			Report[] array = reports.Values.Where((Report report2) => Time.time - report2.Received > maxAge || !ValidTower(report2.Tower, report2.Owner)).ToArray();
			foreach (Report report in array)
			{
				reports.Remove(report.Tower);
			}
			Report[] array2 = (from report2 in reports.Values
				where !reservations.TowerBusy(report2.Tower)
				orderby ((ZDOID)(ref report2.Tower)).UserID, ((ZDOID)(ref report2.Tower)).ID
				select report2).ToArray();
			ZDOID[] array3 = (from target in array2.SelectMany((Report report2) => report2.Distances.Keys).Distinct()
				where !reservations.TargetBusy(target) && ValidTarget(target)
				orderby ((ZDOID)(ref target)).UserID, ((ZDOID)(ref target)).ID
				select target).ToArray();
			double[,] array4 = new double[array2.Length, array3.Length];
			for (int num2 = 0; num2 < array2.Length; num2++)
			{
				for (int num3 = 0; num3 < array3.Length; num3++)
				{
					array4[num2, num3] = (array2[num2].Distances.TryGetValue(array3[num3], out var value) ? ((double)value) : double.PositiveInfinity);
				}
			}
			int[] array5 = TargetAssignment.Match(array4);
			List<TargetReservations<ZDOID>.Lease> list = new List<TargetReservations<ZDOID>.Lease>();
			for (int num4 = 0; num4 < array2.Length; num4++)
			{
				if (array5[num4] >= 0)
				{
					TargetReservations<ZDOID>.Lease lease = reservations.Reserve(array2[num4].Tower, array3[array5[num4]], array2[num4].Owner, now);
					if (lease != null)
					{
						reports.Remove(lease.Tower);
						list.Add(lease);
					}
				}
			}
			foreach (TargetReservations<ZDOID>.Lease item in list)
			{
				ZPackage val = new ZPackage();
				val.Write(item.Id);
				val.Write(item.Tower);
				val.Write(item.Target);
				val.Write(item.Deadline);
				rpc.InvokeRoutedRPC(item.Owner, "LightningTower_TargetGrant", new object[1] { val });
			}
		}

		private void ReceiveGrant(long sender, ZPackage package)
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0055: 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 (sender == Server)
			{
				long num = package.ReadLong();
				ZDOID val = package.ReadZDOID();
				ZDOID val2 = package.ReadZDOID();
				double num2 = package.ReadDouble();
				if ((!lastGrants.TryGetValue(val, out var value) || num > value) && !(Now >= num2))
				{
					lastGrants[val] = num;
					GameObject obj = ZNetScene.instance.FindInstance(val);
					TowerBehaviour towerBehaviour = ((obj != null) ? obj.GetComponent<TowerBehaviour>() : null);
					GameObject obj2 = ZNetScene.instance.FindInstance(val2);
					Character val3 = ((obj2 != null) ? obj2.GetComponent<Character>() : null);
					bool flag = Object.op_Implicit((Object)(object)towerBehaviour) && Object.op_Implicit((Object)(object)val3) && towerBehaviour.TryFire(val3);
					rpc.InvokeRoutedRPC(Server, "LightningTower_TargetResult", new object[2] { num, flag });
				}
			}
		}

		private void ReceiveResult(long sender, long id, bool fired)
		{
			if (ZNet.instance.IsServer())
			{
				reservations.Complete(id, sender, fired, Now, Plugin.Settings.Cooldown.Value);
			}
		}

		private static bool ValidTower(ZDOID id, long owner)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = ZDOMan.instance.GetZDO(id);
			if (zDO != null && zDO.GetPrefab() == StringExtensionMethods.GetStableHashCode("piece_lightningtower"))
			{
				return zDO.GetOwner() == owner;
			}
			return false;
		}

		internal static bool ValidTarget(ZDOID id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = ZDOMan.instance.GetZDO(id);
			if (zDO != null && ConfiguredTargets.Contains(zDO.GetPrefab()) && zDO.GetFloat(ZDOVars.s_health, 1f) > 0f)
			{
				return !zDO.GetBool(ZDOVars.s_tamed, false);
			}
			return false;
		}
	}
	internal sealed class TargetList
	{
		private readonly HashSet<int> prefabs = new HashSet<int>();

		internal TargetList(string csv, Func<string, int?> resolve, Action<string> rejected)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			string[] array = csv.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0 && hashSet.Add(text))
				{
					int? num = resolve(text);
					if (num.HasValue)
					{
						prefabs.Add(num.Value);
					}
					else
					{
						rejected(text);
					}
				}
			}
		}

		internal bool Contains(int prefab)
		{
			return prefabs.Contains(prefab);
		}
	}
	internal sealed class TargetReservations<TKey> where TKey : notnull
	{
		internal sealed class Lease
		{
			internal long Id;

			internal long Owner;

			internal TKey Tower;

			internal TKey Target;

			internal double Deadline;

			internal double Expires;

			internal bool Completed;
		}

		private readonly Dictionary<long, Lease> leases = new Dictionary<long, Lease>();

		private readonly Dictionary<TKey, long> towers = new Dictionary<TKey, long>();

		private readonly Dictionary<TKey, long> targets = new Dictionary<TKey, long>();

		private long sequence;

		internal bool TowerBusy(TKey tower)
		{
			return towers.ContainsKey(tower);
		}

		internal bool TargetBusy(TKey target)
		{
			return targets.ContainsKey(target);
		}

		internal Lease? Reserve(TKey tower, TKey target, long owner, double now)
		{
			Expire(now);
			if (TowerBusy(tower) || TargetBusy(target))
			{
				return null;
			}
			Lease lease = new Lease
			{
				Id = ++sequence,
				Tower = tower,
				Target = target,
				Owner = owner,
				Deadline = now + 2.0,
				Expires = now + 2.0
			};
			leases.Add(lease.Id, lease);
			towers.Add(tower, lease.Id);
			targets.Add(target, lease.Id);
			return lease;
		}

		internal bool Complete(long id, long owner, bool fired, double now, double cooldown)
		{
			Expire(now);
			if (!leases.TryGetValue(id, out Lease value) || value.Owner != owner || value.Completed)
			{
				return false;
			}
			if (!fired)
			{
				Remove(value);
			}
			else
			{
				value.Completed = true;
				value.Expires = now + Math.Max(0.1, cooldown);
			}
			return true;
		}

		internal void Expire(double now)
		{
			Lease[] array = leases.Values.Where((Lease lease2) => now >= lease2.Expires).ToArray();
			foreach (Lease lease in array)
			{
				Remove(lease);
			}
		}

		private void Remove(Lease lease)
		{
			leases.Remove(lease.Id);
			towers.Remove(lease.Tower);
			targets.Remove(lease.Target);
		}
	}
	public sealed class TowerBehaviour : MonoBehaviour, Hoverable, Interactable
	{
		internal const string ChargeKey = "lightningtower.charge";

		private const string ShotKey = "lightningtower.nextShot";

		private const string StormKey = "lightningtower.nextStorm";

		private float nextScan;

		private float nextWeatherCheck;

		private bool storm;

		private bool owned;

		private TowerVisuals visuals;

		private static readonly int OcclusionMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });

		internal ZNetView View { get; private set; }

		internal int Charge
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)View) || !View.IsValid())
				{
					return 0;
				}
				return ChargeRules.Clamp(View.GetZDO().GetInt("lightningtower.charge", 0), Plugin.Settings.Capacity.Value);
			}
		}

		internal Vector3 Tip => visuals.Tip;

		private void Awake()
		{
			//IL_0042: 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)
			View = ((Component)this).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)View) || !View.IsValid() || !Object.op_Implicit((Object)(object)ZNetScene.instance) || (Object)(object)ZNetScene.instance.FindInstance(View.GetZDO().m_uid) != (Object)(object)((Component)this).gameObject)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			((Component)this).transform.localScale = Vector3.one * TowerGeometry.Scale;
			visuals = ((Component)this).GetComponent<TowerVisuals>();
			View.Register<Vector3, Vector3>("LT_Fire", (Action<long, Vector3, Vector3>)ReceiveFire);
			TowerRefill.Register(this);