Decompiled source of AirStrike v1.2.1

plugins/AirStrike/AirStrike.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
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 Microsoft.CodeAnalysis;
using ModCommon;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("AirStrikeDev.Scripts")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AirStrike")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1")]
[assembly: AssemblyProduct("AirStrike")]
[assembly: AssemblyTitle("AirStrike")]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "Code, documentation and translations written with generative AI assistance")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic (Claude, via Claude Code)")]
[assembly: AssemblyVersion("1.2.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ModCommon
{
	internal static class Lang
	{
		private const string Fallback = "English";

		private const string SettingsSource = "Russian";

		private static readonly Dictionary<string, Dictionary<string, string>> s_tables = new Dictionary<string, Dictionary<string, string>>();

		private static readonly MethodInfo s_addWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null);

		private static string s_current;

		public static string Current => s_current ?? Saved();

		private static string Saved()
		{
			try
			{
				string text = PlatformPrefs.GetString("language", "");
				return string.IsNullOrEmpty(text) ? "English" : text;
			}
			catch
			{
				return "English";
			}
		}

		private static Dictionary<string, string> Table(string language)
		{
			if (s_tables.TryGetValue(language, out var value))
			{
				return value;
			}
			value = new Dictionary<string, string>();
			Read(value, "common." + language + ".txt");
			Read(value, "lang." + language + ".txt");
			return s_tables[language] = value;
		}

		private static void Read(Dictionary<string, string> table, string resource)
		{
			using Stream stream = typeof(Lang).Assembly.GetManifestResourceStream(resource);
			if (stream == null)
			{
				return;
			}
			using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
			string text;
			while ((text = streamReader.ReadLine()) != null)
			{
				text = text.Trim();
				if (text.Length != 0 && text[0] != '#')
				{
					int num = text.IndexOf('=');
					if (num > 0)
					{
						table[text.Substring(0, num).Trim()] = text.Substring(num + 1).Trim().Replace("\\n", "\n");
					}
				}
			}
		}

		private static string Find(string language, string key)
		{
			if (!Table(language).TryGetValue(key, out var value))
			{
				return null;
			}
			return value;
		}

		public static string Text(string key)
		{
			return Find(Current, key) ?? Find("English", key) ?? key;
		}

		public static string Setting(string key, string russian)
		{
			string current = Current;
			if (current == "Russian")
			{
				return russian;
			}
			return Find(current, key) ?? Find("English", key) ?? russian;
		}

		internal static void AddTokens(Localization loc, string language)
		{
			s_current = language;
			Dictionary<string, string> dictionary = Table(language);
			foreach (KeyValuePair<string, string> item in Table("English"))
			{
				if (item.Key[0] == '$')
				{
					string value;
					string text = (dictionary.TryGetValue(item.Key, out value) ? value : item.Value);
					s_addWord.Invoke(loc, new object[2]
					{
						item.Key.Substring(1),
						text
					});
				}
			}
		}

		public static void AddTokens()
		{
			Localization instance = Localization.instance;
			if (instance != null)
			{
				AddTokens(instance, instance.GetSelectedLanguage());
			}
		}
	}
	[HarmonyPatch(typeof(Localization), "SetupLanguage")]
	internal static class Lang_SetupLanguage
	{
		private static void Postfix(Localization __instance, string language)
		{
			Lang.AddTokens(__instance, language);
		}
	}
	internal sealed class MenuInfo
	{
		internal string SectionKey;

		internal string KeyPrefix;

		internal string RussianName;

		internal string RussianSection;

		internal string RussianDescription;

		public string Name => Lang.Setting(KeyPrefix + ".name", RussianName);

		public string Section => Lang.Setting("cfg.section." + SectionKey, RussianSection);

		public string Description => ConfigSync.Describe(KeyPrefix, RussianDescription, HostControlled, NeedsRelog, NeedsRestart);

		public string ModName => ConfigSync.ModText("name", "MenuName");

		public string ModDescription => ConfigSync.ModText("description", "MenuDescription");

		public int Order { get; set; }

		public bool HostControlled { get; set; }

		public bool NeedsRelog { get; set; }

		public bool NeedsRestart { get; set; }

		public Func<bool> LockedByHost { get; set; }
	}
	internal static class ConfigSync
	{
		private static BaseUnityPlugin s_plugin;

		private static ManualLogSource s_log;

		private static ConfigFile s_cfg;

		private static string s_version;

		private static string s_rpcRequest;

		private static string s_rpcData;

		private static int s_order;

		private static bool s_sendQueued;

		private static readonly List<ConfigEntryBase> s_hostEntries = new List<ConfigEntryBase>();

		private static readonly Dictionary<string, string> s_sectionNames = new Dictionary<string, string>();

		private static readonly Dictionary<ConfigEntryBase, string> s_local = new Dictionary<ConfigEntryBase, string>();

		private static readonly HashSet<long> s_peers = new HashSet<long>();

		private static readonly Dictionary<Type, FieldInfo> s_valueFields = new Dictionary<Type, FieldInfo>();

		private static List<KeyValuePair<ConfigEntryBase, object>> s_setAside;

		public static bool HostValuesActive { get; private set; }

		public static event Action<string> Received;

		public static void Init(BaseUnityPlugin plugin, string version)
		{
			s_plugin = plugin;
			s_log = Logger.CreateLogSource(plugin.Info.Metadata.Name + " sync");
			s_cfg = plugin.Config;
			s_version = version;
			string gUID = plugin.Info.Metadata.GUID;
			s_rpcRequest = gUID + ".ConfigRequest";
			s_rpcData = gUID + ".ConfigData";
			s_cfg.SettingChanged += OnSettingChanged;
		}

		public static void Section(string key, string name)
		{
			s_sectionNames[key] = name;
		}

		public static ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string name, string description, bool host, AcceptableValueBase acceptable = null, bool relog = false, bool restart = false)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			string value;
			MenuInfo menuInfo = new MenuInfo
			{
				SectionKey = section,
				KeyPrefix = "cfg." + section + "." + key,
				RussianName = name,
				RussianSection = (s_sectionNames.TryGetValue(section, out value) ? value : section),
				RussianDescription = description,
				Order = s_order++,
				HostControlled = host,
				NeedsRelog = relog,
				NeedsRestart = restart,
				LockedByHost = (host ? ((Func<bool>)(() => HostValuesActive)) : ((Func<bool>)(() => false)))
			};
			ConfigEntry<T> val = s_cfg.Bind<T>(section, key, defaultValue, new ConfigDescription(menuInfo.Description, acceptable, new object[1] { menuInfo }));
			if (host)
			{
				s_hostEntries.Add((ConfigEntryBase)(object)val);
			}
			return val;
		}

		internal static string Describe(string keyPrefix, string russian, bool host, bool relog, bool restart)
		{
			string text = Lang.Setting(keyPrefix + ".desc", russian);
			if (host)
			{
				text = text + "\n" + Lang.Text("common.host");
			}
			if (restart)
			{
				text = text + "\n" + Lang.Text("common.restart");
			}
			else if (relog)
			{
				text = text + "\n" + Lang.Text("common.relog");
			}
			return text;
		}

		internal static string ModText(string key, string constant)
		{
			FieldInfo field = ((object)s_plugin).GetType().GetField(constant, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			return Lang.Setting("menu." + key, (field?.GetValue(null) as string) ?? s_plugin.Info.Metadata.Name);
		}

		internal static void RegisterRpcs()
		{
			if (s_cfg != null && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.Register<string>(s_rpcRequest, (Action<long, string>)RPC_Request);
				ZRoutedRpc.instance.Register<ZPackage>(s_rpcData, (Action<long, ZPackage>)RPC_Data);
			}
		}

		internal static void RequestFromHost()
		{
			if (s_cfg != null && s_hostEntries.Count != 0 && Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer())
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(s_rpcRequest, new object[1] { s_version });
			}
		}

		private static void RPC_Request(long sender, string clientVersion)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				if (clientVersion != s_version)
				{
					s_log.LogWarning((object)$"Client {sender} runs version {clientVersion}, this host runs {s_version}");
				}
				s_peers.Add(sender);
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, s_rpcData, new object[1] { Pack() });
			}
		}

		private static ZPackage Pack()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(s_version);
			val.Write(s_hostEntries.Count);
			foreach (ConfigEntryBase s_hostEntry in s_hostEntries)
			{
				val.Write(s_hostEntry.Definition.Section + "/" + s_hostEntry.Definition.Key);
				val.Write(s_hostEntry.GetSerializedValue());
			}
			return val;
		}

		private static void RPC_Data(long sender, ZPackage p)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.IsServer())
			{
				return;
			}
			string text = p.ReadString();
			Dictionary<string, ConfigEntryBase> dictionary = new Dictionary<string, ConfigEntryBase>();
			foreach (ConfigEntryBase s_hostEntry in s_hostEntries)
			{
				dictionary[s_hostEntry.Definition.Section + "/" + s_hostEntry.Definition.Key] = s_hostEntry;
			}
			bool saveOnConfigSet = s_cfg.SaveOnConfigSet;
			s_cfg.SaveOnConfigSet = false;
			HostValuesActive = true;
			try
			{
				int num = p.ReadInt();
				for (int i = 0; i < num; i++)
				{
					string text2 = p.ReadString();
					string text3 = p.ReadString();
					if (!dictionary.TryGetValue(text2, out var value))
					{
						continue;
					}
					if (!s_local.ContainsKey(value))
					{
						s_local[value] = value.GetSerializedValue();
					}
					if (!(value.GetSerializedValue() == text3))
					{
						try
						{
							value.SetSerializedValue(text3);
						}
						catch (Exception ex)
						{
							s_log.LogWarning((object)("Host value '" + text3 + "' for " + text2 + " rejected: " + ex.Message));
						}
					}
				}
			}
			finally
			{
				s_cfg.SaveOnConfigSet = saveOnConfigSet;
			}
			s_log.LogInfo((object)("Using the host's settings (host runs version " + text + ")"));
			try
			{
				ConfigSync.Received?.Invoke(text);
			}
			catch (Exception ex2)
			{
				s_log.LogError((object)ex2);
			}
		}

		internal static void RestoreLocal()
		{
			s_peers.Clear();
			if (!HostValuesActive)
			{
				return;
			}
			HostValuesActive = false;
			bool saveOnConfigSet = s_cfg.SaveOnConfigSet;
			s_cfg.SaveOnConfigSet = false;
			try
			{
				foreach (KeyValuePair<ConfigEntryBase, string> item in s_local)
				{
					if (item.Key.GetSerializedValue() != item.Value)
					{
						item.Key.SetSerializedValue(item.Value);
					}
				}
			}
			finally
			{
				s_cfg.SaveOnConfigSet = saveOnConfigSet;
			}
			s_local.Clear();
		}

		private static void OnSettingChanged(object sender, SettingChangedEventArgs e)
		{
			if (!s_sendQueued && s_peers.Count != 0 && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer() && s_hostEntries.Contains(e.ChangedSetting))
			{
				s_sendQueued = true;
				((MonoBehaviour)s_plugin).StartCoroutine(SendSoon());
			}
		}

		private static IEnumerator SendSoon()
		{
			yield return (object)new WaitForSecondsRealtime(0.3f);
			s_sendQueued = false;
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || ZRoutedRpc.instance == null)
			{
				yield break;
			}
			s_peers.RemoveWhere((long uid) => ZNet.instance.GetPeer(uid) == null);
			foreach (long s_peer in s_peers)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(s_peer, s_rpcData, new object[1] { Pack() });
			}
		}

		private static void SetRaw(ConfigEntryBase e, object value)
		{
			Type type = ((object)e).GetType();
			if (!s_valueFields.TryGetValue(type, out var value2))
			{
				value2 = (s_valueFields[type] = type.GetField("_typedValue", BindingFlags.Instance | BindingFlags.NonPublic));
			}
			value2.SetValue(e, value);
		}

		internal static void SwapToLocal(ConfigFile file)
		{
			if (file != s_cfg || s_local.Count == 0 || s_setAside != null)
			{
				return;
			}
			s_setAside = new List<KeyValuePair<ConfigEntryBase, object>>();
			foreach (KeyValuePair<ConfigEntryBase, string> item in s_local)
			{
				s_setAside.Add(new KeyValuePair<ConfigEntryBase, object>(item.Key, item.Key.BoxedValue));
				SetRaw(item.Key, TomlTypeConverter.ConvertToValue(item.Value, item.Key.SettingType));
			}
		}

		internal static void SwapBack(ConfigFile file)
		{
			if (file != s_cfg || s_setAside == null)
			{
				return;
			}
			foreach (KeyValuePair<ConfigEntryBase, object> item in s_setAside)
			{
				SetRaw(item.Key, item.Value);
			}
			s_setAside = null;
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class ConfigSync_GameStart
	{
		private static void Postfix()
		{
			ConfigSync.RegisterRpcs();
		}
	}
	[HarmonyPatch(typeof(Game), "Shutdown")]
	internal static class ConfigSync_GameShutdown
	{
		private static void Postfix()
		{
			ConfigSync.RestoreLocal();
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class ConfigSync_PlayerSpawned
	{
		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				ConfigSync.RequestFromHost();
			}
		}
	}
	[HarmonyPatch(typeof(ConfigFile), "Save")]
	internal static class ConfigSync_Save
	{
		private static void Prefix(ConfigFile __instance)
		{
			ConfigSync.SwapToLocal(__instance);
		}

		private static Exception Finalizer(ConfigFile __instance, Exception __exception)
		{
			ConfigSync.SwapBack(__instance);
			return __exception;
		}
	}
}
namespace AirStrike
{
	internal static class Aim
	{
		private const string BomberCooldownKey = "AirStrike_LastCall";

		private const string HeliCooldownKey = "AirStrike_LastValkyries";

		private const float MarkerLift = 0.4f;

		private const int CircleSegments = 64;

		public static bool Active;

		private static StrikeMode s_mode = StrikeMode.Bombs;

		private static bool s_valid;

		private static Vector3 s_target;

		private static Vector3 s_dir;

		private static GameObject s_marker;

		private static LineRenderer s_outline;

		private static LineRenderer s_arrow;

		private static int s_aimMask;

		private static int s_groundMask;

		private static GUIStyle s_style;

		private static readonly List<Vector3> s_points = new List<Vector3>();

		private static readonly Color BombColor = new Color(1f, 0.15f, 0.1f, 0.9f);

		private static readonly Color NapalmColor = new Color(1f, 0.55f, 0.05f, 0.9f);

		private static readonly Color HeliColor = new Color(0.35f, 1f, 0.45f, 0.9f);

		private static readonly Color CooldownColor = new Color(0.65f, 0.65f, 0.65f, 0.9f);

		public static void Begin()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//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)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				return;
			}
			if (Active)
			{
				Cancel();
				return;
			}
			if (((Character)localPlayer).InInterior())
			{
				Show(Loc.T("$airstrike_indoors"));
				return;
			}
			if (InventoryGui.IsVisible())
			{
				InventoryGui.instance.Hide();
			}
			Active = true;
			s_valid = false;
			Sounds.PlayAt(Sounds.Horn, ((Component)localPlayer).transform.position + Vector3.up * 1.6f, 1f, 15f);
		}

		public static void Cancel()
		{
			Active = false;
			s_valid = false;
			if (Object.op_Implicit((Object)(object)s_marker))
			{
				s_marker.SetActive(false);
			}
		}

		private static void Show(string text)
		{
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true);
			}
		}

		private static string CooldownKey(StrikeMode mode)
		{
			if (mode != StrikeMode.Valkyries)
			{
				return "AirStrike_LastCall";
			}
			return "AirStrike_LastValkyries";
		}

		private static float CooldownLeft(Player p, StrikeMode mode)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !p.m_customData.TryGetValue(CooldownKey(mode), out var value))
			{
				return 0f;
			}
			if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return 0f;
			}
			double timeSeconds = ZNet.instance.GetTimeSeconds();
			if (timeSeconds < result)
			{
				return 0f;
			}
			float num = ((mode == StrikeMode.Valkyries) ? Cfg.HeliCooldown : Cfg.Cooldown);
			return (float)(result + (double)num - timeSeconds);
		}

		private static string FormatTime(float seconds)
		{
			int num = Mathf.CeilToInt(seconds);
			return $"{num / 60}:{num % 60:00}";
		}

		private static StrikeMode NextMode(StrikeMode m)
		{
			return m switch
			{
				StrikeMode.Napalm => StrikeMode.Valkyries, 
				StrikeMode.Bombs => StrikeMode.Napalm, 
				_ => StrikeMode.Bombs, 
			};
		}

		private static string ModeName(StrikeMode m)
		{
			return Loc.T(m switch
			{
				StrikeMode.Valkyries => "$airstrike_mode_valkyries", 
				StrikeMode.Napalm => "$airstrike_mode_napalm", 
				_ => "$airstrike_mode_bombs", 
			});
		}

		private static Color ModeColor(StrikeMode m)
		{
			//IL_0014: 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_0008: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(m switch
			{
				StrikeMode.Valkyries => HeliColor, 
				StrikeMode.Napalm => NapalmColor, 
				_ => BombColor, 
			});
		}

		public static void Update()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!Active)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InPlaceMode() || ((Character)localPlayer).IsTeleporting() || !Object.op_Implicit((Object)(object)GameCamera.instance) || InventoryGui.IsVisible() || Menu.IsVisible() || TextInput.IsVisible() || Minimap.IsOpen() || Console.IsVisible())
			{
				Cancel();
				return;
			}
			if (ZInput.GetKeyDown(Cfg.ModeKey, false))
			{
				s_mode = NextMode(s_mode);
			}
			UpdateTarget(localPlayer);
			UpdateMarker(localPlayer);
			if (ZInput.GetMouseButtonDown(1))
			{
				Cancel();
			}
			else if (ZInput.GetMouseButtonDown(0))
			{
				float num = CooldownLeft(localPlayer, s_mode);
				if (num > 0f)
				{
					Show(Loc.T("$airstrike_cooldown", FormatTime(num)));
				}
				else if (s_valid)
				{
					Confirm(localPlayer);
				}
				else
				{
					Show(Loc.T("$airstrike_no_target"));
				}
			}
		}

		private static void UpdateTarget(Player p)
		{
			//IL_0071: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			if (s_aimMask == 0)
			{
				s_aimMask = LayerMask.GetMask(new string[5] { "terrain", "piece", "static_solid", "Default", "Default_small" });
				s_groundMask = LayerMask.GetMask(new string[2] { "terrain", "piece" });
			}
			Transform transform = ((Component)GameCamera.instance).transform;
			s_valid = false;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(transform.position, transform.forward, ref val, Cfg.AimDistance + 30f, s_aimMask) && !(Vector3.Distance(((Component)p).transform.position, ((RaycastHit)(ref val)).point) > Cfg.AimDistance))
			{
				Vector3 val2 = ((RaycastHit)(ref val)).point - ((Component)p).transform.position;
				val2.y = 0f;
				if (((Vector3)(ref val2)).magnitude < 8f)
				{
					val2 = transform.forward;
					val2.y = 0f;
				}
				if (!(((Vector3)(ref val2)).sqrMagnitude < 0.001f))
				{
					s_target = ((RaycastHit)(ref val)).point;
					s_dir = ((Vector3)(ref val2)).normalized;
					s_valid = true;
				}
			}
		}

		private static Vector3 OnGround(Vector3 p)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(p + Vector3.up * 60f, Vector3.down, ref val, 200f, s_groundMask))
			{
				p.y = ((RaycastHit)(ref val)).point.y;
			}
			else if (Object.op_Implicit((Object)(object)ZoneSystem.instance))
			{
				p.y = ZoneSystem.instance.GetGroundHeight(p);
			}
			p.y = Mathf.Max(p.y, Floating.GetLiquidLevel(p, 1f, (LiquidType)10));
			return p + Vector3.up * 0.4f;
		}

		private static void AddEdge(Vector3 a, Vector3 b)
		{
			//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_0022: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(1, Mathf.CeilToInt(Vector3.Distance(a, b) / 2f));
			for (int i = 0; i < num; i++)
			{
				s_points.Add(OnGround(Vector3.Lerp(a, b, (float)i / (float)num)));
			}
		}

		private static void UpdateMarker(Player p)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00b8: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: 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_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: 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_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: 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_0138: 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_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: 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_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: 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_01aa: 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_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: 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_01c5: 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_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)s_marker))
			{
				s_marker = new GameObject("AirStrike_Marker");
				Object.DontDestroyOnLoad((Object)(object)s_marker);
				s_outline = Visuals.NewLine(s_marker.transform, "outline");
				s_arrow = Visuals.NewLine(s_marker.transform, "arrow");
			}
			s_marker.SetActive(s_valid);
			if (!s_valid)
			{
				return;
			}
			Vector3 val = Vector3.Cross(Vector3.up, s_dir);
			s_points.Clear();
			float num2;
			if (s_mode == StrikeMode.Valkyries)
			{
				float heliZone = Cfg.HeliZone;
				for (int i = 0; i <= 64; i++)
				{
					float num = (float)i * 2f * MathF.PI / 64f;
					s_points.Add(OnGround(s_target + new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * heliZone));
				}
				num2 = heliZone;
			}
			else
			{
				bool num3 = s_mode == StrikeMode.Napalm;
				num2 = (num3 ? Cfg.NapalmLength : Cfg.BombLength) / 2f;
				float num4 = (num3 ? Cfg.NapalmWidth : Cfg.BombWidth) / 2f;
				Vector3 val2 = s_target - s_dir * num2 - val * num4;
				Vector3 val3 = s_target + s_dir * num2 - val * num4;
				Vector3 val4 = s_target + s_dir * num2 + val * num4;
				Vector3 val5 = s_target - s_dir * num2 + val * num4;
				AddEdge(val2, val3);
				AddEdge(val3, val4);
				AddEdge(val4, val5);
				AddEdge(val5, val2);
				s_points.Add(s_points[0]);
			}
			s_outline.positionCount = s_points.Count;
			s_outline.SetPositions(s_points.ToArray());
			Vector3 val6 = s_target + s_dir * num2 * 0.6f;
			float num5 = Mathf.Min(4f, num2 * 0.3f);
			s_points.Clear();
			AddEdge(s_target - s_dir * num2 * 0.6f, val6);
			s_points.Add(OnGround(val6));
			s_points.Add(OnGround(val6 - s_dir * num5 - val * num5 * 0.7f));
			s_points.Add(OnGround(val6));
			s_points.Add(OnGround(val6 - s_dir * num5 + val * num5 * 0.7f));
			s_arrow.positionCount = s_points.Count;
			s_arrow.SetPositions(s_points.ToArray());
			Color val7 = ((CooldownLeft(p, s_mode) > 0f) ? CooldownColor : ModeColor(s_mode));
			LineRenderer[] array = (LineRenderer[])(object)new LineRenderer[2] { s_outline, s_arrow };
			foreach (LineRenderer obj in array)
			{
				obj.startColor = val7;
				obj.endColor = val7;
			}
		}

		private static void Confirm(Player p)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			StrikeData data = StrikeData.FromConfig(s_target, s_dir, s_mode, p.GetPlayerName());
			if (Object.op_Implicit((Object)(object)ZNet.instance))
			{
				p.m_customData[CooldownKey(s_mode)] = ZNet.instance.GetTimeSeconds().ToString(CultureInfo.InvariantCulture);
			}
			Cancel();
			Net.Call(data);
		}

		public static void OnGUI()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_00cb: 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_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			if (Active)
			{
				if (s_style == null)
				{
					s_style = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						fontStyle = (FontStyle)1
					};
				}
				s_style.fontSize = Mathf.RoundToInt(22f * (float)Screen.height / 1080f);
				Player localPlayer = Player.m_localPlayer;
				float num = (Object.op_Implicit((Object)(object)localPlayer) ? CooldownLeft(localPlayer, s_mode) : 0f);
				string text = Loc.T("$airstrike_mode", ModeName(s_mode));
				if (num > 0f)
				{
					text = text + " — " + Loc.T("$airstrike_mode_cooldown", FormatTime(num));
				}
				string text2 = Loc.T("$airstrike_aim_hint", ((object)Cfg.ModeKey/*cast due to .constrained prefix*/).ToString());
				float num2 = (float)Screen.height * 0.16f;
				float num3 = (float)s_style.fontSize * 1.6f;
				Label(new Rect(0f, num2, (float)Screen.width, num3), text, (num > 0f) ? CooldownColor : ModeColor(s_mode));
				Label(new Rect(0f, num2 + num3, (float)Screen.width, num3), text2, Color.white);
			}
		}

		private static void Label(Rect r, string text, Color color)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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)
			s_style.normal.textColor = new Color(0f, 0f, 0f, 0.85f);
			GUI.Label(new Rect(((Rect)(ref r)).x + 2f, ((Rect)(ref r)).y + 2f, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, s_style);
			s_style.normal.textColor = color;
			GUI.Label(r, text, s_style);
		}
	}
	internal static class Cfg
	{
		private static ConfigEntry<string> s_recipe;

		private static ConfigEntry<string> s_station;

		private static ConfigEntry<float> s_cooldown;

		private static ConfigEntry<float> s_aimDistance;

		private static ConfigEntry<KeyCode> s_modeKey;

		private static ConfigEntry<float> s_bombLength;

		private static ConfigEntry<float> s_bombWidth;

		private static ConfigEntry<int> s_bombCount;

		private static ConfigEntry<float> s_bombRadius;

		private static ConfigEntry<float> s_bombDamage;

		private static ConfigEntry<float> s_bombToolDamage;

		private static ConfigEntry<bool> s_craters;

		private static ConfigEntry<float> s_craterRadius;

		private static ConfigEntry<float> s_craterDepth;

		private static ConfigEntry<float> s_napalmLength;

		private static ConfigEntry<float> s_napalmWidth;

		private static ConfigEntry<int> s_canisterCount;

		private static ConfigEntry<float> s_napalmSeconds;

		private static ConfigEntry<float> s_napalmDamage;

		private static ConfigEntry<bool> s_fireSpread;

		private static ConfigEntry<float> s_fireSpreadMargin;

		private static ConfigEntry<float> s_fireSpreadSeconds;

		private static ConfigEntry<float> s_heliCooldown;

		private static ConfigEntry<float> s_heliZone;

		private static ConfigEntry<int> s_heliCount;

		private static ConfigEntry<float> s_heliOrbitSeconds;

		private static ConfigEntry<float> s_heliOrbitRadius;

		private static ConfigEntry<float> s_heliAltitude;

		private static ConfigEntry<float> s_heliSpeed;

		private static ConfigEntry<float> s_heliArrival;

		private static ConfigEntry<float> s_heliScale;

		private static ConfigEntry<float> s_gunDamage;

		private static ConfigEntry<float> s_gunHitChance;

		private static ConfigEntry<int> s_rockets;

		private static ConfigEntry<float> s_rocketDamage;

		private static ConfigEntry<bool> s_damagePlayers;

		private static ConfigEntry<bool> s_protectWards;

		private static ConfigEntry<float> s_altitude;

		private static ConfigEntry<float> s_speed;

		private static ConfigEntry<float> s_arrival;

		private static ConfigEntry<float> s_scale;

		private static ConfigEntry<float> s_musicVolume;

		private static ConfigEntry<float> s_voiceVolume;

		private static ConfigEntry<float> s_engineVolume;

		private static ConfigEntry<float> s_hearRadius;

		public static string Recipe => s_recipe.Value;

		public static string Station => s_station.Value;

		public static float Cooldown => Mathf.Max(0f, s_cooldown.Value);

		public static float AimDistance => Mathf.Clamp(s_aimDistance.Value, 10f, 500f);

		public static KeyCode ModeKey => s_modeKey.Value;

		public static float BombLength => Mathf.Clamp(s_bombLength.Value, 5f, 300f);

		public static float BombWidth => Mathf.Clamp(s_bombWidth.Value, 1f, 100f);

		public static int BombCount => Mathf.Clamp(s_bombCount.Value, 1, 60);

		public static float BombRadius => Mathf.Clamp(s_bombRadius.Value, 1f, 30f);

		public static float BombDamage => Mathf.Max(0f, s_bombDamage.Value);

		public static float BombToolDamage => Mathf.Max(0f, s_bombToolDamage.Value);

		public static bool Craters => s_craters.Value;

		public static float CraterRadius => Mathf.Clamp(s_craterRadius.Value, 1f, 15f);

		public static float CraterDepth => Mathf.Clamp(s_craterDepth.Value, 0.1f, 6f);

		public static float NapalmLength => Mathf.Clamp(s_napalmLength.Value, 5f, 300f);

		public static float NapalmWidth => Mathf.Clamp(s_napalmWidth.Value, 1f, 100f);

		public static int CanisterCount => Mathf.Clamp(s_canisterCount.Value, 1, 40);

		public static float NapalmSeconds => Mathf.Clamp(s_napalmSeconds.Value, 1f, 120f);

		public static float NapalmDamage => Mathf.Max(0f, s_napalmDamage.Value);

		public static bool FireSpread => s_fireSpread.Value;

		public static float FireSpreadMargin => Mathf.Clamp(s_fireSpreadMargin.Value, 0f, 200f);

		public static float FireSpreadSeconds => Mathf.Clamp(s_fireSpreadSeconds.Value, 0f, 1800f);

		public static float HeliCooldown => Mathf.Max(0f, s_heliCooldown.Value);

		public static float HeliZone => Mathf.Clamp(s_heliZone.Value, 5f, 100f);

		public static int HeliCount => Mathf.Clamp(s_heliCount.Value, 1, 8);

		public static float HeliOrbitSeconds => Mathf.Clamp(s_heliOrbitSeconds.Value, 5f, 180f);

		public static float HeliOrbitRadius => Mathf.Clamp(s_heliOrbitRadius.Value, 15f, 150f);

		public static float HeliAltitude => Mathf.Clamp(s_heliAltitude.Value, 10f, 150f);

		public static float HeliSpeed => Mathf.Clamp(s_heliSpeed.Value, 15f, 120f);

		public static float HeliArrival => Mathf.Clamp(s_heliArrival.Value, 4f, 60f);

		public static float HeliScale => Mathf.Clamp(s_heliScale.Value, 0.1f, 5f);

		public static float GunDamage => Mathf.Max(0f, s_gunDamage.Value);

		public static float GunHitChance => Mathf.Clamp01(s_gunHitChance.Value);

		public static int Rockets => Mathf.Clamp(s_rockets.Value, 0, 20);

		public static float RocketDamage => Mathf.Max(0f, s_rocketDamage.Value);

		public static bool DamagePlayers => s_damagePlayers.Value;

		public static bool ProtectWards => s_protectWards.Value;

		public static float Altitude => Mathf.Clamp(s_altitude.Value, 30f, 500f);

		public static float Speed => Mathf.Clamp(s_speed.Value, 10f, 400f);

		public static float Arrival => Mathf.Clamp(s_arrival.Value, 4f, 60f);

		public static float Scale => Mathf.Clamp(s_scale.Value, 0.05f, 5f);

		public static float MusicVolume => Mathf.Clamp01(s_musicVolume.Value);

		public static float VoiceVolume => Mathf.Clamp01(s_voiceVolume.Value);

		public static float EngineVolume => Mathf.Clamp01(s_engineVolume.Value);

		public static float HearRadius => Mathf.Max(0f, s_hearRadius.Value);

		private static AcceptableValueRange<float> Range(float min, float max)
		{
			return new AcceptableValueRange<float>(min, max);
		}

		private static AcceptableValueRange<int> Range(int min, int max)
		{
			return new AcceptableValueRange<int>(min, max);
		}

		public static void Bind(ConfigFile f)
		{
			ConfigSync.Section("Horn", "Рог");
			ConfigSync.Section("Bombs", "Бомбы");
			ConfigSync.Section("Napalm", "Напалм");
			ConfigSync.Section("Valkyries", "Вертолёты");
			ConfigSync.Section("Damage", "Урон");
			ConfigSync.Section("Bomber", "Бомбардировщик");
			ConfigSync.Section("Audio", "Звук");
			s_recipe = ConfigSync.Bind("Horn", "Recipe", "Bronze:5,SurtlingCore:3,HardAntler:1", "Рецепт рога", "Предметы для крафта боевого рога.", host: true);
			s_station = ConfigSync.Bind("Horn", "CraftingStation", "forge", "Станция для рога", "Префаб станции, на которой крафтится рог. Пусто — крафт с рук.", host: true);
			s_cooldown = ConfigSync.Bind("Horn", "CooldownSeconds", 300f, "Перезарядка удара, с", "Секунды (игрового времени), через которые тот же игрок может вызвать новый удар.", host: true, (AcceptableValueBase)(object)Range(0f, 3600f));
			s_aimDistance = ConfigSync.Bind("Horn", "MaxAimDistance", 150f, "Дальность прицела, м", "Как далеко можно отметить цель.", host: true, (AcceptableValueBase)(object)Range(10f, 500f));
			s_modeKey = ConfigSync.Bind<KeyCode>("Horn", "ToggleModeKey", (KeyCode)114, "Клавиша смены режима", "Во время прицеливания переключает бомбы, напалм и вертолёты.", host: false);
			s_bombLength = ConfigSync.Bind("Bombs", "StripLength", 60f, "Длина полосы, м", "Длина полосы ковровой бомбардировки.", host: true, (AcceptableValueBase)(object)Range(5f, 300f));
			s_bombWidth = ConfigSync.Bind("Bombs", "StripWidth", 16f, "Ширина полосы, м", "Ширина полосы ковровой бомбардировки.", host: true, (AcceptableValueBase)(object)Range(1f, 100f));
			s_bombCount = ConfigSync.Bind("Bombs", "BombCount", 14, "Бомб", "Сколько бомб падает вдоль полосы.", host: true, (AcceptableValueBase)(object)Range(1, 60));
			s_bombRadius = ConfigSync.Bind("Bombs", "BlastRadius", 6f, "Радиус взрыва, м", "Радиус взрыва одной бомбы. К краю урон слабеет.", host: true, (AcceptableValueBase)(object)Range(1f, 30f));
			s_bombDamage = ConfigSync.Bind("Bombs", "BlastDamage", 160f, "Урон взрыва", "Дробящий урон в центре взрыва.", host: true, (AcceptableValueBase)(object)Range(0f, 2000f));
			s_bombToolDamage = ConfigSync.Bind("Bombs", "ChopPickaxeDamage", 150f, "Урон по деревьям и камням", "Рубящий и кирочный урон в центре взрыва (деревья, камни, руда).", host: true, (AcceptableValueBase)(object)Range(0f, 2000f));
			s_craters = ConfigSync.Bind("Bombs", "Craters", defaultValue: true, "Воронки", "Бомбы оставляют воронки в земле.", host: true);
			s_craterRadius = ConfigSync.Bind("Bombs", "CraterRadius", 4f, "Радиус воронки, м", "Радиус воронки.", host: true, (AcceptableValueBase)(object)Range(1f, 15f), relog: false, restart: true);
			s_craterDepth = ConfigSync.Bind("Bombs", "CraterDepth", 1.6f, "Глубина воронки, м", "Глубина воронки в центре.", host: true, (AcceptableValueBase)(object)Range(0.1f, 6f), relog: false, restart: true);
			s_napalmLength = ConfigSync.Bind("Napalm", "StripLength", 50f, "Длина полосы, м", "Длина полосы напалма.", host: true, (AcceptableValueBase)(object)Range(5f, 300f));
			s_napalmWidth = ConfigSync.Bind("Napalm", "StripWidth", 12f, "Ширина полосы, м", "Ширина полосы напалма.", host: true, (AcceptableValueBase)(object)Range(1f, 100f));
			s_canisterCount = ConfigSync.Bind("Napalm", "CanisterCount", 8, "Баков", "Сколько баков с напалмом падает вдоль полосы.", host: true, (AcceptableValueBase)(object)Range(1, 40));
			s_napalmSeconds = ConfigSync.Bind("Napalm", "BurnSeconds", 15f, "Горение, с", "Сколько горит сам напалм.", host: true, (AcceptableValueBase)(object)Range(1f, 120f));
			s_napalmDamage = ConfigSync.Bind("Napalm", "FireDamage", 20f, "Урон огнём", "Урон огнём каждые полсекунды всему, что стоит в горящем напалме. Ещё и поджигает.", host: true, (AcceptableValueBase)(object)Range(0f, 500f));
			s_fireSpread = ConfigSync.Bind("Napalm", "FireSpread", defaultValue: true, "Огонь распространяется", "Напалм поджигает траву, деревья и деревянные постройки, и огонь расходится, как в Пепельных землях.", host: true);
			s_fireSpreadMargin = ConfigSync.Bind("Napalm", "FireSpreadMargin", 25f, "Огонь за полосой, м", "Насколько далеко за полосу может уйти огонь.", host: true, (AcceptableValueBase)(object)Range(0f, 200f));
			s_fireSpreadSeconds = ConfigSync.Bind("Napalm", "FireSpreadSeconds", 120f, "Огонь расходится, с", "Сколько секунд после удара огонь продолжает распространяться. Дождь тушит раньше.", host: true, (AcceptableValueBase)(object)Range(0f, 1800f));
			s_heliCooldown = ConfigSync.Bind("Valkyries", "CooldownSeconds", 600f, "Перезарядка вертолётов, с", "Секунды (игрового времени), через которые тот же игрок может снова вызвать вертолёты.", host: true, (AcceptableValueBase)(object)Range(0f, 3600f));
			s_heliZone = ConfigSync.Bind("Valkyries", "ZoneRadius", 25f, "Радиус зоны, м", "Радиус отмеченной зоны. Пулемётчики стреляют только по врагам внутри неё.", host: true, (AcceptableValueBase)(object)Range(5f, 100f));
			s_heliCount = ConfigSync.Bind("Valkyries", "Helicopters", 3, "Вертолётов", "Сколько вертолётов в звене.", host: true, (AcceptableValueBase)(object)Range(1, 8));
			s_heliOrbitSeconds = ConfigSync.Bind("Valkyries", "OrbitSeconds", 30f, "Кружат над зоной, с", "Сколько вертолёты кружат над зоной, прежде чем улететь.", host: true, (AcceptableValueBase)(object)Range(5f, 180f));
			s_heliOrbitRadius = ConfigSync.Bind("Valkyries", "OrbitRadius", 40f, "Радиус круга, м", "Радиус круга, по которому они летают над зоной.", host: true, (AcceptableValueBase)(object)Range(15f, 150f));
			s_heliAltitude = ConfigSync.Bind("Valkyries", "Altitude", 28f, "Высота, м", "Высота полёта над целью, пока кружат.", host: true, (AcceptableValueBase)(object)Range(10f, 150f));
			s_heliSpeed = ConfigSync.Bind("Valkyries", "Speed", 45f, "Скорость, м/с", "Скорость подлёта и отлёта.", host: true, (AcceptableValueBase)(object)Range(15f, 120f));
			s_heliArrival = ConfigSync.Bind("Valkyries", "ArrivalSeconds", 12f, "Подлёт, с", "Секунды от вызова до прибытия вертолётов к зоне.", host: true, (AcceptableValueBase)(object)Range(4f, 60f));
			s_heliScale = ConfigSync.Bind("Valkyries", "Scale", 1.35f, "Размер вертолёта", "Размер вертолёта. 1,35 — настоящий UH-1, около 13 м в длину.", host: true, (AcceptableValueBase)(object)Range(0.1f, 5f));
			s_gunDamage = ConfigSync.Bind("Valkyries", "GunDamage", 14f, "Урон пулемёта", "Колющий урон одной пули бортового пулемёта.", host: true, (AcceptableValueBase)(object)Range(0f, 500f));
			s_gunHitChance = ConfigSync.Bind("Valkyries", "GunHitChance", 0.55f, "Попадания пулемёта", "Доля пуль бортового пулемёта, которые попадают (0–1).", host: true, (AcceptableValueBase)(object)Range(0f, 1f));
			s_rockets = ConfigSync.Bind("Valkyries", "RocketsPerHelicopter", 4, "Ракет на вертолёт", "Сколько ракет выпускает каждый вертолёт, парами, по самым крепким врагам.", host: true, (AcceptableValueBase)(object)Range(0, 20));
			s_rocketDamage = ConfigSync.Bind("Valkyries", "RocketDamage", 120f, "Урон ракеты", "Дробящий урон в центре взрыва ракеты (радиус 4 м).", host: true, (AcceptableValueBase)(object)Range(0f, 2000f));
			s_damagePlayers = ConfigSync.Bind("Damage", "DamagePlayers", defaultValue: true, "Урон по игрокам", "Бомбы и напалм ранят и игроков, включая того, кто вызвал удар.", host: true);
			s_protectWards = ConfigSync.Bind("Damage", "ProtectWardedAreas", defaultValue: true, "Защита под вардом", "Внутри активного варда: постройки не повреждаются, нет воронок и огня. Существ там всё равно задевает.", host: true);
			s_altitude = ConfigSync.Bind("Bomber", "Altitude", 130f, "Высота, м", "Высота полёта над целью.", host: true, (AcceptableValueBase)(object)Range(30f, 500f));
			s_speed = ConfigSync.Bind("Bomber", "Speed", 70f, "Скорость, м/с", "Скорость полёта.", host: true, (AcceptableValueBase)(object)Range(10f, 400f));
			s_arrival = ConfigSync.Bind("Bomber", "ArrivalSeconds", 12f, "Подлёт, с", "Секунды от вызова до момента, когда бомбардировщик над целью.", host: true, (AcceptableValueBase)(object)Range(4f, 60f));
			s_scale = ConfigSync.Bind("Bomber", "Scale", 1f, "Размер бомбардировщика", "Размер бомбардировщика. 1 — настоящий B-2, размах крыльев 52 м.", host: true, (AcceptableValueBase)(object)Range(0.05f, 5f));
			s_musicVolume = ConfigSync.Bind("Audio", "MusicVolume", 0.68f, "Громкость музыки", "Громкость музыки удара (sounds/fortunate_son.*).", host: false, (AcceptableValueBase)(object)Range(0f, 1f));
			s_voiceVolume = ConfigSync.Bind("Audio", "VoiceVolume", 1f, "Громкость голоса", "Громкость фразы при вызове (sounds/good_morning.*).", host: false, (AcceptableValueBase)(object)Range(0f, 1f));
			s_engineVolume = ConfigSync.Bind("Audio", "EngineVolume", 1f, "Громкость моторов", "Громкость моторов бомбардировщика и падающих бомб.", host: false, (AcceptableValueBase)(object)Range(0f, 1f));
			s_hearRadius = ConfigSync.Bind("Audio", "MusicRadius", 300f, "Слышно в радиусе, м", "Игроки ближе этого расстояния к цели слышат фразу и музыку.", host: false, (AcceptableValueBase)(object)Range(0f, 1000f));
		}
	}
	internal static class Loc
	{
		public static string T(string token, params string[] args)
		{
			return Localization.instance.Localize(token, args);
		}
	}
	internal static class Net
	{
		private const string CallRpc = "AirStrike_Call";

		private const string FireRpc = "AirStrike_Fire";

		private const float SimulateDistance = 2000f;

		private static int s_pendingSeed;

		public static void Register()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.Register<ZPackage>("AirStrike_Call", (Action<long, ZPackage>)RPC_Call);
			}
			ZRoutedRpc instance2 = ZRoutedRpc.instance;
			if (instance2 != null)
			{
				instance2.Register<ZPackage>("AirStrike_Fire", (Action<long, ZPackage>)RPC_Fire);
			}
		}

		public static void Call(StrikeData data)
		{
			s_pendingSeed = data.Seed;
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "AirStrike_Call", new object[1] { data.Write() });
		}

		private static void RPC_Call(long sender, ZPackage pkg)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			StrikeData strikeData = StrikeData.Read(pkg);
			if (strikeData != null)
			{
				bool flag = strikeData.Seed == s_pendingSeed;
				if (flag)
				{
					s_pendingSeed = 0;
				}
				Player localPlayer = Player.m_localPlayer;
				if (Object.op_Implicit((Object)(object)localPlayer) && (flag || !(Vector3.Distance(((Component)localPlayer).transform.position, strikeData.Target) > 2000f)))
				{
					StrikeRunner.Begin(strikeData, flag);
				}
			}
		}

		public static void SendFire(int strike, int heli, int kind, int side, ZDOID target, Vector3 point, int rounds, int seed, float hitChance, float delay)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0023: 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)
			ZPackage val = new ZPackage();
			val.Write(strike);
			val.Write(heli);
			val.Write(kind);
			val.Write(side);
			val.Write(target);
			val.Write(point);
			val.Write(rounds);
			val.Write(seed);
			val.Write(hitChance);
			val.Write(delay);
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "AirStrike_Fire", new object[1] { val });
		}

		private static void RPC_Fire(long sender, ZPackage p)
		{
			//IL_002e: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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)
			ValkyrieRunner valkyrieRunner = ValkyrieRunner.Find(p.ReadInt());
			if (Object.op_Implicit((Object)(object)valkyrieRunner))
			{
				int heliIndex = p.ReadInt();
				int kind = p.ReadInt();
				bool right = p.ReadInt() == 1;
				ZDOID target = p.ReadZDOID();
				Vector3 point = p.ReadVector3();
				int rounds = p.ReadInt();
				int seed = p.ReadInt();
				float hitChance = p.ReadSingle();
				float delay = p.ReadSingle();
				valkyrieRunner.PlayFire(heliIndex, kind, right, target, point, rounds, seed, hitChance, delay);
			}
		}
	}
	internal static class Patches
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class ZNetScene_Awake
		{
			private static void Postfix(ZNetScene __instance)
			{
				Prefabs.RegisterInScene(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake
		{
			private static void Postfix(ObjectDB __instance)
			{
				Prefabs.RegisterInObjectDB(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class ObjectDB_CopyOtherDB
		{
			private static void Postfix(ObjectDB __instance)
			{
				Prefabs.RegisterInObjectDB(__instance);
			}
		}

		[HarmonyPatch(typeof(Game), "Start")]
		private static class Game_Start
		{
			private static void Postfix()
			{
				Net.Register();
				Plugin.ReloadSounds();
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		private static class Humanoid_UseItem
		{
			private static bool Prefix(Humanoid __instance, ItemData item)
			{
				if (item == null || item.m_shared.m_name != "$item_airstrike_horn")
				{
					return true;
				}
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					Aim.Begin();
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		private static class Player_SetControls
		{
			private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold)
			{
				if (Aim.Active && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					attack = (attackHold = (secondaryAttack = (secondaryAttackHold = (block = (blockHold = false)))));
				}
			}
		}

		[HarmonyPatch(typeof(Aoe), "ShouldHit")]
		private static class Aoe_ShouldHit
		{
			private static void Postfix(Aoe __instance, Collider collider, ref bool __result)
			{
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				if (!__result)
				{
					return;
				}
				StrikeAoe component = ((Component)__instance).GetComponent<StrikeAoe>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					return;
				}
				GameObject val = Projectile.FindHitObject(collider);
				if (Object.op_Implicit((Object)(object)val))
				{
					Character component2 = val.GetComponent<Character>();
					if (component.EnemiesOnly && Object.op_Implicit((Object)(object)component2) && !ValkyrieRunner.IsEnemy(component2))
					{
						__result = false;
					}
					else if (!Cfg.DamagePlayers && Object.op_Implicit((Object)(object)val.GetComponent<Player>()))
					{
						__result = false;
					}
					else if (Cfg.ProtectWards && Object.op_Implicit((Object)(object)val.GetComponent<WearNTear>()) && Wards.Inside(val.transform.position, 0f))
					{
						__result = false;
					}
				}
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static class CinderSpawner_CanSpawnCinder
		{
			private static void Postfix(Transform transform, ref bool __result)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if (!__result && Cfg.FireSpread && Object.op_Implicit((Object)(object)transform) && FireZones.Contains(transform.position))
				{
					__result = true;
				}
			}
		}

		[HarmonyPatch(typeof(Cinder), "CanBurn")]
		private static class Cinder_CanBurn
		{
			private static bool Prefix(Vector3 point, ref bool isTerrain, ref bool __result)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				if (!Cfg.ProtectWards || !FireZones.Contains(point) || !Wards.Inside(point, 0f))
				{
					return true;
				}
				isTerrain = false;
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(MusicMan), "UpdateMusic")]
		private static class MusicMan_UpdateMusic
		{
			private static void Postfix(MusicMan __instance)
			{
				if (Sounds.MusicPlaying)
				{
					AudioSource val = s_musicSource.Invoke(__instance);
					if (Object.op_Implicit((Object)(object)val))
					{
						val.volume = 0f;
					}
				}
			}
		}

		private static readonly FieldRef<MusicMan, AudioSource> s_musicSource = AccessTools.FieldRefAccess<MusicMan, AudioSource>("m_musicSource");
	}
	[BepInPlugin("oldma.valheim.airstrike", "AirStrike", "1.2.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "oldma.valheim.airstrike";

		public const string Version = "1.2.1";

		public const string MenuName = "Авиаудар";

		public const string MenuDescription = "Боевой рог: ковровая бомбардировка B-2, напалм и вертолёты «Валькирии». Неофициальный мод.";

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal static string Dir;

		private void Awake()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Dir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			ConfigSync.Init((BaseUnityPlugin)(object)this, "1.2.1");
			Cfg.Bind(((BaseUnityPlugin)this).Config);
			((BaseUnityPlugin)this).Config.SettingChanged += delegate
			{
				if (Object.op_Implicit((Object)(object)ObjectDB.instance) && ObjectDB.instance.m_items.Count > 0)
				{
					Prefabs.UpdateRecipe(ObjectDB.instance);
				}
			};
			new Harmony("oldma.valheim.airstrike").PatchAll(typeof(Plugin).Assembly);
			Lang.AddTokens();
			ReloadSounds();
			Log.LogInfo((object)"AirStrike 1.2.1 loaded");
		}

		internal static void ReloadSounds()
		{
			((MonoBehaviour)Instance).StartCoroutine(Sounds.Load(Path.Combine(Dir, "sounds")));
		}

		private void Update()
		{
			Aim.Update();
		}

		private void OnGUI()
		{
			Aim.OnGUI();
		}
	}
	public class StrikeAoe : MonoBehaviour
	{
		public bool EnemiesOnly;
	}
	internal static class Prefabs
	{
		public const string HornName = "AirStrike_Horn";

		public const string HornToken = "$item_airstrike_horn";

		public const string ExplosionName = "AirStrike_BombExplosion";

		public const string NapalmName = "AirStrike_Napalm";

		public const string CraterName = "AirStrike_Crater";

		public const string RocketExplosionName = "AirStrike_RocketExplosion";

		public const string SmallCraterName = "AirStrike_SmallCrater";

		public static GameObject Horn;

		public static GameObject Explosion;

		public static GameObject RocketExplosion;

		public static GameObject Napalm;

		public static GameObject Crater;

		public static GameObject SmallCrater;

		public static GameObject Fire;

		public static GameObject HouseFire;

		private static GameObject s_root;

		private static Recipe s_recipe;

		private static readonly FieldInfo s_namedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

		private static readonly FieldInfo s_itemByHash = AccessTools.Field(typeof(ObjectDB), "m_itemByHash");

		private static readonly FieldInfo s_terrainOpsByHash = AccessTools.Field(typeof(ObjectDB), "m_terrainOpsByHash");

		private static Transform Root
		{
			get
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				if (!Object.op_Implicit((Object)(object)s_root))
				{
					s_root = new GameObject("AirStrikePrefabs");
					Object.DontDestroyOnLoad((Object)(object)s_root);
					s_root.SetActive(false);
				}
				return s_root.transform;
			}
		}

		private static GameObject Clone(GameObject source, string name)
		{
			GameObject obj = Object.Instantiate<GameObject>(source, Root, false);
			((Object)obj).name = name;
			return obj;
		}

		public static void RegisterInScene(ZNetScene scene)
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)Horn))
				{
					Horn = BuildHorn(scene.GetPrefab("HardAntler"));
				}
				if (!Object.op_Implicit((Object)(object)Explosion))
				{
					Explosion = BuildExplosion(scene.GetPrefab("siegebomb_explosion"), scene.GetPrefab("fx_unstablelavarock_explosion"), "AirStrike_BombExplosion", 2.5f, 1.6f);
				}
				if (!Object.op_Implicit((Object)(object)RocketExplosion))
				{
					RocketExplosion = BuildExplosion(scene.GetPrefab("siegebomb_explosion"), scene.GetPrefab("fx_unstablelavarock_explosion"), "AirStrike_RocketExplosion", 1.2f, 0.8f);
					if (Object.op_Implicit((Object)(object)RocketExplosion))
					{
						RocketExplosion.GetComponent<StrikeAoe>().EnemiesOnly = true;
					}
				}
				if (!Object.op_Implicit((Object)(object)Napalm))
				{
					Napalm = BuildNapalm(scene.GetPrefab("Fader_DroppedFire_AOE"), scene.GetPrefab("fx_fireball_staff_explosion"), scene.GetPrefab("Fire"));
				}
				Fire = scene.GetPrefab("Fire");
				HouseFire = scene.GetPrefab("HouseFire");
				Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)s_namedPrefabs.GetValue(scene);
				GameObject[] array = (GameObject[])(object)new GameObject[4] { Horn, Explosion, RocketExplosion, Napalm };
				foreach (GameObject val in array)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						if (!scene.m_prefabs.Contains(val))
						{
							scene.m_prefabs.Add(val);
						}
						dictionary[StringExtensionMethods.GetStableHashCode(((Object)val).name)] = val;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to build prefabs: " + ex));
			}
		}

		public static void RegisterInObjectDB(ObjectDB db)
		{
			if (db.m_items.Count == 0)
			{
				return;
			}
			try
			{
				if (!Object.op_Implicit((Object)(object)Horn))
				{
					Horn = BuildHorn(db.GetItemPrefab("HardAntler"));
				}
				if (Object.op_Implicit((Object)(object)Horn) && !db.m_items.Contains(Horn))
				{
					db.m_items.Add(Horn);
					((Dictionary<int, GameObject>)s_itemByHash.GetValue(db))[StringExtensionMethods.GetStableHashCode(((Object)Horn).name)] = Horn;
				}
				UpdateRecipe(db);
				if (!Object.op_Implicit((Object)(object)Crater))
				{
					Crater = BuildCrater(db, "AirStrike_Crater", Cfg.CraterRadius, Cfg.CraterDepth);
				}
				if (!Object.op_Implicit((Object)(object)SmallCrater))
				{
					SmallCrater = BuildCrater(db, "AirStrike_SmallCrater", 2.2f, 0.7f);
				}
				Dictionary<int, TerrainOp> dictionary = (Dictionary<int, TerrainOp>)s_terrainOpsByHash.GetValue(db);
				GameObject[] array = (GameObject[])(object)new GameObject[2] { Crater, SmallCrater };
				foreach (GameObject val in array)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						TerrainOp component = val.GetComponent<TerrainOp>();
						if (!db.m_terrainOps.Contains(component))
						{
							db.m_terrainOps.Add(component);
						}
						dictionary[StringExtensionMethods.GetStableHashCode(((Object)val).name)] = component;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to register items: " + ex));
			}
		}

		internal static void UpdateRecipe(ObjectDB db)
		{
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)Horn))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)s_recipe))
			{
				s_recipe = ScriptableObject.CreateInstance<Recipe>();
				((Object)s_recipe).name = "Recipe_AirStrike_Horn";
				s_recipe.m_item = Horn.GetComponent<ItemDrop>();
				s_recipe.m_amount = 1;
				s_recipe.m_enabled = true;
			}
			if (!db.m_recipes.Contains(s_recipe))
			{
				db.m_recipes.Add(s_recipe);
			}
			s_recipe.m_craftingStation = null;
			string station = Cfg.Station;
			if (!string.IsNullOrEmpty(station))
			{
				foreach (Recipe recipe in db.m_recipes)
				{
					if (Object.op_Implicit((Object)(object)recipe) && Object.op_Implicit((Object)(object)recipe.m_craftingStation) && Utils.GetPrefabName(((Component)recipe.m_craftingStation).gameObject) == station)
					{
						s_recipe.m_craftingStation = recipe.m_craftingStation;
						break;
					}
				}
			}
			List<Requirement> list = new List<Requirement>();
			string[] array = Cfg.Recipe.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(':');
				if (array2.Length == 2 && int.TryParse(array2[1].Trim(), out var result))
				{
					GameObject itemPrefab = db.GetItemPrefab(array2[0].Trim());
					if (!Object.op_Implicit((Object)(object)itemPrefab))
					{
						Plugin.Log.LogWarning((object)("Horn recipe: unknown item " + array2[0]));
						continue;
					}
					list.Add(new Requirement
					{
						m_resItem = itemPrefab.GetComponent<ItemDrop>(),
						m_amount = result,
						m_recover = true
					});
				}
			}
			s_recipe.m_resources = list.ToArray();
		}

		private static GameObject BuildHorn(GameObject antler)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)antler))
			{
				return null;
			}
			GameObject val = Clone(antler, "AirStrike_Horn");
			ItemDrop component = val.GetComponent<ItemDrop>();
			SharedData shared = component.m_itemData.m_shared;
			shared.m_name = "$item_airstrike_horn";
			shared.m_description = "$item_airstrike_horn_desc";
			shared.m_itemType = (ItemType)16;
			shared.m_maxStackSize = 1;
			shared.m_weight = 2f;
			shared.m_value = 0;
			shared.m_teleportable = true;
			shared.m_questItem = false;
			if (shared.m_icons != null && shared.m_icons.Length != 0)
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { Tint(shared.m_icons[0], new Color(1f, 0.3f, 0.2f)) };
			}
			component.m_itemData.m_dropPrefab = val;
			return val;
		}

		private static void StripChildNetworking(GameObject go)
		{
			ZNetView[] componentsInChildren = go.GetComponentsInChildren<ZNetView>(true);
			foreach (ZNetView val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).gameObject != (Object)(object)go)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
			TimedDestruction[] componentsInChildren2 = go.GetComponentsInChildren<TimedDestruction>(true);
			foreach (TimedDestruction val2 in componentsInChildren2)
			{
				if ((Object)(object)((Component)val2).gameObject != (Object)(object)go)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
		}

		private static void ScaleEffects(Transform fx, float scale)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystem[] componentsInChildren = ((Component)fx).GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				MainModule main = componentsInChildren[i].main;
				((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
			}
			fx.localScale *= scale;
		}

		private static GameObject BuildExplosion(GameObject source, GameObject smoke, string name, float fireScale, float smokeScale)
		{
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)source))
			{
				return null;
			}
			GameObject val = Clone(source, name);
			if (Object.op_Implicit((Object)(object)smoke))
			{
				GameObject obj = Object.Instantiate<GameObject>(smoke, val.transform, false);
				((Object)obj).name = "smoke";
				ScaleEffects(obj.transform, smokeScale);
			}
			StripChildNetworking(val);
			Aoe component = val.GetComponent<Aoe>();
			component.m_useAttackSettings = false;
			component.m_spawnOnHitTerrain = null;
			component.m_hitTerrain = false;
			component.m_hitOwner = (component.m_hitSame = (component.m_hitFriendly = (component.m_hitEnemy = true)));
			component.m_hitCharacters = (component.m_hitProps = true);
			component.m_dodgeable = false;
			component.m_blockable = false;
			component.m_scaleDamageByDistance = true;
			component.m_distanceScaleCurve = AnimationCurve.Linear(0f, 1f, 1f, 0.25f);
			component.m_attackForce = 60f;
			component.m_launchCharacters = true;
			component.m_launchForceMinMax = new Vector2(5f, 9f);
			component.m_launchForceUpFactor = 0.85f;
			component.m_toolTier = 4;
			component.m_hitNoise = 100f;
			component.m_ttl = 6f;
			component.m_ttlMax = 0f;
			component.m_hitAfterTtl = false;
			component.m_hitInterval = 0f;
			val.AddComponent<StrikeAoe>();
			Transform val2 = val.transform.Find("fx_siegebomb_explosion");
			if (Object.op_Implicit((Object)(object)val2))
			{
				ScaleEffects(val2, fireScale);
			}
			return val;
		}

		private static GameObject BuildNapalm(GameObject source, GameObject burst, GameObject fire)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)source))
			{
				return null;
			}
			GameObject val = Clone(source, "AirStrike_Napalm");
			Transform val2 = val.transform.Find("Burning");
			if (Object.op_Implicit((Object)(object)val2))
			{
				Object.DestroyImmediate((Object)(object)((Component)val2).gameObject);
			}
			Light[] componentsInChildren = val.GetComponentsInChildren<Light>(true);
			foreach (Light obj in componentsInChildren)
			{
				obj.color = new Color(1f, 0.55f, 0.2f);
				obj.range = 14f;
			}
			Transform val3 = (Object.op_Implicit((Object)(object)fire) ? fire.transform.Find("Particles") : null);
			if (Object.op_Implicit((Object)(object)val3))
			{
				for (int j = 0; j < 3; j++)
				{
					Transform obj2 = Object.Instantiate<Transform>(val3, val.transform, false);
					((Object)obj2).name = "flames" + j;
					float num = (float)j * 120f * (MathF.PI / 180f);
					obj2.localPosition = new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * 1.8f;
					ScaleEffects(obj2, 2.5f);
				}
			}
			if (Object.op_Implicit((Object)(object)burst))
			{
				GameObject obj3 = Object.Instantiate<GameObject>(burst, val.transform, false);
				((Object)obj3).name = "burst";
				ScaleEffects(obj3.transform, 2.5f);
			}
			StripChildNetworking(val);
			Aoe component = val.GetComponent<Aoe>();
			component.m_useAttackSettings = false;
			component.m_hitOwner = (component.m_hitSame = (component.m_hitFriendly = (component.m_hitEnemy = true)));
			component.m_hitCharacters = (component.m_hitProps = true);
			component.m_dodgeable = false;
			component.m_blockable = false;
			component.m_ttlMax = 0f;
			val.AddComponent<StrikeAoe>();
			return val;
		}

		private static GameObject BuildCrater(ObjectDB db, string name, float radius, float depth)
		{
			//IL_0083: 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_00c1: Expected O, but got Unknown
			TerrainOp val = default(TerrainOp);
			if (!db.TryGetTerrainOp("digg_UnstableLavaRock", ref val))
			{
				return null;
			}
			GameObject obj = Clone(((Component)val).gameObject, name);
			TerrainOp component = obj.GetComponent<TerrainOp>();
			component.m_settings.m_raise = true;
			component.m_settings.m_raiseRadius = radius;
			component.m_settings.m_raisePower = 0.6f;
			component.m_settings.m_raiseDelta = 0f - depth;
			component.m_settings.m_level = false;
			component.m_settings.m_smooth = false;
			component.m_settings.m_paintCleared = true;
			component.m_settings.m_paintType = (PaintType)0;
			component.m_settings.m_paintRadius = radius + 1.5f;
			component.m_settings.m_paintStrength = 1f;
			component.m_settings.m_square = false;
			component.m_onPlacedEffect = new EffectList();
			component.m_spawnOnPlaced = null;
			return obj;
		}

		private static Sprite Tint(Sprite source, Color tint)
		{
			//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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00bc: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Rect textureRect = source.textureRect;
				int num = (int)((Rect)(ref textureRect)).width;
				int num2 = (int)((Rect)(ref textureRect)).height;
				Texture2D texture = source.texture;
				RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
				RenderTexture active = RenderTexture.active;
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
				val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				Color[] pixels = val.GetPixels();
				Color val3 = default(Color);
				for (int i = 0; i < pixels.Length; i++)
				{
					Color val2 = pixels[i];
					float num3 = val2.r * 0.3f + val2.g * 0.59f + val2.b * 0.11f;
					((Color)(ref val3))..ctor(num3 * tint.r * 1.35f, num3 * tint.g * 1.35f, num3 * tint.b * 1.35f, val2.a);
					pixels[i] = Color.Lerp(val2, val3, 0.75f);
				}
				val.SetPixels(pixels);
				val.Apply();
				((Object)val).name = "airstrike_horn_icon";
				Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), source.pixelsPerUnit);
				((Object)obj).name = "airstrike_horn_icon";
				return obj;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Icon tint failed, using original: " + ex.Message));
				return source;
			}
		}
	}
	internal static class Sounds
	{
		private class MusicPlayer : MonoBehaviour
		{
			private AudioSource m_voice;

			private AudioSource m_music;

			private float m_musicStart = -1f;

			private float m_stopAt;

			private float m_fade = 1f;

			private AudioClip m_next;

			public bool Playing
			{
				get
				{
					if (Object.op_Implicit((Object)(object)m_music))
					{
						return m_music.isPlaying;
					}
					return false;
				}
			}

			private void Awake()
			{
				m_voice = ((Component)this).gameObject.AddComponent<AudioSource>();
				m_music = ((Component)this).gameObject.AddComponent<AudioSource>();
				AudioSource[] array = (AudioSource[])(object)new AudioSource[2] { m_voice, m_music };
				foreach (AudioSource obj in array)
				{
					obj.spatialBlend = 0f;
					obj.playOnAwake = false;
					obj.loop = false;
				}
			}

			public void Begin(float seconds, AudioClip voice, AudioClip music)
			{
				float time = Time.time;
				if (Playing && (Object)(object)m_music.clip == (Object)(object)music)
				{
					m_stopAt = Mathf.Max(m_stopAt, time + seconds);
					m_fade = 1f;
					return;
				}
				m_stopAt = time + seconds;
				if (Object.op_Implicit((Object)(object)voice))
				{
					m_voice.outputAudioMixerGroup = Visuals.SfxMixer;
					m_voice.clip = voice;
					m_voice.volume = Cfg.VoiceVolume;
					m_voice.Play();
				}
				m_next = music;
				m_musicStart = (Object.op_Implicit((Object)(object)music) ? (time + (Object.op_Implicit((Object)(object)voice) ? (voice.length * 0.8f) : 0f)) : (-1f));
			}

			private void Update()
			{
				float time = Time.time;
				if (m_musicStart >= 0f && time >= m_musicStart)
				{
					m_musicStart = -1f;
					if (Object.op_Implicit((Object)(object)MusicMan.instance))
					{
						m_music.outputAudioMixerGroup = MusicMan.instance.m_musicMixer;
					}
					m_music.clip = m_next;
					m_fade = 1f;
					m_music.Play();
				}
				if (m_music.isPlaying)
				{
					if (time > m_stopAt)
					{
						m_fade -= Time.deltaTime / 4f;
					}
					m_music.volume = Cfg.MusicVolume * Mathf.Clamp01(m_fade);
					if (m_fade <= 0f)
					{
						m_music.Stop();
					}
				}
			}
		}

		private const int Rate = 44100;

		public static AudioClip Voice;

		public static AudioClip Music;

		public static AudioClip ValkyriesMusic;

		public static AudioClip RotorRecording;

		private static AudioClip s_engine;

		private static AudioClip s_rotor;

		private static AudioClip s_rocket;

		private static readonly Dictionary<int, AudioClip> s_bursts = new Dictionary<int, AudioClip>();

		private static AudioClip s_horn;

		private static readonly Dictionary<int, AudioClip> s_whistles = new Dictionary<int, AudioClip>();

		private static MusicPlayer s_player;

		public static bool MusicPlaying
		{
			get
			{
				if (Object.op_Implicit((Object)(object)s_player))
				{
					return s_player.Playing;
				}
				return false;
			}
		}

		public static AudioClip Engine
		{
			get
			{
				if (Object.op_Implicit((Object)(object)s_engine))
				{
					return s_engine;
				}
				int num = 264600;
				int num2 = 22050;
				float[] array = new float[num + num2];
				Random random = new Random(7);
				float num3 = 0f;
				float num4 = 0f;
				float num5 = 0f;
				for (int i = 0; i < array.Length; i++)
				{
					float num6 = (float)i / 44100f;
					float num7 = (float)(random.NextDouble() * 2.0 - 1.0);
					num3 = num3 * 0.995f + num7 * 0.05f;
					num4 += (num7 - num4) * 0.08f;
					num5 += (num4 - num5) * 0.08f;
					float num8 = Mathf.Sin(MathF.PI * 96f * num6) * 0.25f + Mathf.Sin(MathF.PI * 192f * num6 + 0.3f) * 0.15f + Mathf.Sin(MathF.PI * 288f * num6) * 0.07f;
					float num9 = Mathf.Sin(MathF.PI * 2f * (1250f + 8f * Mathf.Sin(1.8849558f * num6)) * num6) * 0.015f;
					array[i] = num3 * 1.6f + num5 * 1.8f + num8 * 0.35f + num9;
				}
				float[] array2 = new float[num];
				for (int j = 0; j < num; j++)
				{
					array2[j] = array[j];
				}
				for (int k = 0; k < num2; k++)
				{
					float num10 = (float)k / (float)num2;
					array2[k] = array[k] * num10 + array[num + k] * (1f - num10);
				}
				return s_engine = Clip("airstrike_engine", array2);
			}
		}

		public static AudioClip Horn
		{
			get
			{
				if (Object.op_Implicit((Object)(object)s_horn))
				{
					return s_horn;
				}
				float num = 2.6f;
				int num2 = (int)(44100f * num);
				float[] array = new float[num2];
				Random random = new Random(3);
				double num3 = 0.0;
				double num4 = 0.0;
				float num5 = 0f;
				for (int i = 0; i < num2; i++)
				{
					float num6 = (float)i / 44100f;
					float num7 = Mathf.Clamp01(num6 / 0.2f) * Mathf.Clamp01((num - num6) / 0.6f);
					float num8 = Mathf.Lerp(0.94f, 1f, Mathf.Clamp01(num6 / 0.25f));
					float num9 = 87.3f * num8 * (1f + 0.006f * Mathf.Sin(MathF.PI * 9f * num6));
					num3 += 6.2831854820251465 * (double)num9 / 44100.0;
					num4 += 6.2831854820251465 * (double)num9 * 1.5 / 44100.0;
					float num10 = 0f;
					for (int j = 1; j <= 12; j++)
					{
						float num11 = Mathf.Pow(num7, (float)j * 0.15f);
						num10 += (float)Math.Sin(num3 * (double)j) / Mathf.Pow((float)j, 1.1f) * num11;
						if (j <= 6)
						{
							num10 += (float)Math.Sin(num4 * (double)j) / Mathf.Pow((float)j, 1.2f) * num11 * 0.35f;
						}
					}
					num5 += ((float)(random.NextDouble() * 2.0 - 1.0) - num5) * 0.05f;
					array[i] = (num10 + num5 * 0.6f) * num7;
				}
				return s_horn = Clip("airstrike_horn", array);
			}
		}

		public static AudioClip Rotor
		{
			get
			{
				if (Object.op_Implicit((Object)(object)RotorRecording))
				{
					return RotorRecording;
				}
				if (Object.op_Implicit((Object)(object)s_rotor))
				{
					return s_rotor;
				}
				int num = 88200;
				float[] array = new float[num];
				Random random = new Random(5);
				float num2 = 0f;
				for (int i = 0; i < num; i++)
				{
					float num3 = (float)i / 44100f;
					float num4 = num3 * 11f % 1f / 11f;
					float num5 = (float)(random.NextDouble() * 2.0 - 1.0);
					num2 += (num5 - num2) * 0.06f;
					float num6 = Mathf.Exp((0f - num4) / 0.022f);
					float num7 = Mathf.Sin(MathF.PI * 132f * num4) * Mathf.Exp((0f - num4) / 0.035f);
					float num8 = Mathf.Sin(MathF.PI * 2200f * num3) * 0.012f + Mathf.Sin(MathF.PI * 4400f * num3) * 0.005f;
					array[i] = num2 * (0.35f + 2.2f * num6) + num7 * 0.55f + num8;
				}
				return s_rotor = Clip("airstrike_rotor", array);
			}
		}

		public static AudioClip Rocket
		{
			get
			{
				if (Object.op_Implicit((Object)(object)s_rocket))
				{
					return s_rocket;
				}
				int num = 70560;
				float[] array = new float[num];
				Random random = new Random(13);
				float num2 = 0f;
				for (int i = 0; i < num; i++)
				{
					float num3 = (float)i / 44100f;
					float num4 = (float)(random.NextDouble() * 2.0 - 1.0);
					num2 += (num4 - num2) * 0.3f;
					float num5 = num4 - num2;
					float num6 = num2 * Mathf.Exp((0f - num3) / 0.05f) * 1.5f;
					float num7 = (num5 * 0.6f + num2 * 0.4f) * Mathf.Clamp01(num3 / 0.05f) * Mathf.Exp((0f - num3) / 0.6f);
					array[i] = num6 + num7;
				}
				return s_rocket = Clip("airstrike_rocket", array);
			}
		}

		public static IEnumerator Load(string dir)
		{
			if (!Directory.Exists(dir))
			{
				try
				{
					Directory.CreateDirectory(dir);
					yield break;
				}
				catch
				{
					yield break;
				}
			}
			Voice = null;
			Music = null;
			ValkyriesMusic = null;
			RotorRecording = null;
			yield return LoadClip(dir, "good_morning", delegate(AudioClip c)
			{
				Voice = c;
			});
			yield return LoadClip(dir, "fortunate_son", delegate(AudioClip c)
			{
				Music = c;
			});
			yield return LoadClip(dir, "valkyries", delegate(AudioClip c)
			{
				ValkyriesMusic = c;
			});
			yield return LoadClip(dir, "rotor", delegate(AudioClip c)
			{
				RotorRecording = c;
			});
		}

		private static IEnumerator LoadClip(string dir, string name, Action<AudioClip> done)
		{
			string[] exts = new string[3] { ".ogg", ".wav", ".mp3" };
			AudioType[] array = new AudioType[3];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			AudioType[] types = (AudioType[])(object)array;
			for (int k = 0; k < exts.Length; k++)
			{
				string ext = exts[k];
				AudioType val = types[k];
				string path = Path.Combine(dir, name + ext);
				if (!File.Exists(path))
				{
					continue;
				}
				UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip("file:///" + path.Replace('\\', '/'), val);
				try
				{
					yield return req.SendWebRequest();
					if ((int)req.result != 1)
					{
						Plugin.Log.LogWarning((object)("Could not load " + path + ": " + req.error));
						continue;
					}
					AudioClip content = DownloadHandlerAudioClip.GetContent(req);
					((Object)content).name = name;
					done(content);
					Plugin.Log.LogInfo((object)$"Loaded {name}{ext} ({content.length:F1} s)");
					break;
				}
				finally
				{
					((IDisposable)req)?.Dispose();
				}
			}
		}

		private static AudioClip Clip(string name, float[] data)
		{
			float num = 0f;
			foreach (float num2 in data)
			{
				num = Mathf.Max(num, Mathf.Abs(num2));
			}
			if (num > 0f)
			{
				for (int j = 0; j < data.Length; j++)
				{
					data[j] *= 0.9f / num;
				}
			}
			AudioClip obj = AudioClip.Create(name, data.Length, 1, 44100, false);
			obj.SetData(data, 0);
			return obj;
		}

		public static AudioClip Whistle(float seconds)
		{
			int num = Mathf.RoundToInt(seconds * 10f);
			if (s_whistles.TryGetValue(num, out var value))
			{
				return value;
			}
			float num2 = (float)num / 10f;
			int num3 = Mathf.Max(1, (int)(44100f * num2));
			float[] array = new float[num3];
			Random random = new Random(11);
			double num4 = 0.0;
			for (int i = 0; i < num3; i++)
			{
				float num5 = (float)i / 44100f;
				float num6 = num5 / num2;
				float num7 = Mathf.Lerp(1500f, 550f, Mathf.Pow(num6, 0.8f)) * (1f + 0.01f * Mathf.Sin(MathF.PI * 12f * num5));
				num4 += 6.2831854820251465 * (double)num7 / 44100.0;
				float num8 = Mathf.Lerp(0.15f, 1f, num6) * Mathf.Clamp01(num5 * 8f);
				array[i] = (float)Math.Sin(num4) * num8 + (float)(random.NextDouble() * 2.0 - 1.0) * 0.03f * num8;
			}
			return s_whistles[num] = Clip("airstrike_whistle", array);
		}

		public static AudioClip GunBurst(int rounds, float interval)
		{
			int key = rounds * 1000 + Mathf.RoundToInt(interval * 1000f);
			if (s_bursts.TryGetValue(key, out var value))
			{
				return value;
			}
			int num = (int)(44100f * ((float)rounds * interval + 0.4f));
			float[] array = new float[num];
			Random random = new Random(9);
			for (int i = 0; i < rounds; i++)
			{
				int num2 = (int)((float)(44100 * i) * interval);
				float num3 = 0f;
				for (int j = num2; j < num; j++)
				{
					float num4 = (float)(j - num2) / 44100f;
					if (num4 > 0.35f)
					{
						break;
					}
					float num5 = (float)(random.NextDouble() * 2.0 - 1.0);
					num3 += (num5 - num3) * 0.25f;
					float num6 = num5 * Mathf.Exp((0f - num4) / 0.008f);
					float num7 = num3 * Mathf.Exp((0f - num4) / 0.045f);
					float num8 = Mathf.Sin(MathF.PI * 220f * num4) * Mathf.Exp((0f - num4) / 0.03f);
					float num9 = num3 * 0.25f * Mathf.Exp((0f - num4) / 0.12f);
					array[j] += num6 * 0.6f + num7 * 0.9f + num8 * 0.7f + num9;
				}
			}
			return s_bursts[key] = Clip("airstrike_gunburst", array);
		}

		public static void PlayAt(AudioClip clip, Vector3 pos, float volume, float minDistance)
		{
			//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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0037: Expected O, but got Unknown
			GameObject val = new GameObject("airstrike_sfx");
			val.transform.position = pos;
			Visuals.NewSource(val, clip, volume, minDistance, 300f, loop: false);
			Object.Destroy((Object)val, clip.length + 0.5f);
		}

		public static void PlayStrike(float seconds, AudioClip voice, AudioClip music)
		{
			//IL_0022: 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_002d: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)voice) || Object.op_Implicit((Object)(object)music))
			{
				if (!Object.op_Implicit((Object)(object)s_player))
				{
					GameObject val = new GameObject("AirStrikeMusic");
					Object.DontDestroyOnLoad((Object)val);
					s_player = val.AddComponent<MusicPlayer>();
				}
				s_player.Begin(seconds, voice, music);
			}
		}
	}
	internal enum StrikeMode
	{
		Bombs,
		Napalm,
		Valkyries
	}
	internal class StrikeData
	{
		public Vector3 Target;

		public Vector3 Dir;

		public StrikeMode Mode;

		public float Length;

		public float Width;

		public int Count;

		public float Speed;

		public float Altitude;

		public float Arrival;

		public float Duration;

		public int Seed;

		public string Caller;

		public static StrikeData FromConfig(Vector3 target, Vector3 dir, StrikeMode mode, string caller)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0014: 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)
			if (mode == StrikeMode.Valkyries)
			{
				return new StrikeData
				{
					Target = target,
					Dir = dir,
					Mode = mode,
					Length = Cfg.HeliOrbitRadius,
					Width = Cfg.HeliZone,
					Count = Cfg.HeliCount,
					Speed = Cfg.HeliSpeed,
					Altitude = Cfg.HeliAltitude,
					Arrival = Cfg.HeliArrival,
					Duration = Cfg.HeliOrbitSeconds,
					Seed = Random.Range(1, int.MaxValue),
					Caller = caller
				};
			}
			bool flag = mode == StrikeMode.Napalm;
			return new StrikeData
			{
				Target = target,
				Dir = dir,
				Mode = mode,
				Length = (flag ? Cfg.NapalmLength : Cfg.BombLength),
				Width = (flag ? Cfg.NapalmWidth : Cfg.BombWidth),
				Count = (flag ? Cfg.CanisterCount : Cfg.BombCount),
				Speed = Cfg.Speed,
				Altitude = Cfg.Altitude,
				Arrival = Cfg.Arrival,
				Seed = Random.Range(1, int.MaxValue),
				Caller = caller
			};
		}

		public ZPackage Write()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0018: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0054: 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_006c: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(2);
			val.Write(Target);
			val.Write(Dir);
			val.Write((int)Mode);
			val.Write(Length);
			val.Write(Width);
			val.Write(Count);
			val.Write(Speed);
			val.Write(Altitude);
			val.Write(Arrival);
			val.Write(Duration);
			val.Write(Seed);
			val.Write(Caller ?? "");
			return val;
		}

		public static StrikeData Read(ZPackage p)
		{
			//IL_0012: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (p.ReadInt() != 2)
			{
				return null;
			}
			return new StrikeData
			{
				Target = p.ReadVector3(),
				Dir = p.ReadVector3(),
				Mode = (StrikeMode)p.ReadInt(),
				Length = p.ReadSingle(),
				Width = p.ReadSingle(),
				Count = p.ReadInt(),
				Speed = p.ReadSingle(),
				Altitude = p.ReadSingle(),
				Arrival = p.ReadSingle(),
				Duration = p.ReadSingle(),
				Seed = p.ReadInt(),
				Caller = p.ReadString()
			};
		}
	}
	internal class StrikeRunner : MonoBehaviour
	{
		private class Drop
		{
			public float Along;

			public float Side;

			public float Release;

			public float Fall;

			public bool Released;

			public bool Landed;

			public bool Water;

			public bool OnTerrain;

			public Vector3 Start;

			public Vector3 Impact;

			public GameObject Model;

			public float Spin;
		}

		private const float Gravity = 20f;

		private const float FlyPast = 1100f;

		private static int s_impactMask;

		private StrikeData m_data;

		private bool m_authority;

		private float m_time;

		private float m_flightY;

		private float m_end;

		private Vector3 m_side;

		private GameObject m_bomber;

		private readonly List<Drop> m_drops = new List<Drop>();

		public static void Begin(StrikeData data, bool authority)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (data.Mode == StrikeMode.Valkyries)
			{
				ValkyrieRunner.Begin(data, authority);
			}
			else
			{
				new GameObject("AirStrike_Run").AddComponent<StrikeRunner>().Init(data, authority);
			}
		}

		private void Init(StrikeData data, bool authority)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: 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_0121: 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_0254: Unknown result type (might be due to invalid IL or missing references)
			if (s_impactMask == 0)
			{
				s_impact