Decompiled source of WarfareTweaks v1.0.0

WarfareTweaks.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WarfareTweaks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sighsorry")]
[assembly: AssemblyProduct("WarfareTweaks")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2D0FD9F5-0C44-4B03-B27D-E60BB6C0A7B7")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LocalizationManager
{
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, string>> LoadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> LocalizationLanguage;

		private static readonly List<WeakReference<Localization>> LocalizationObjects;

		private static readonly string[] FileExtensions;

		private static BaseUnityPlugin? _plugin;

		private static BaseUnityPlugin Plugin
		{
			get
			{
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Expected O, but got Unknown
				if ((Object)(object)_plugin == (Object)null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from type in ex.Types
							where type != null
							select type.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo type) => type.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(type)));
				}
				return _plugin;
			}
		}

		public static void Load()
		{
			_ = Plugin;
			if (Localization.instance != null)
			{
				LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage());
			}
		}

		public static void LoadLocalizationLater()
		{
			if (Localization.instance != null)
			{
				LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage());
			}
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!LocalizationLanguage.Remove(__instance))
			{
				LocalizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			LocalizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = FindLocalizationFiles();
			byte[] array = LoadTranslationFromAssembly("English");
			if (array == null)
			{
				Debug.LogWarning((object)("Found no English localizations in mod " + Plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."));
				return;
			}
			Dictionary<string, string> dictionary2 = DeserializeLocalizationText(Encoding.UTF8.GetString(array), "embedded English localization");
			if (dictionary2.Count == 0)
			{
				Debug.LogWarning((object)("Localization for mod " + Plugin.Info.Metadata.Name + " failed: English localization file was empty or invalid."));
				return;
			}
			string text = null;
			if (language != "English")
			{
				if (dictionary.TryGetValue(language, out var value))
				{
					text = File.ReadAllText(value);
				}
				else
				{
					byte[] array2 = LoadTranslationFromAssembly(language);
					if (array2 != null)
					{
						text = Encoding.UTF8.GetString(array2);
					}
				}
			}
			if (text == null && dictionary.TryGetValue("English", out var value2))
			{
				text = File.ReadAllText(value2);
			}
			if (text != null)
			{
				foreach (KeyValuePair<string, string> item in DeserializeLocalizationText(text, language + " localization"))
				{
					dictionary2[item.Key] = item.Value;
				}
			}
			LoadedTexts[language] = dictionary2;
			foreach (string key in dictionary2.Keys)
			{
				UpdateText(__instance, key);
			}
		}

		private static Dictionary<string, string> DeserializeLocalizationText(string localizationData, string sourceDescription)
		{
			try
			{
				return new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(localizationData) ?? new Dictionary<string, string>();
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to parse " + sourceDescription + " for mod " + Plugin.Info.Metadata.Name + ": " + ex.Message));
				return new Dictionary<string, string>();
			}
		}

		private static Dictionary<string, string> FindLocalizationFiles()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string pluginPath = Paths.PluginPath;
			if (!Directory.Exists(pluginPath))
			{
				return dictionary;
			}
			foreach (string item in from file in Directory.GetFiles(pluginPath, Plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where FileExtensions.Contains<string>(Path.GetExtension(file))
				select file)
			{
				string[] array = Path.GetFileNameWithoutExtension(item).Split('.');
				if (array.Length >= 2)
				{
					string text = array[1];
					if (dictionary.ContainsKey(text))
					{
						Debug.LogWarning((object)("Duplicate key " + text + " found for " + Plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
					}
					else
					{
						dictionary[text] = item;
					}
				}
			}
			return dictionary;
		}

		private static void UpdateText(Localization localization, string key)
		{
			LocalizationLanguage.TryGetValue(localization, out string value);
			if (LoadedTexts.TryGetValue(value, out Dictionary<string, string> value2) && value2.TryGetValue(key, out var value3))
			{
				localization.AddWord(key, value3);
			}
		}

		static Localizer()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			LoadedTexts = new Dictionary<string, Dictionary<string, string>>();
			LocalizationLanguage = new ConditionalWeakTable<Localization, string>();
			LocalizationObjects = new List<WeakReference<Localization>>();
			FileExtensions = new string[2] { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			string[] fileExtensions = FileExtensions;
			foreach (string text in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + text);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		private static byte[]? ReadEmbeddedFileBytes(string resourceFileName)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			using MemoryStream memoryStream = new MemoryStream();
			string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string name) => name.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				executingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
	public static class LocalizationManagerVersion
	{
		public const string Version = "1.4.0";
	}
}
namespace WarfareTweaks
{
	internal static class ChainLightningDedupSystem
	{
		internal readonly struct ChainUpdateScope
		{
			internal ChainLightningActivation? PreviousActivation { get; }

			internal ChainUpdateScope(ChainLightningActivation? previousActivation)
			{
				PreviousActivation = previousActivation;
			}
		}

		internal sealed class ChainLightningActivation
		{
			public int Id { get; }

			public float CreatedAt { get; }

			public int CreatedFrame { get; }

			public int SetupCount { get; set; }

			public HashSet<int> HitTargetIds { get; } = new HashSet<int>();

			public ChainLightningActivation(int id, float createdAt, int createdFrame)
			{
				Id = id;
				CreatedAt = createdAt;
				CreatedFrame = createdFrame;
			}
		}

		private sealed class ChainLightningAoeState
		{
			internal static readonly ChainLightningAoeState NotChainLightning = new ChainLightningAoeState(isChainLightning: false, 0);

			public bool IsChainLightning { get; }

			public int SourceId { get; }

			public ChainLightningActivation? Activation { get; set; }

			public ChainLightningAoeState(bool isChainLightning, int sourceId)
			{
				IsChainLightning = isChainLightning;
				SourceId = sourceId;
			}
		}

		private const float VanillaLightningDamage = 75f;

		private const float VanillaChainChancePerTarget = 0.3f;

		private static readonly ConditionalWeakTable<Aoe, ChainLightningAoeState> AoeStates = new ConditionalWeakTable<Aoe, ChainLightningAoeState>();

		private static bool _loggedVanillaRestore;

		private static int _nextActivationId;

		[ThreadStatic]
		private static ChainLightningActivation? ActiveActivation;

		internal static void RestoreVanillaChainLightningBehavior(ZNetScene scene)
		{
			GameObject val = (((Object)(object)scene != (Object)null) ? scene.GetPrefab("ChainLightning") : null);
			Aoe val2 = (((Object)(object)val != (Object)null) ? (val.GetComponent<Aoe>() ?? val.GetComponentInChildren<Aoe>(true)) : null);
			if (!((Object)(object)val2 == (Object)null))
			{
				bool num = !Mathf.Approximately(val2.m_damage.m_lightning, 75f) || !Mathf.Approximately(val2.m_chainChancePerTarget, 0.3f);
				val2.m_damage.m_lightning = 75f;
				val2.m_chainChancePerTarget = 0.3f;
				if (num && !_loggedVanillaRestore)
				{
					_loggedVanillaRestore = true;
					WarfareTweaksPlugin.ModLogger.LogInfo((object)"Restored vanilla ChainLightning damage and chain target chance after WarfareFireAndIce patch.");
				}
			}
		}

		internal static void TrackSetup(Aoe aoe, Character owner, ItemData item)
		{
			if (!((Object)(object)aoe == (Object)null) && TryGetChainLightningState(aoe, out ChainLightningAoeState state))
			{
				ChainLightningActivation? obj = ActiveActivation ?? new ChainLightningActivation(++_nextActivationId, Time.time, Time.frameCount);
				(state.Activation = obj).SetupCount++;
			}
		}

		internal static ChainUpdateScope BeginChainUpdate(Aoe aoe)
		{
			ChainLightningActivation? activeActivation = ActiveActivation;
			if ((Object)(object)aoe != (Object)null && TryGetChainLightningState(aoe, out ChainLightningAoeState state))
			{
				ActiveActivation = EnsureActivation(state);
			}
			return new ChainUpdateScope(activeActivation);
		}

		internal static void EndChainUpdate(ChainUpdateScope scope)
		{
			ActiveActivation = scope.PreviousActivation;
		}

		internal static bool ShouldAllowChainLightningHit(Aoe aoe, Collider collider)
		{
			if ((Object)(object)aoe == (Object)null || (Object)(object)collider == (Object)null)
			{
				return true;
			}
			if (!TryGetChainLightningState(aoe, out ChainLightningAoeState state))
			{
				return true;
			}
			Character val = TryGetHitCharacter(collider);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			int instanceID = ((Object)val).GetInstanceID();
			ChainLightningActivation chainLightningActivation = EnsureActivation(state);
			if (chainLightningActivation.HitTargetIds.Contains(instanceID))
			{
				return false;
			}
			chainLightningActivation.HitTargetIds.Add(instanceID);
			return true;
		}

		internal static void FilterChainLightningCandidate(Aoe aoe, Collider collider, ref bool result)
		{
			if (!result || (Object)(object)aoe == (Object)null || (Object)(object)collider == (Object)null || !TryGetChainLightningState(aoe, out ChainLightningAoeState state))
			{
				return;
			}
			ChainLightningActivation chainLightningActivation = state.Activation ?? ActiveActivation;
			if (chainLightningActivation != null)
			{
				Character val = TryGetHitCharacter(collider);
				if (!((Object)(object)val == (Object)null) && chainLightningActivation.HitTargetIds.Contains(((Object)val).GetInstanceID()))
				{
					result = false;
				}
			}
		}

		private static ChainLightningActivation EnsureActivation(ChainLightningAoeState state)
		{
			ChainLightningActivation chainLightningActivation = state.Activation;
			if (chainLightningActivation == null)
			{
				ChainLightningActivation? obj = ActiveActivation ?? new ChainLightningActivation(++_nextActivationId, Time.time, Time.frameCount);
				ChainLightningActivation chainLightningActivation2 = obj;
				state.Activation = obj;
				chainLightningActivation = chainLightningActivation2;
			}
			return chainLightningActivation;
		}

		private static Character? TryGetHitCharacter(Collider collider)
		{
			GameObject val = Projectile.FindHitObject(collider);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<Character>();
		}

		private static bool TryGetChainLightningState(Aoe aoe, out ChainLightningAoeState state)
		{
			state = ChainLightningAoeState.NotChainLightning;
			if (!CouldBeChainLightningAoe(aoe))
			{
				return false;
			}
			state = AoeStates.GetValue(aoe, CreateAoeState);
			return state.IsChainLightning;
		}

		private static ChainLightningAoeState CreateAoeState(Aoe aoe)
		{
			if (!TryResolveChainLightningSourceName(aoe, out string sourceName))
			{
				return ChainLightningAoeState.NotChainLightning;
			}
			return new ChainLightningAoeState(isChainLightning: true, StringExtensionMethods.GetStableHashCode(NormalizeSourceName(sourceName)));
		}

		private static bool TryResolveChainLightningSourceName(Aoe aoe, out string sourceName)
		{
			string name = ((Object)aoe).name;
			Transform transform = ((Component)aoe).transform;
			bool flag = ContainsChainLightningName(name);
			bool flag2 = (Object)(object)transform.root != (Object)null && ContainsChainLightningName(((Object)transform.root).name);
			bool flag3 = (Object)(object)transform.parent != (Object)null && ContainsChainLightningName(((Object)transform.parent).name);
			if (!flag && !flag2 && !flag3)
			{
				sourceName = "";
				return false;
			}
			sourceName = ((!flag && (Object)(object)transform.root != (Object)null) ? ((Object)transform.root).name : name);
			return true;
		}

		private static bool CouldBeChainLightningAoe(Aoe aoe)
		{
			if ((Object)(object)aoe == (Object)null)
			{
				return false;
			}
			if (ContainsChainLightningName(((Object)aoe).name))
			{
				return true;
			}
			if (aoe.m_chainStartChance <= 0f && aoe.m_chainChancePerTarget <= 0f && (Object)(object)aoe.m_chainObj == (Object)null)
			{
				return false;
			}
			if (ContainsChainLightningName(((Object)(object)aoe.m_chainObj != (Object)null) ? ((Object)aoe.m_chainObj).name : ""))
			{
				return true;
			}
			Transform transform = ((Component)aoe).transform;
			if (!((Object)(object)transform.root != (Object)null) || !ContainsChainLightningName(((Object)transform.root).name))
			{
				if ((Object)(object)transform.parent != (Object)null)
				{
					return ContainsChainLightningName(((Object)transform.parent).name);
				}
				return false;
			}
			return true;
		}

		private static bool ContainsChainLightningName(string value)
		{
			if (!string.IsNullOrWhiteSpace(value))
			{
				return value.IndexOf("ChainLightning", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static string NormalizeSourceName(string name)
		{
			return name.Replace("(Clone)", "", StringComparison.OrdinalIgnoreCase).Trim();
		}
	}
	[HarmonyPatch(typeof(Aoe), "OnHit", new Type[]
	{
		typeof(Collider),
		typeof(Vector3)
	})]
	internal static class AoeOnHitChainLightningDedupPatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(Aoe __instance, Collider collider, ref bool __result)
		{
			if (ChainLightningDedupSystem.ShouldAllowChainLightningHit(__instance, collider))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Aoe), "ShouldHit", new Type[] { typeof(Collider) })]
	internal static class AoeShouldHitChainLightningCandidatePatch
	{
		private static void Postfix(Aoe __instance, Collider collider, ref bool __result)
		{
			ChainLightningDedupSystem.FilterChainLightningCandidate(__instance, collider, ref __result);
		}
	}
	[HarmonyPatch(typeof(Aoe), "Setup")]
	internal static class AoeSetupChainLightningActivationPatch
	{
		private static void Postfix(Aoe __instance, Character owner, ItemData item)
		{
			ChainLightningDedupSystem.TrackSetup(__instance, owner, item);
		}
	}
	[HarmonyPatch(typeof(Aoe), "CustomFixedUpdate")]
	internal static class AoeCustomFixedUpdateChainLightningActivationPatch
	{
		private static void Prefix(Aoe __instance, out ChainLightningDedupSystem.ChainUpdateScope __state)
		{
			__state = ChainLightningDedupSystem.BeginChainUpdate(__instance);
		}

		private static void Postfix(ChainLightningDedupSystem.ChainUpdateScope __state)
		{
			ChainLightningDedupSystem.EndChainUpdate(__state);
		}
	}
	internal static class DirectWeaponHitContextSystem
	{
		internal readonly struct Scope
		{
			internal ScopeKind Kind { get; }

			internal Scope(ScopeKind kind)
			{
				Kind = kind;
			}
		}

		internal enum ScopeKind
		{
			None,
			DirectHit,
			CharacterDamage,
			CharacterDamageWithExternalDirectHit
		}

		private static int _directHitDepth;

		private static int _characterDamageDepth;

		private static string _weaponPrefabName = "";

		internal static bool IsDirectWeaponHitActive => _directHitDepth > 0;

		internal static bool ShouldCountWeaponEffectHit
		{
			get
			{
				if (_directHitDepth > 0 && _characterDamageDepth == 1)
				{
					return !WeaponEffectManager.IsApplyingGeneratedEffectDamage;
				}
				return false;
			}
		}

		internal static Scope BeginAttackHit(Attack attack)
		{
			if ((Object)(object)attack?.m_character != (Object)(object)Player.m_localPlayer)
			{
				return default(Scope);
			}
			_weaponPrefabName = GetWeaponPrefabName(attack.m_weapon);
			_directHitDepth++;
			return new Scope(ScopeKind.DirectHit);
		}

		internal static Scope BeginProjectileHit(Projectile projectile)
		{
			if ((Object)(object)projectile == (Object)null || (Object)(object)ProjectileAccess.GetOwner(projectile) != (Object)(object)Player.m_localPlayer || WarfareTweaksBridge.ShouldSuppressProjectile(projectile))
			{
				return default(Scope);
			}
			_weaponPrefabName = GetWeaponPrefabName(ProjectileAccess.GetWeapon(projectile));
			_directHitDepth++;
			return new Scope(ScopeKind.DirectHit);
		}

		internal static Scope BeginCharacterDamage()
		{
			_characterDamageDepth++;
			if (_directHitDepth == 0 && WarfareTweaksBridge.TryGetCaptainValheimShieldHitWeaponPrefabName(out string weaponPrefabName))
			{
				_weaponPrefabName = weaponPrefabName;
				_directHitDepth++;
				return new Scope(ScopeKind.CharacterDamageWithExternalDirectHit);
			}
			return new Scope(ScopeKind.CharacterDamage);
		}

		internal static bool TryGetCurrentProjectileWeaponPrefabName(out string prefabName)
		{
			prefabName = _weaponPrefabName;
			if (_directHitDepth > 0)
			{
				return !string.IsNullOrWhiteSpace(prefabName);
			}
			return false;
		}

		private static string GetWeaponPrefabName(ItemData? weapon)
		{
			if (!((Object)(object)weapon?.m_dropPrefab != (Object)null))
			{
				return "";
			}
			return ((Object)weapon.m_dropPrefab).name;
		}

		internal static void End(Scope scope)
		{
			switch (scope.Kind)
			{
			case ScopeKind.DirectHit:
				if (_directHitDepth > 0)
				{
					_directHitDepth--;
					if (_directHitDepth == 0)
					{
						_weaponPrefabName = "";
					}
				}
				break;
			case ScopeKind.CharacterDamage:
				if (_characterDamageDepth > 0)
				{
					_characterDamageDepth--;
				}
				break;
			case ScopeKind.CharacterDamageWithExternalDirectHit:
				if (_characterDamageDepth > 0)
				{
					_characterDamageDepth--;
				}
				if (_directHitDepth > 0)
				{
					_directHitDepth--;
					if (_directHitDepth == 0)
					{
						_weaponPrefabName = "";
					}
				}
				break;
			}
		}
	}
	[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
	internal static class AttackDoMeleeAttackDirectWeaponHitPatch
	{
		[HarmonyPriority(800)]
		private static void Prefix(Attack __instance, out DirectWeaponHitContextSystem.Scope __state)
		{
			__state = DirectWeaponHitContextSystem.BeginAttackHit(__instance);
		}

		[HarmonyPriority(800)]
		private static void Postfix(DirectWeaponHitContextSystem.Scope __state)
		{
			DirectWeaponHitContextSystem.End(__state);
		}
	}
	[HarmonyPatch(typeof(Attack), "DoAreaAttack")]
	internal static class AttackDoAreaAttackDirectWeaponHitPatch
	{
		[HarmonyPriority(800)]
		private static void Prefix(Attack __instance, out DirectWeaponHitContextSystem.Scope __state)
		{
			__state = DirectWeaponHitContextSystem.BeginAttackHit(__instance);
		}

		[HarmonyPriority(800)]
		private static void Postfix(DirectWeaponHitContextSystem.Scope __state)
		{
			DirectWeaponHitContextSystem.End(__state);
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class CharacterDamageDirectWeaponHitDepthPatch
	{
		[HarmonyPriority(800)]
		private static void Prefix(out DirectWeaponHitContextSystem.Scope __state)
		{
			__state = DirectWeaponHitContextSystem.BeginCharacterDamage();
		}

		[HarmonyPriority(0)]
		private static void Postfix(DirectWeaponHitContextSystem.Scope __state)
		{
			DirectWeaponHitContextSystem.End(__state);
		}
	}
	internal static class ProjectileAccess
	{
		private static readonly FieldRef<Projectile, ItemData>? WeaponRef = CreateFieldRef<ItemData>("m_weapon");

		private static readonly FieldRef<Projectile, ItemData>? AmmoRef = CreateFieldRef<ItemData>("m_ammo");

		private static readonly FieldRef<Projectile, Character>? OwnerRef = CreateFieldRef<Character>("m_owner");

		private static readonly FieldRef<Projectile, HitData>? OriginalHitDataRef = CreateFieldRef<HitData>("m_originalHitData");

		private static readonly FieldRef<Projectile, int>? StatusEffectHashRef = CreateFieldRef<int>("m_statusEffectHash");

		private static readonly FieldRef<Projectile, Vector3>? VelocityRef = CreateFieldRef<Vector3>("m_vel");

		private static readonly FieldRef<Projectile, bool>? DidHitRef = CreateFieldRef<bool>("m_didHit");

		private static readonly FieldInfo? WeaponField = AccessTools.Field(typeof(Projectile), "m_weapon");

		private static readonly FieldInfo? AmmoField = AccessTools.Field(typeof(Projectile), "m_ammo");

		private static readonly FieldInfo? OwnerField = AccessTools.Field(typeof(Projectile), "m_owner");

		private static readonly FieldInfo? OriginalHitDataField = AccessTools.Field(typeof(Projectile), "m_originalHitData");

		private static readonly FieldInfo? StatusEffectHashField = AccessTools.Field(typeof(Projectile), "m_statusEffectHash");

		private static readonly FieldInfo? VelocityField = AccessTools.Field(typeof(Projectile), "m_vel");

		private static readonly FieldInfo? DidHitField = AccessTools.Field(typeof(Projectile), "m_didHit");

		internal static ItemData? GetWeapon(Projectile projectile)
		{
			if (WeaponRef == null)
			{
				object? obj = WeaponField?.GetValue(projectile);
				return (ItemData?)((obj is ItemData) ? obj : null);
			}
			return WeaponRef.Invoke(projectile);
		}

		internal static ItemData? GetAmmo(Projectile projectile)
		{
			if (AmmoRef == null)
			{
				object? obj = AmmoField?.GetValue(projectile);
				return (ItemData?)((obj is ItemData) ? obj : null);
			}
			return AmmoRef.Invoke(projectile);
		}

		internal static Character? GetOwner(Projectile projectile)
		{
			if (OwnerRef == null)
			{
				object? obj = OwnerField?.GetValue(projectile);
				return (Character?)((obj is Character) ? obj : null);
			}
			return OwnerRef.Invoke(projectile);
		}

		internal static HitData? GetOriginalHitData(Projectile projectile)
		{
			if (OriginalHitDataRef == null)
			{
				object? obj = OriginalHitDataField?.GetValue(projectile);
				return (HitData?)((obj is HitData) ? obj : null);
			}
			return OriginalHitDataRef.Invoke(projectile);
		}

		internal static int GetStatusEffectHash(Projectile projectile)
		{
			if (StatusEffectHashRef == null)
			{
				object obj = StatusEffectHashField?.GetValue(projectile);
				if (obj is int)
				{
					return (int)obj;
				}
				return 0;
			}
			return StatusEffectHashRef.Invoke(projectile);
		}

		internal static Vector3 GetVelocity(Projectile projectile)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (VelocityRef == null)
			{
				object obj = VelocityField?.GetValue(projectile);
				if (obj is Vector3)
				{
					return (Vector3)obj;
				}
				return Vector3.zero;
			}
			return VelocityRef.Invoke(projectile);
		}

		internal static void SetVelocity(Projectile projectile, Vector3 velocity)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			if (VelocityRef != null)
			{
				VelocityRef.Invoke(projectile) = velocity;
			}
			else
			{
				VelocityField?.SetValue(projectile, velocity);
			}
		}

		internal static void SetDidHit(Projectile projectile, bool didHit)
		{
			if (DidHitRef != null)
			{
				DidHitRef.Invoke(projectile) = didHit;
			}
			else
			{
				DidHitField?.SetValue(projectile, didHit);
			}
		}

		private static FieldRef<Projectile, T>? CreateFieldRef<T>(string fieldName)
		{
			try
			{
				return AccessTools.FieldRefAccess<Projectile, T>(fieldName);
			}
			catch
			{
				return null;
			}
		}
	}
	internal static class WarfareEffectConfigHelpers
	{
		internal static bool IsWarfareEffectConfig(EffectBehaviorConfig effectConfig)
		{
			string text = effectConfig.Type?.Trim() ?? "";
			if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, "warfare", StringComparison.OrdinalIgnoreCase) && !string.Equals(text, "chainLightning", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(text, "chainLightningMistlands", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		internal static bool HasPrefabAssignment(EffectBehaviorConfig effectConfig, string prefabName)
		{
			if (effectConfig.Prefabs == null || string.IsNullOrWhiteSpace(prefabName))
			{
				return false;
			}
			return effectConfig.Prefabs.Keys.Any((string configuredPrefabName) => string.Equals(configuredPrefabName?.Trim(), prefabName, StringComparison.OrdinalIgnoreCase));
		}
	}
	internal static class WarfareTweaksLocalization
	{
		internal const string EffectAdrenaline = "$wt_effect_adrenaline";

		internal const string EffectBash = "$wt_effect_bash";

		internal const string EffectBleeding = "$wt_effect_bleeding";

		internal const string EffectBleedingSecondary = "$wt_effect_bleeding_secondary";

		internal const string EffectBurningSecondary = "$wt_effect_burning_secondary";

		internal const string EffectDecapitator = "$wt_effect_decapitator";

		internal const string EffectExecutioner = "$wt_effect_executioner";

		internal const string EffectHackAndSlash = "$wt_effect_hack_and_slash";

		internal const string EffectHaste = "$wt_effect_haste";

		internal const string EffectImpale = "$wt_effect_impale";

		internal const string EffectPiercer = "$wt_effect_piercer";

		internal const string EffectLightningBurst = "$wt_effect_lightning_burst";

		internal const string EffectPinning = "$wt_effect_pinning";

		internal const string EffectPiercingGreatbow = "$wt_effect_piercing_greatbow";

		internal const string EffectSmasher = "$wt_effect_smasher";

		internal const string EffectSmashAndBash = "$wt_effect_smash_and_bash";

		internal const string EffectBludgeoner = "$wt_effect_bludgeoner";

		internal const string EffectVampirism = "$wt_effect_vampirism";

		internal const string EffectFallback = "$wt_effect_fallback";

		internal const string DamageBlunt = "$wt_damage_blunt";

		internal const string DamageFire = "$wt_damage_fire";

		internal const string DamageFrost = "$wt_damage_frost";

		internal const string DamageLightning = "$wt_damage_lightning";

		internal const string DamagePierce = "$wt_damage_pierce";

		internal const string DamageSlash = "$wt_damage_slash";

		internal const string TooltipAdrenalineValue = "$wt_tooltip_adrenaline_value";

		internal const string TooltipAdrenaline = "$wt_tooltip_adrenaline";

		internal const string TooltipHaste = "$wt_tooltip_haste";

		internal const string TooltipVampirismValue = "$wt_tooltip_vampirism_value";

		internal const string TooltipVampirism = "$wt_tooltip_vampirism";

		internal const string TooltipDotValue = "$wt_tooltip_dot_value";

		internal const string TooltipDot = "$wt_tooltip_dot";

		internal const string TooltipBashValue = "$wt_tooltip_bash_value";

		internal const string TooltipBash = "$wt_tooltip_bash";

		internal const string TooltipExecutionerValue = "$wt_tooltip_executioner_value";

		internal const string TooltipExecutioner = "$wt_tooltip_executioner";

		internal const string TooltipResistanceWeakness = "$wt_tooltip_resistance_weakness";

		internal const string TooltipFixedExtraDamageValue = "$wt_tooltip_fixed_extra_damage_value";

		internal const string TooltipFixedExtraDamage = "$wt_tooltip_fixed_extra_damage";

		internal const string TooltipPinningValue = "$wt_tooltip_pinning_value";

		internal const string TooltipPinning = "$wt_tooltip_pinning";

		internal const string TooltipFallbackValue = "$wt_tooltip_fallback_value";

		internal const string TooltipFallback = "$wt_tooltip_fallback";

		internal static void Load()
		{
			Localizer.Load();
		}

		internal static string Localize(string token, string fallback)
		{
			if (Localization.instance == null)
			{
				return fallback;
			}
			string text = Localization.instance.Localize(token);
			if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, token, StringComparison.Ordinal))
			{
				return text;
			}
			return fallback;
		}

		internal static string Format(string token, string fallback, params object[] args)
		{
			string format = Localize(token, fallback);
			try
			{
				return string.Format(CultureInfo.InvariantCulture, format, args);
			}
			catch (FormatException)
			{
				return string.Format(CultureInfo.InvariantCulture, fallback, args);
			}
		}
	}
	internal static class WarfareTweaksBridge
	{
		private delegate bool ShouldSuppressProjectileDelegate(Projectile projectile);

		private delegate bool IsGeneratedDamageActiveDelegate();

		private delegate bool TryGetWeaponPrefabNameDelegate(out string weaponPrefabName);

		private const string SecondaryAttacksBridgeTypeName = "SecondaryAttacks.WarfareTweaksBridge, SecondaryAttacks";

		private const string CaptainValheimBridgeTypeName = "CaptainValheim.WarfareTweaksBridge, CaptainValheim";

		private static ShouldSuppressProjectileDelegate? _shouldSuppressProjectile;

		private static IsGeneratedDamageActiveDelegate? _isGeneratedDamageActive;

		private static TryGetWeaponPrefabNameDelegate? _tryGetCaptainValheimShieldHitWeaponPrefabName;

		private static bool _resolved;

		internal static bool IsExternalGeneratedDamageActive
		{
			get
			{
				EnsureResolved();
				return _isGeneratedDamageActive?.Invoke() ?? false;
			}
		}

		internal static bool ShouldSuppressProjectile(Projectile projectile)
		{
			EnsureResolved();
			return _shouldSuppressProjectile?.Invoke(projectile) ?? false;
		}

		internal static bool TryGetCaptainValheimShieldHitWeaponPrefabName(out string weaponPrefabName)
		{
			weaponPrefabName = "";
			EnsureResolved();
			if (_tryGetCaptainValheimShieldHitWeaponPrefabName == null)
			{
				return false;
			}
			if (!_tryGetCaptainValheimShieldHitWeaponPrefabName(out var weaponPrefabName2) || string.IsNullOrWhiteSpace(weaponPrefabName2))
			{
				return false;
			}
			weaponPrefabName = weaponPrefabName2;
			return true;
		}

		private static void EnsureResolved()
		{
			if (!_resolved)
			{
				_resolved = true;
				Type type = Type.GetType("SecondaryAttacks.WarfareTweaksBridge, SecondaryAttacks", throwOnError: false);
				Type type2 = Type.GetType("CaptainValheim.WarfareTweaksBridge, CaptainValheim", throwOnError: false);
				if (type != null)
				{
					_shouldSuppressProjectile = CreateStaticDelegate<ShouldSuppressProjectileDelegate>(type.GetMethod("ShouldSuppressProjectile", BindingFlags.Static | BindingFlags.Public));
					_isGeneratedDamageActive = CreateStaticDelegate<IsGeneratedDamageActiveDelegate>(type.GetProperty("IsGeneratedDamageActive", BindingFlags.Static | BindingFlags.Public)?.GetGetMethod());
				}
				if (type2 != null)
				{
					_tryGetCaptainValheimShieldHitWeaponPrefabName = CreateStaticDelegate<TryGetWeaponPrefabNameDelegate>(type2.GetMethod("TryGetShieldHitWeaponPrefabName", BindingFlags.Static | BindingFlags.Public));
				}
			}
		}

		private static TDelegate? CreateStaticDelegate<TDelegate>(MethodInfo? method) where TDelegate : class
		{
			if (method == null)
			{
				return null;
			}
			try
			{
				return Delegate.CreateDelegate(typeof(TDelegate), method, throwOnBindFailure: false) as TDelegate;
			}
			catch
			{
				return null;
			}
		}
	}
	internal static class WarfareTweaksCompat
	{
		internal const string WarfareGuid = "Therzie.Warfare";

		internal const string WarfareFireAndIceGuid = "Therzie.WarfareFireAndIce";

		internal const string JewelcraftingGuid = "org.bepinex.plugins.jewelcrafting";
	}
	internal static class WarfareTweaksConfigLoader
	{
		private static readonly Dictionary<string, string> PrefabScalarFields = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			["adrenaline"] = "staminaRestore.value",
			["bash"] = "value",
			["bleeding"] = "damageFactor",
			["bleedingSecondary"] = "damageFactor",
			["bleeding_secondary"] = "damageFactor",
			["burningSecondary"] = "damageFactor",
			["burning_secondary"] = "damageFactor",
			["executioner"] = "value",
			["haste"] = "moveSpeedMultiplier",
			["impale"] = "damageFactor",
			["lightningBurst"] = "value",
			["pinning"] = "value",
			["pierceGreatbow"] = "value",
			["pierceGreatbowFireAndIce"] = "value",
			["piercingGreatbowFireAndIce"] = "value",
			["piercingGreatbowMistlands"] = "value",
			["piercingGreatbowModer"] = "value",
			["piercingGreatbowPlains"] = "value",
			["vampirism"] = "value"
		};

		private static readonly IDeserializer Deserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();

		internal static void EnsureLocalFileExists()
		{
			Directory.CreateDirectory(WarfareTweaksPlugin.ConfigDirectoryPath);
			if (!File.Exists(WarfareTweaksPlugin.WarfareYamlFilePath))
			{
				File.WriteAllText(WarfareTweaksPlugin.WarfareYamlFilePath, WarfareTweaksDefaultYamlResources.Load("WarfareTweaks.yml"));
			}
		}

		internal static Dictionary<string, EffectBehaviorConfig> LoadLocalFile()
		{
			EnsureLocalFileExists();
			return Parse(File.ReadAllText(WarfareTweaksPlugin.WarfareYamlFilePath));
		}

		internal static Dictionary<string, EffectBehaviorConfig> Parse(string yamlText)
		{
			Dictionary<string, EffectBehaviorConfig> dictionary = new Dictionary<string, EffectBehaviorConfig>(StringComparer.OrdinalIgnoreCase);
			if (string.IsNullOrWhiteSpace(yamlText))
			{
				return dictionary;
			}
			try
			{
				YamlStream yamlStream = new YamlStream();
				yamlStream.Load(new StringReader(yamlText));
				if (yamlStream.Documents.Count == 0 || !(yamlStream.Documents[0].RootNode is YamlMappingNode yamlMappingNode))
				{
					return dictionary;
				}
				foreach (KeyValuePair<YamlNode, YamlNode> child in yamlMappingNode.Children)
				{
					string text = (child.Key as YamlScalarNode)?.Value?.Trim() ?? "";
					if (!string.IsNullOrWhiteSpace(text))
					{
						try
						{
							dictionary[text] = DeserializeEffectBehaviorConfig(text, child.Value);
						}
						catch (Exception ex)
						{
							WarfareTweaksPlugin.ModLogger.LogWarning((object)("Skipping WarfareTweaks.yml block '" + text + "': " + ex.Message));
						}
					}
				}
			}
			catch (Exception ex2)
			{
				WarfareTweaksPlugin.ModLogger.LogError((object)("Failed to parse WarfareTweaks.yml: " + ex2.Message));
			}
			return dictionary;
		}

		private static EffectBehaviorConfig DeserializeEffectBehaviorConfig(string rootKey, YamlNode node)
		{
			if (!(node is YamlMappingNode yamlMappingNode))
			{
				return DeserializeYamlNode<EffectBehaviorConfig>(node) ?? new EffectBehaviorConfig();
			}
			NormalizePrefabScalarOverrides(rootKey, yamlMappingNode);
			return DeserializeYamlNode<EffectBehaviorConfig>(yamlMappingNode) ?? new EffectBehaviorConfig();
		}

		private static void NormalizePrefabScalarOverrides(string rootKey, YamlMappingNode mapping)
		{
			string text = ResolvePrefabScalarField(rootKey, mapping);
			if (string.IsNullOrWhiteSpace(text) || !TryGetMappingChild(mapping, "prefabs", out YamlMappingNode child) || child == null)
			{
				return;
			}
			foreach (KeyValuePair<YamlNode, YamlNode> item in child.Children.ToList())
			{
				if (item.Value is YamlScalarNode yamlScalarNode)
				{
					string text2 = yamlScalarNode.Value?.Trim() ?? "";
					float result;
					int result2;
					if (string.IsNullOrWhiteSpace(text2))
					{
						child.Children[item.Key] = new YamlMappingNode();
					}
					else if (!float.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out result))
					{
						WarfareTweaksPlugin.ModLogger.LogWarning((object)("Skipping scalar prefab override in WarfareTweaks.yml block '" + rootKey + "': expected a numeric " + text + ", got '" + text2 + "'."));
					}
					else if (string.Equals(text, "value", StringComparison.OrdinalIgnoreCase) && !int.TryParse(text2, NumberStyles.Integer, CultureInfo.InvariantCulture, out result2))
					{
						WarfareTweaksPlugin.ModLogger.LogWarning((object)("Skipping scalar prefab override in WarfareTweaks.yml block '" + rootKey + "': expected an integer value, got '" + text2 + "'."));
					}
					else
					{
						child.Children[item.Key] = BuildScalarOverrideNode(text, text2);
					}
				}
			}
		}

		private static YamlMappingNode BuildScalarOverrideNode(string scalarField, string value)
		{
			string[] array = (from part in scalarField.Split(new char[1] { '.' }, StringSplitOptions.RemoveEmptyEntries)
				select part.Trim() into part
				where !string.IsNullOrWhiteSpace(part)
				select part).ToArray();
			if (array.Length == 0)
			{
				return new YamlMappingNode();
			}
			YamlMappingNode yamlMappingNode = new YamlMappingNode();
			YamlMappingNode yamlMappingNode2 = yamlMappingNode;
			for (int num = 0; num < array.Length - 1; num++)
			{
				YamlMappingNode yamlMappingNode3 = new YamlMappingNode();
				yamlMappingNode2.Children[new YamlScalarNode(array[num])] = yamlMappingNode3;
				yamlMappingNode2 = yamlMappingNode3;
			}
			yamlMappingNode2.Children[new YamlScalarNode(array[^1])] = new YamlScalarNode(value);
			return yamlMappingNode;
		}

		private static string? ResolvePrefabScalarField(string rootKey, YamlMappingNode mapping)
		{
			string value;
			string text = ((TryGetScalarChild(mapping, "type", out value) && !string.IsNullOrWhiteSpace(value)) ? value : rootKey).Trim();
			if (text.IndexOf("ChainLightning", StringComparison.OrdinalIgnoreCase) >= 0 || string.Equals(text, "chainLightning", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "chainLightningMistlands", StringComparison.OrdinalIgnoreCase))
			{
				return "procChance";
			}
			if (!PrefabScalarFields.TryGetValue(text, out string value2))
			{
				return null;
			}
			return value2;
		}

		private static bool TryGetMappingChild(YamlMappingNode mapping, string key, out YamlMappingNode? child)
		{
			child = null;
			foreach (KeyValuePair<YamlNode, YamlNode> child2 in mapping.Children)
			{
				if (child2.Key is YamlScalarNode yamlScalarNode && string.Equals(yamlScalarNode.Value?.Trim(), key, StringComparison.OrdinalIgnoreCase) && child2.Value is YamlMappingNode yamlMappingNode)
				{
					child = yamlMappingNode;
					return true;
				}
			}
			return false;
		}

		private static bool TryGetScalarChild(YamlMappingNode mapping, string key, out string? value)
		{
			value = null;
			foreach (KeyValuePair<YamlNode, YamlNode> child in mapping.Children)
			{
				if (child.Key is YamlScalarNode yamlScalarNode && string.Equals(yamlScalarNode.Value?.Trim(), key, StringComparison.OrdinalIgnoreCase) && child.Value is YamlScalarNode yamlScalarNode2)
				{
					value = yamlScalarNode2.Value;
					return true;
				}
			}
			return false;
		}

		private static T? DeserializeYamlNode<T>(YamlNode node)
		{
			using StringWriter stringWriter = new StringWriter();
			new YamlStream(new YamlDocument(node)).Save(stringWriter, assignAnchors: false);
			return Deserializer.Deserialize<T>(stringWriter.ToString());
		}
	}
	internal sealed class EffectBehaviorConfig
	{
		public string Type { get; set; } = "";

		public int? Value { get; set; }

		public string Prefab { get; set; } = "";

		public string Trigger { get; set; } = "anyHit";

		public int? StacksRequired { get; set; }

		public float StackWindow { get; set; }

		public float? Duration { get; set; }

		public float? TickInterval { get; set; }

		public float? DamageFactor { get; set; }

		public float? LightningDamage { get; set; }

		public float? Radius { get; set; }

		public float? Ttl { get; set; }

		public float? HitInterval { get; set; }

		public float ProcChance { get; set; } = 100f;

		public string DamageType { get; set; } = "";

		public string Modifier { get; set; } = "normal";

		public ScalarValueConfig Damage { get; set; } = new ScalarValueConfig();

		public ScalarValueConfig Heal { get; set; } = new ScalarValueConfig();

		public ScalarValueConfig StaminaRestore { get; set; } = new ScalarValueConfig();

		public float MoveSpeedMultiplier { get; set; } = 1f;

		public float HealthThresholdPercent { get; set; } = 25f;

		public float DamageMultiplier { get; set; } = 1f;

		public bool ConsumeOnModify { get; set; }

		public Dictionary<string, EffectBehaviorOverrideConfig>? Prefabs { get; set; }
	}
	internal sealed class EffectBehaviorOverrideConfig
	{
		public string? Type { get; set; }

		public int? Value { get; set; }

		public string? Prefab { get; set; }

		public string? Trigger { get; set; }

		public int? StacksRequired { get; set; }

		public float? StackWindow { get; set; }

		public float? Duration { get; set; }

		public float? TickInterval { get; set; }

		public float? DamageFactor { get; set; }

		public float? LightningDamage { get; set; }

		public float? Radius { get; set; }

		public float? Ttl { get; set; }

		public float? HitInterval { get; set; }

		public float? ProcChance { get; set; }

		public string? DamageType { get; set; }

		public string? Modifier { get; set; }

		public ScalarValueOverrideConfig? Damage { get; set; }

		public ScalarValueOverrideConfig? Heal { get; set; }

		public ScalarValueOverrideConfig? StaminaRestore { get; set; }

		public float? MoveSpeedMultiplier { get; set; }

		public float? HealthThresholdPercent { get; set; }

		public float? DamageMultiplier { get; set; }

		public bool? ConsumeOnModify { get; set; }
	}
	internal sealed class ScalarValueConfig
	{
		public string Mode { get; set; } = "fixed";

		public float Value { get; set; }
	}
	internal sealed class ScalarValueOverrideConfig
	{
		public string? Mode { get; set; }

		public float? Value { get; set; }
	}
	internal static class WarfareTweaksConfigExtensions
	{
		internal static bool IsOn(this WarfareTweaksPlugin.Toggle value)
		{
			return value == WarfareTweaksPlugin.Toggle.On;
		}
	}
	internal static class WarfareTweaksDefaultYamlResources
	{
		private const string ResourcePrefix = "WarfareTweaks.Resources.Defaults.";

		internal static string Load(string fileName)
		{
			string text = "WarfareTweaks.Resources.Defaults." + fileName;
			using Stream stream = typeof(WarfareTweaksDefaultYamlResources).Assembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				throw new InvalidOperationException("Embedded default YAML resource '" + text + "' was not found.");
			}
			using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true);
			return streamReader.ReadToEnd();
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "Awake")]
	internal static class FejdStartupAwakeWarfareItemManagerSyncCompatPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			WarfareItemManagerSyncCompat.RegisterMissingRecipeConfigs();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDbAwakeWarfareTweaksPatch
	{
		private static void Postfix(ObjectDB __instance)
		{
			WarfareTweaksPlugin.ApplyToObjectDb(__instance);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ObjectDbCopyOtherDbWarfareTweaksPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(ObjectDB __instance)
		{
			WarfareTweaksPlugin.ApplyToObjectDb(__instance);
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	[HarmonyAfter(new string[] { "Therzie.WarfareFireAndIce" })]
	internal static class ZNetSceneAwakeWarfareTweaksPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(ZNetScene __instance)
		{
			WarfareTweaksPlugin.ApplyToZNetScene(__instance);
		}
	}
	[HarmonyPatch(typeof(SEMan), "ApplyStatusEffectSpeedMods")]
	internal static class SeManApplyStatusEffectSpeedModsWarfareHastePatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(SEMan __instance, ref float speed)
		{
			WarfareCompat.ApplyWarfareHasteSpeedModifier(__instance, ref speed);
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int)
	})]
	internal static class ItemDataGetTooltipWarfareTweaksFallbackTooltipPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(ItemData item, ref string __result)
		{
			WarfareCompat.AppendMissingConfiguredEffectTooltips(item, ref __result);
		}
	}
	[HarmonyPatch(typeof(Projectile), "Setup")]
	internal static class ProjectileSetupWarfareThrowablePatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(Projectile __instance)
		{
			WarfareThrowableCompat.PrepareProjectileIfNeeded(__instance);
		}
	}
	[HarmonyPatch(typeof(Projectile), "OnHit")]
	internal static class ProjectileOnHitWarfareTweaksPatch
	{
		private readonly struct ProjectileHitContextScope
		{
			public WarfareTweaksProjectileHitContext.Scope ProjectileScope { get; }

			public DirectWeaponHitContextSystem.Scope DirectHitScope { get; }

			public ProjectileHitContextScope(WarfareTweaksProjectileHitContext.Scope projectileScope, DirectWeaponHitContextSystem.Scope directHitScope)
			{
				ProjectileScope = projectileScope;
				DirectHitScope = directHitScope;
			}
		}

		[HarmonyPriority(800)]
		private static void Prefix(Projectile __instance, out ProjectileHitContextScope __state)
		{
			__state = new ProjectileHitContextScope(WarfareTweaksProjectileHitContext.Begin(__instance), DirectWeaponHitContextSystem.BeginProjectileHit(__instance));
			WarfareThrowableCompat.PrepareProjectileIfNeeded(__instance);
		}

		[HarmonyPriority(0)]
		private static void Postfix(ProjectileHitContextScope __state)
		{
			DirectWeaponHitContextSystem.End(__state.DirectHitScope);
			WarfareTweaksProjectileHitContext.End(__state.ProjectileScope);
		}
	}
	[HarmonyPatch(typeof(Destructible), "Damage")]
	internal static class DestructibleDamageWarfareThrowablePatch
	{
		private static void Prefix(HitData hit)
		{
			WarfareThrowableCompat.ApplyProjectileToolTierIfNeeded(hit, "Destructible.Damage");
		}
	}
	[HarmonyPatch(typeof(MineRock), "Damage")]
	internal static class MineRockDamageWarfareThrowablePatch
	{
		private static void Prefix(HitData hit)
		{
			WarfareThrowableCompat.ApplyProjectileToolTierIfNeeded(hit, "MineRock.Damage");
		}
	}
	[HarmonyPatch(typeof(MineRock5), "Damage")]
	internal static class MineRock5DamageWarfareThrowablePatch
	{
		private static void Prefix(HitData hit)
		{
			WarfareThrowableCompat.ApplyProjectileToolTierIfNeeded(hit, "MineRock5.Damage");
		}
	}
	[HarmonyPatch(typeof(TreeBase), "Damage")]
	internal static class TreeBaseDamageWarfareThrowablePatch
	{
		private static void Prefix(HitData hit)
		{
			WarfareThrowableCompat.ApplyProjectileToolTierIfNeeded(hit, "TreeBase.Damage");
			WarfareThrowableCompat.ApplyProjectileWoodCuttingSkillIfNeeded(hit, "TreeBase.Damage");
		}
	}
	[HarmonyPatch(typeof(TreeLog), "Damage")]
	internal static class TreeLogDamageWarfareThrowablePatch
	{
		private static void Prefix(HitData hit)
		{
			WarfareThrowableCompat.ApplyProjectileToolTierIfNeeded(hit, "TreeLog.Damage");
			WarfareThrowableCompat.ApplyProjectileWoodCuttingSkillIfNeeded(hit, "TreeLog.Damage");
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Damage")]
	internal static class WearNTearDamageWarfareThrowablePatch
	{
		private static void Prefix(HitData hit)
		{
			WarfareThrowableCompat.ApplyProjectileToolTierIfNeeded(hit, "WearNTear.Damage");
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList", new Type[] { typeof(List<Recipe>) })]
	internal static class InventoryGuiUpdateRecipeListWarfareThrowableUpgradePatch
	{
		[HarmonyPriority(800)]
		private static void Prefix(InventoryGui __instance, List<Recipe> recipes)
		{
			WarfareThrowableCompat.PrepareUpgradeRecipeList(recipes, !__instance.InCraftTab());
		}
	}
	[HarmonyPatch(typeof(Humanoid), "StartAttack")]
	internal static class HumanoidStartAttackWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static void Prefix(Humanoid __instance)
		{
			if (__instance is Player)
			{
				WarfareThrowableCompat.PrepareWeaponForUse(__instance.GetCurrentWeapon());
			}
		}
	}
	[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
	internal static class AttackOnAttackTriggerWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static void Prefix(Attack __instance, out bool __state)
		{
			__state = WarfareThrowableCompat.BeginInventoryRemovalPreservation(__instance);
		}

		[HarmonyPriority(0)]
		private static void Postfix(bool __state)
		{
			WarfareThrowableCompat.EndInventoryRemovalPreservation(__state);
		}
	}
	[HarmonyPatch(typeof(Attack), "ConsumeItem")]
	internal static class AttackConsumeItemWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(Attack __instance)
		{
			return !WarfareThrowableCompat.ShouldPreserveWeaponOnConsume(__instance);
		}
	}
	[HarmonyPatch(typeof(Attack), "UseAmmo")]
	internal static class AttackUseAmmoWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(Attack __instance, ref bool __result, ref ItemData ammoItem)
		{
			if (!WarfareThrowableCompat.ShouldSkipAmmoConsumption(__instance))
			{
				return true;
			}
			ammoItem = null;
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })]
	internal static class InventoryRemoveItemWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(ItemData item, ref bool __result)
		{
			if (!WarfareThrowableCompat.ShouldBlockInventoryRemoval(item, "Inventory.RemoveItem(item)"))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[]
	{
		typeof(ItemData),
		typeof(int)
	})]
	internal static class InventoryRemoveItemAmountWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(ItemData item, int amount, ref bool __result)
		{
			if (!WarfareThrowableCompat.ShouldBlockInventoryRemoval(item, "Inventory.RemoveItem(item, amount)", amount))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "RemoveOneItem", new Type[] { typeof(ItemData) })]
	internal static class InventoryRemoveOneItemWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(ItemData item, ref bool __result)
		{
			if (!WarfareThrowableCompat.ShouldBlockInventoryRemoval(item, "Inventory.RemoveOneItem(item)", 1))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UnequipItem", new Type[]
	{
		typeof(ItemData),
		typeof(bool)
	})]
	internal static class HumanoidUnequipItemWarfareThrowableAttackPatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(ItemData item)
		{
			return !WarfareThrowableCompat.ShouldBlockInventoryRemoval(item, "Humanoid.UnequipItem(item)");
		}
	}
	[HarmonyPatch(typeof(Humanoid), "ConsumeItem", new Type[]
	{
		typeof(Inventory),
		typeof(ItemData),
		typeof(bool)
	})]
	internal static class HumanoidConsumeItemWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(ItemData item, ref bool __result)
		{
			if (!WarfareThrowableCompat.ShouldBlockInventoryRemoval(item, "Humanoid.ConsumeItem(item)", 1))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[]
	{
		typeof(string),
		typeof(int),
		typeof(int),
		typeof(bool)
	})]
	internal static class InventoryRemoveNamedItemWarfareThrowablePatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(string name, int amount)
		{
			return !WarfareThrowableCompat.ShouldBlockNamedInventoryRemoval("Inventory.RemoveItem(name, amount, quality, worldLevel)", name, amount);
		}
	}
	[HarmonyPatch(typeof(Attack), "ProjectileAttackTriggered")]
	internal static class AttackProjectileAttackTriggeredWarfareThrowableDurabilityPatch
	{
		private static void Prefix(Attack __instance, out WarfareThrowableCompat.ProjectileDurabilityDrainState __state)
		{
			__state = WarfareThrowableCompat.CaptureProjectileDurabilityDrain(__instance);
		}

		private static void Postfix(WarfareThrowableCompat.ProjectileDurabilityDrainState __state)
		{
			WarfareThrowableCompat.ApplyMissingProjectileDurabilityDrain(__state);
		}
	}
	[BepInPlugin("sighsorry.WarfareTweaks", "WarfareTweaks", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class WarfareTweaksPlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		internal const string ModName = "WarfareTweaks";

		internal const string ModVersion = "1.0.0";

		internal const string Author = "sighsorry";

		internal const string ModGUID = "sighsorry.WarfareTweaks";

		internal const string WarfareYamlFileName = "WarfareTweaks.yml";

		internal static readonly ManualLogSource ModLogger = Logger.CreateLogSource("WarfareTweaks");

		internal static readonly ConfigSync ConfigSync = new ConfigSync("sighsorry.WarfareTweaks")
		{
			DisplayName = "WarfareTweaks",
			CurrentVersion = "1.0.0",
			MinimumRequiredVersion = "1.0.0"
		};

		private static Dictionary<string, EffectBehaviorConfig> _currentEffects = new Dictionary<string, EffectBehaviorConfig>(StringComparer.OrdinalIgnoreCase);

		private static CustomSyncedValue<string>? _syncedWarfareYaml;

		private static bool _suppressSyncedYamlChanged;

		private readonly Harmony _harmony = new Harmony("sighsorry.WarfareTweaks");

		private FileSystemWatcher? _watcher;

		private readonly object _reloadLock = new object();

		private DateTime _lastConfigReloadTime;

		private const long ReloadDelayTicks = 10000000L;

		internal static string ConfigDirectoryPath => Paths.ConfigPath;

		internal static string WarfareYamlFilePath => Path.Combine(ConfigDirectoryPath, "WarfareTweaks.yml");

		internal static IReadOnlyDictionary<string, EffectBehaviorConfig> CurrentEffects => _currentEffects;

		public void Awake()
		{
			ConfigSync.AddLockingConfigEntry<Toggle>(((BaseUnityPlugin)this).Config.Bind<Toggle>("1 - General", "Lock Configuration", Toggle.On, "If on, the server configuration is enforced for clients."));
			_syncedWarfareYaml = new CustomSyncedValue<string>(ConfigSync, "warfare_tweaks_warfare_yaml", "");
			_syncedWarfareYaml.ValueChanged += OnSyncedWarfareYamlChanged;
			WarfareTweaksLocalization.Load();
			WarfareTweaksConfigLoader.EnsureLocalFileExists();
			ReloadLocalConfigFromDisk(applyToWorld: false);
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			WarfareCompat.TryInstallHooks();
			WarfareSkillCompat.TryInstallHooks();
			JewelcraftingThrowableCompat.TryInstallHooks();
			SetupWatcher();
		}

		private void OnDestroy()
		{
			if (_syncedWarfareYaml != null)
			{
				_syncedWarfareYaml.ValueChanged -= OnSyncedWarfareYamlChanged;
			}
			_watcher?.Dispose();
			_harmony.UnpatchSelf();
		}

		internal static void ApplyToObjectDb(ObjectDB objectDb, bool logMissingPrefabWarnings = false)
		{
			if (!((Object)(object)objectDb == (Object)null))
			{
				WarfareCompat.ApplyConfiguredEffects(objectDb, _currentEffects, logMissingPrefabWarnings);
				WarfareThrowableCompat.ApplyToObjectDb(objectDb);
				WarfareSkillCompat.ApplyToObjectDb(objectDb);
			}
		}

		internal static void ApplyToZNetScene(ZNetScene scene)
		{
			if (!((Object)(object)scene == (Object)null))
			{
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					WarfareCompat.ApplyConfiguredEffects(ObjectDB.instance, _currentEffects, logMissingPrefabWarnings: true);
				}
				WarfareThrowableCompat.ApplyToZNetScene(scene);
				ChainLightningDedupSystem.RestoreVanillaChainLightningBehavior(scene);
			}
		}

		private void SetupWatcher()
		{
			_watcher = new FileSystemWatcher(ConfigDirectoryPath, "WarfareTweaks.yml");
			_watcher.Changed += ReadConfigValues;
			_watcher.Created += ReadConfigValues;
			_watcher.Renamed += ReadConfigValues;
			_watcher.IncludeSubdirectories = false;
			_watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			_watcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			DateTime now = DateTime.Now;
			if (now.Ticks - _lastConfigReloadTime.Ticks >= 10000000)
			{
				lock (_reloadLock)
				{
					ReloadLocalConfigFromDisk(applyToWorld: true);
				}
				_lastConfigReloadTime = now;
			}
		}

		private static void ReloadLocalConfigFromDisk(bool applyToWorld)
		{
			WarfareTweaksConfigLoader.EnsureLocalFileExists();
			string text = File.ReadAllText(WarfareYamlFilePath);
			if (_syncedWarfareYaml != null)
			{
				_suppressSyncedYamlChanged = true;
				try
				{
					_syncedWarfareYaml.AssignLocalValue(text);
				}
				finally
				{
					_suppressSyncedYamlChanged = false;
				}
			}
			ApplyYamlText(text, applyToWorld);
		}

		private static void OnSyncedWarfareYamlChanged()
		{
			if (!_suppressSyncedYamlChanged && _syncedWarfareYaml != null && !string.IsNullOrWhiteSpace(_syncedWarfareYaml.Value))
			{
				ApplyYamlText(_syncedWarfareYaml.Value, applyToWorld: true);
			}
		}

		private static void ApplyYamlText(string yamlText, bool applyToWorld)
		{
			_currentEffects = WarfareTweaksConfigLoader.Parse(yamlText);
			WarfareCompat.RebuildBuiltInEffects(_currentEffects);
			if (applyToWorld)
			{
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					ApplyToObjectDb(ObjectDB.instance, (Object)(object)ZNetScene.instance != (Object)null);
				}
				if ((Object)(object)ZNetScene.instance != (Object)null)
				{
					ApplyToZNetScene(ZNetScene.instance);
				}
				ModLogger.LogInfo((object)"WarfareTweaks YAML reload complete.");
			}
		}
	}
	internal static class WarfareTweaksProjectileHitContext
	{
		internal readonly struct Scope
		{
			internal Projectile? Previous { get; }

			internal Scope(Projectile? previous)
			{
				Previous = previous;
			}
		}

		[ThreadStatic]
		private static Projectile? _currentProjectile;

		internal static Scope Begin(Projectile projectile)
		{
			if ((Object)(object)projectile == (Object)null)
			{
				return default(Scope);
			}
			Projectile? currentProjectile = _currentProjectile;
			_currentProjectile = projectile;
			return new Scope(currentProjectile);
		}

		internal static void End(Scope scope)
		{
			_currentProjectile = scope.Previous;
		}

		internal static bool TryPeek(out ProjectileHitContext context)
		{
			Projectile currentProjectile = _currentProjectile;
			context = (((Object)(object)currentProjectile != (Object)null) ? new ProjectileHitContext(currentProjectile) : default(ProjectileHitContext));
			return (Object)(object)currentProjectile != (Object)null;
		}
	}
	internal readonly struct ProjectileHitContext
	{
		public Projectile? Projectile { get; }

		public ProjectileHitContext(Projectile projectile)
		{
			Projectile = projectile;
		}
	}
	internal static class WarfareTweaksRuntimeContext
	{
		internal static bool TryPeekProjectileHitContext(out ProjectileHitContext context)
		{
			return WarfareTweaksProjectileHitContext.TryPeek(out context);
		}
	}
	internal static class WarfareTweaksRuntimeFacade
	{
		internal static bool TryGetProjectileHitAttackContext(out string weaponPrefabName, out bool secondaryAttack, out object? definition, out bool disableCurrentAttackFallback)
		{
			weaponPrefabName = "";
			secondaryAttack = false;
			definition = null;
			disableCurrentAttackFallback = false;
			return DirectWeaponHitContextSystem.TryGetCurrentProjectileWeaponPrefabName(out weaponPrefabName);
		}
	}
	internal static class WeaponEffectManager
	{
		internal static bool IsApplyingGeneratedEffectDamage => WarfareTweaksBridge.IsExternalGeneratedDamageActive;

		internal static bool ShouldSuppressWarfareBuiltIn(string effectId)
		{
			if (DirectWeaponHitContextSystem.TryGetCurrentProjectileWeaponPrefabName(out string prefabName))
			{
				return WarfareCompat.ShouldSuppressBuiltIn(prefabName, effectId);
			}
			return false;
		}
	}
	internal static class WarfareTweaksWarningLog
	{
		private static readonly HashSet<string> Reported = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static bool TryMarkReported(string key)
		{
			if (!string.IsNullOrWhiteSpace(key))
			{
				return Reported.Add(key);
			}
			return false;
		}
	}
	internal static class JewelcraftingThrowableCompat
	{
		private const string UtilsTypeName = "Jewelcrafting.Utils";

		private const string JewelcraftingTypeName = "Jewelcrafting.Jewelcrafting";

		private static bool _hooksInstalled;

		private static bool _reportedFailure;

		private static FieldInfo? _socketBlacklistField;

		private static FieldInfo? _prefabBlacklistField;

		internal static void TryInstallHooks()
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			if (_hooksInstalled || !TryGetJewelcraftingAssembly(out Assembly jewelcraftingAssembly) || jewelcraftingAssembly == null)
			{
				return;
			}
			MethodInfo methodInfo = jewelcraftingAssembly.GetType("Jewelcrafting.Utils", throwOnError: false)?.GetMethod("IsSocketableItem", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
			MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(JewelcraftingThrowableCompat), "IsSocketableItemPostfix", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.DeclaredMethod(typeof(InventoryGui), "UpdateRecipeList", (Type[])null, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.DeclaredMethod(typeof(JewelcraftingThrowableCompat), "PrepareInventoryBeforeRecipeListPrefix", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null || methodInfo4 == null)
			{
				ReportFailure("Jewelcrafting.Utils.IsSocketableItem(ItemData) was not found.");
				return;
			}
			CacheBlacklistFields(jewelcraftingAssembly);
			Harmony val = new Harmony("sighsorry.WarfareTweaks.JewelcraftingThrowableCompat");
			val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			if (methodInfo3 != null)
			{
				val.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo4)
				{
					priority = 800
				}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				ReportFailure("InventoryGui.UpdateRecipeList was not found; socket tab pre-normalization is unavailable.");
			}
			_hooksInstalled = true;
			WarfareTweaksPlugin.ModLogger.LogInfo((object)"Installed Jewelcrafting compatibility hooks for Warfare throwing axe socketing.");
		}

		private static void PrepareInventoryBeforeRecipeListPrefix()
		{
			Player localPlayer = Player.m_localPlayer;
			Inventory val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null);
			if (val == null)
			{
				return;
			}
			foreach (ItemData item in val.m_inventory)
			{
				if (WarfareThrowableCompat.TryPrepareJewelcraftingSocketableWeapon(item))
				{
					RemovePrefabBlacklistEntry(item);
					if (WarfareThrowableCompat.DebugLoggingEnabled)
					{
						WarfareThrowableCompat.LogDebug("Jewelcrafting pre-normalized Warfare throwable prefab=" + GetItemPrefabName(item) + " shared=" + item.m_shared?.m_name);
					}
				}
			}
		}

		private static void IsSocketableItemPostfix(ItemData item, ref bool __result)
		{
			if (!__result && item != null && !IsUserSocketBlacklisted(item) && WarfareThrowableCompat.TryPrepareJewelcraftingSocketableWeapon(item))
			{
				RemovePrefabBlacklistEntry(item);
				__result = true;
				if (WarfareThrowableCompat.DebugLoggingEnabled)
				{
					WarfareThrowableCompat.LogDebug("Jewelcrafting socketability allowed for Warfare throwable prefab=" + GetItemPrefabName(item) + " shared=" + item.m_shared?.m_name);
				}
			}
		}

		private static bool IsUserSocketBlacklisted(ItemData item)
		{
			string itemPrefabName = GetItemPrefabName(item);
			if (string.IsNullOrWhiteSpace(itemPrefabName))
			{
				return false;
			}
			if (_socketBlacklistField?.GetValue(null) is ConfigEntry<string> val)
			{
				string[] array = val.Value.Replace(" ", "").Split(',');
				for (int i = 0; i < array.Length; i++)
				{
					if (string.Equals(array[i], itemPrefabName, StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void RemovePrefabBlacklistEntry(ItemData item)
		{
			string itemPrefabName = GetItemPrefabName(item);
			if (!string.IsNullOrWhiteSpace(itemPrefabName) && _prefabBlacklistField?.GetValue(null) is ICollection<string> collection && collection.Contains(itemPrefabName))
			{
				collection.Remove(itemPrefabName);
			}
		}

		private static void CacheBlacklistFields(Assembly jewelcraftingAssembly)
		{
			Type type = jewelcraftingAssembly.GetType("Jewelcrafting.Jewelcrafting", throwOnError: false);
			_socketBlacklistField = ((type != null) ? AccessTools.Field(type, "socketBlacklist") : null);
			_prefabBlacklistField = ((type != null) ? AccessTools.Field(type, "PrefabBlacklist") : null);
		}

		private static bool TryGetJewelcraftingAssembly(out Assembly? jewelcraftingAssembly)
		{
			jewelcraftingAssembly = null;
			if (Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.jewelcrafting", out var value))
			{
				jewelcraftingAssembly = ((object)value.Instance)?.GetType().Assembly;
				if (jewelcraftingAssembly != null)
				{
					return true;
				}
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly.GetType("Jewelcrafting.Utils", throwOnError: false) != null)
				{
					jewelcraftingAssembly = assembly;
					return true;
				}
			}
			return false;
		}

		private static void ReportFailure(string message)
		{
			if (!_reportedFailure)
			{
				_reportedFailure = true;
				WarfareTweaksPlugin.ModLogger.LogWarning((object)("Jewelcrafting Warfare throwable compatibility skipped: " + message));
			}
		}

		private static string GetItemPrefabName(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab == (Object)null)
			{
				return string.Empty;
			}
			string name = ((Object)item.m_dropPrefab).name;
			if (!name.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				return name;
			}
			return name.Substring(0, name.Length - "(Clone)".Length);
		}
	}
	internal static class WarfareCompat
	{
		private sealed class ConfiguredWarfareEffectLookup
		{
			public WarfareBuiltInEffectRegistration Registration { get; }

			public EffectBehaviorConfig EffectConfig { get; }

			public EffectBehaviorOverrideConfig? PrefabOverride { get; }

			public ConfiguredWarfareEffectLookup(WarfareBuiltInEffectRegistration registration, EffectBehaviorConfig effectConfig, EffectBehaviorOverrideConfig? prefabOverride)
			{
				Registration = registration;
				EffectConfig = effectConfig;
				PrefabOverride = prefabOverride;
			}
		}

		private sealed class WarfareTargetAccessors
		{
			public FieldInfo? TargetsField { get; }

			public MethodInfo[] AddToItemMethods { get; }

			public WarfareTargetAccessors(Type effectType)
			{
				TargetsField = effectType.GetField("Targets", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				AddToItemMethods = (from method in effectType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
					where method.Name == "AddToItem"
					select method).ToArray();
			}
		}

		private sealed class WarfareTargetSetAccessors
		{
			public MethodInfo? ContainsMethod { get; }

			public MethodInfo? AddMethod { get; }

			public MethodInfo? RemoveMethod { get; }

			public WarfareTargetSetAccessors(Type targetType)
			{
				ContainsMethod = targetType.GetMethod("Contains", new Type[1] { typeof(string) });
				AddMethod = targetType.GetMethod("Add", new Type[1] { typeof(string) });
				RemoveMethod = targetType.GetMethod("Remove", new Type[1] { typeof(string) });
			}
		}

		private sealed class WarfareBuiltInEffectRegistration
		{
			private readonly Dictionary<string, WarfareDefaultAssignment> _defaultAssignmentsByPrefabName;

			public string Id { get; }

			public WarfareEffectTypeSpec[] EffectTypeSpecs { get; }

			public string StatusEffectsNamespace => EffectTypeSpecs[0].StatusEffectsNamespace;

			public string PatchTypeName => EffectTypeSpecs[0].PatchTypeName;

			public string CharacterDamagePatchTypeName => StatusEffectsNamespace + "." + PatchTypeName + "+Character_Damage_Patch";

			public string EffectTypeName => EffectTypeSpecs[0].EffectTypeName;

			public string[] EffectTypeNames => EffectTypeSpecs.Select((WarfareEffectTypeSpec spec) => spec.EffectTypeName).ToArray();

			public string[] PrefabNames { get; }

			public string[] EffectIds { get; }

			public bool RequiresValue => _defaultAssignmentsByPrefabName.Values.Any((WarfareDefaultAssignment assignment) => assignment.Value.HasValue);

			public WarfareBuiltInEffectRegistration(string id, string patchTypeName, string[] prefabSpecs, params string[] aliases)
				: this(id, new WarfareEffectTypeSpec[1]
				{
					new WarfareEffectTypeSpec("Warfare_StatusEffects.StatusEffects", patchTypeName, prefabSpecs)
				}, aliases)
			{
			}

			public WarfareBuiltInEffectRegistration(string id, WarfareEffectTypeSpec[] effectTypeSpecs, params string[] aliases)
			{
				Id = id;
				EffectTypeSpecs = (effectTypeSpecs ?? Array.Empty<WarfareEffectTypeSpec>()).Where((WarfareEffectTypeSpec spec) => spec != null && !string.IsNullOrWhiteSpace(spec.EffectTypeName)).ToArray();
				if (EffectTypeSpecs.Length == 0)
				{
					EffectTypeSpecs = new WarfareEffectTypeSpec[1]
					{
						new WarfareEffectTypeSpec("Warfare_StatusEffects.StatusEffects", id, Array.Empty<string>())
					};
				}
				_defaultAssignmentsByPrefabName = ParsePrefabSpecs(EffectTypeSpecs);
				PrefabNames = _defaultAssignmentsByPrefabName.Keys.ToArray();
				EffectIds = new string[1] { id }.Concat(aliases).ToArray();
			}

			public int? GetDefaultValue(string prefabName)
			{
				if (!_defaultAssignmentsByPrefabName.TryGetValue(prefabName, out WarfareDefaultAssignment value))
				{
					return null;
				}
				return value.Value;
			}

			public string? GetDefaultEffectTypeName(string prefabName)
			{
				if (!_defaultAssignmentsByPrefabName.TryGetValue(prefabName, out WarfareDefaultAssignment value))
				{
					return null;
				}
				return value.EffectTypeName;
			}

			public bool IsDefaultAssignment(string prefabName, int? value)
			{
				if (_defaultAssignmentsByPrefabName.TryGetValue(prefabName, out WarfareDefaultAssignment value2))
				{
					return value2.Value == value;
				}
				return false;
			}

			private static Dictionary<string, WarfareDefaultAssignment> ParsePrefabSpecs(IEnumerable<WarfareEffectTypeSpec> effectTypeSpecs)
			{
				Dictionary<string, WarfareDefaultAssignment> dictionary = new Dictionary<string, WarfareDefaultAssignment>(StringComparer.OrdinalIgnoreCase);
				foreach (WarfareEffectTypeSpec effectTypeSpec in effectTypeSpecs)
				{
					string[] prefabSpecs = effectTypeSpec.PrefabSpecs;
					foreach (string text in prefabSpecs)
					{
						if (string.IsNullOrWhiteSpace(text))
						{
							continue;
						}
						string[] array = text.Split(new char[1] { ':' }, 2);
						string text2 = array[0].Trim();
						if (!string.IsNullOrWhiteSpace(text2))
						{
							int? value = null;
							if (array.Length == 2 && int.TryParse(array[1].Trim(), out var result))
							{
								value = result;
							}
							dictionary[text2] = new WarfareDefaultAssignment(effectTypeSpec.EffectTypeName, value);
						}
					}
				}
				return dictionary;
			}
		}

		private sealed class WarfareEffectTypeSpec
		{
			public string StatusEffectsNamespace { get; }

			public string PatchTypeName { get; }

			public string EffectTypeName { get; }

			public string CharacterDamagePatchTypeName => StatusEffectsNamespace + "." + PatchTypeName + "+Character_Damage_Patch";

			public string[] PrefabSpecs { get; }

			public WarfareEffectTypeSpec(string statusEffectsNamespace, string patchTypeName, string[] prefabSpecs)
			{
				StatusEffectsNamespace = statusEffectsNamespace;
				PatchTypeName = patchTypeName;
				PrefabSpecs = prefabSpecs ?? Array.Empty<string>();
				EffectTypeName = StatusEffectsNamespace + "." + PatchTypeName;
			}
		}

		private sealed class WarfareDefaultAssignment
		{
			public string EffectTypeName { get; }

			public int? Value { get; }

			public WarfareDefaultAssignment(string effectTypeName, int? value)
			{
				EffectTypeName = effectTypeName;
				Value = value;
			}
		}

		private sealed class WarfareAppliedAssignment
		{
			public string EffectTypeName { get; }

			public string PrefabName { get; }

			public bool UsesValueTarget { get; }

			public bool HadOriginalTarget { get; }

			public int? OriginalValue { get; }

			public int? AppliedValue { get; }

			public WarfareAppliedAssignment(string effectTypeName, string prefabName, bool usesValueTarget, bool hadOriginalTarget, int? originalValue, int? appliedValue)
			{
				EffectTypeName = effectTypeName;
				PrefabName = prefabName;
				UsesValueTarget = usesValueTarget;
				HadOriginalTarget = hadOriginalTarget;
				OriginalValue = originalValue;
				AppliedValue = appliedValue;
			}
		}

		private sealed class WarfareAttackSpawnOverrideState
		{
			public Attack Attack { get; }

			public GameObject? OriginalSpawnOnHit { get; }

			public float OriginalSpawnOnHitChance { get; }

			public WarfareAttackSpawnOverrideState(Attack attack, GameObject? originalSpawnOnHit, float originalSpawnOnHitChance)
			{
				Attack = attack;
				OriginalSpawnOnHit = originalSpawnOnHit;
				OriginalSpawnOnHitChance = originalSpawnOnHitChance;
			}
		}

		private sealed class WarfareAoeOverrideState
		{
			public Aoe Aoe { get; }

			public DamageTypes OriginalDamage { get; }

			public float OriginalRadius { get; }

			public float OriginalTtl { get; }

			public float OriginalHitInterval { get; }

			public WarfareAoeOverrideState(Aoe aoe, DamageTypes originalDamage, float originalRadius, float originalTtl, float originalHitInterval)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				Aoe = aoe;
				OriginalDamage = originalDamage;
				OriginalRadius = originalRadius;
				OriginalTtl = originalTtl;
				OriginalHitInterval = originalHitInterval;
			}
		}

		private sealed class WarfareAttackStatusEffectOverrideState
		{
			public ItemDrop ItemDrop { get; }

			public StatusEffect OriginalAttackStatusEffect { get; }

			public WarfareAttackStatusEffectOverrideState(ItemDrop itemDrop, StatusEffect originalAttackStatusEffect)
			{
				ItemDrop = itemDrop;
				OriginalAttackStatusEffect = originalAttackStatusEffect;
			}
		}

		private sealed class WarfareBleedTuning
		{
			public string PrefabName { get; set; } = "";

			public int? StacksRequired { get; set; }

			public float? StackWindow { get; set; }

			public float? Duration { get; set; }

			public float? TickInterval { get; set; }

			public float? DamageFactor { get; set; }

			public int? NativeValue { get; set; }

			public float? SourceDamage { get; set; }

			public bool HasAnyValue
			{
				get
				{
					if (!StacksRequired.HasValue && !StackWindow.HasValue && !Duration.HasValue && !TickInterval.HasValue)
					{
						return DamageFactor.HasValue;
					}
					return true;
				}
			}
		}

		private sealed class WarfareBleedTuningState
		{
			public float? Duration { get; }

			public float? TickInterval { get; }

			public float? DamageFactor { get; }

			public int? NativeValue { get; }

			public float? SourceDamage { get; private set; }

			public bool UseSourceDamageDot => DamageFactor.HasValue;

			public WarfareBleedTuningState(WarfareBleedTuning tuning)
			{
				Duration = tuning.Duration;
				TickInterval = tuning.TickInterval;
				DamageFactor = tuning.DamageFactor;
				NativeValue = tuning.NativeValue;
				SourceDamage = tuning.SourceDamage;
			}

			public void SetSourceDamage(float sourceDamage)
			{
				SourceDamage = Mathf.Max(0f, sourceDamage);
			}
		}

		private sealed class WarfareHasteTuningState
		{
			public float MoveSpeedMultiplier { get; }

			public WarfareHasteTuningState(float moveSpeedMultiplier)
			{
				MoveSpeedMultiplier = moveSpeedMultiplier;
			}
		}

		private sealed class ItemPrefabNameCacheEntry
		{
			public string PrefabName { get; }

			public ItemPrefabNameCacheEntry(string prefabName)
			{
				PrefabName = prefabName;
			}
		}

		private sealed class ObjectDbItemNameCache
		{
			public int ItemCount { get; }

			public HashSet<string> ItemNames { get; }

			public ObjectDbItemNameCache(int itemCount, HashSet<string> itemNames)
			{
				ItemCount = itemCount;
				ItemNames = itemNames;
			}
		}

		private sealed class WarfareDotSourceDamageContext
		{
			private readonly List<WarfareBleedTuningState> _states = new List<WarfareBleedTuningState>();

			public Character Target { get; }

			public string WeaponPrefabName { get; }

			public float SourceDamage { get; }

			public float HealthBefore { get; }

			public WarfareDotSourceDamageContext(Character target, string weaponPrefabName, float sourceDamage, float healthBefore)
			{
				Target = target;
				WeaponPrefabName = weaponPrefabName;
				SourceDamage = sourceDamage;
				HealthBefore = healthBefore;
			}

			public void RegisterState(WarfareBleedTuningState state)
			{
				if (!_states.Contains(state))
				{
					_states.Add(state);
				}
			}

			public void ApplyActualDamage(float actualDamage)
			{
				foreach (WarfareBleedTuningState state in _states)
				{
					state.SetSourceDamage(actualDamage);
				}
			}
		}

		internal const string WarfareGuid = "Therzie.Warfare";

		private const string WarfareStatusEffectsNamespace = "Warfare_StatusEffects.StatusEffects";

		private const string WarfareFireAndIceStatusEffectsNamespace = "WarfareFireAndIce_StatusEffects.StatusEffects";

		private const string WarfareUtilsTypeName = "Warfare_StatusEffects.StatusEffects.WarfareUtils";

		private static readonly Dictionary<string, HashSet<string>> SuppressedEffectsByPrefabName = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, HashSet<string>> ManagedEffectsByPrefabName = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<string> ManagedChainLightningPrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

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

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

		private static readonly Dictionary<string, WarfareAppliedAssignment> AppliedConfiguredAssignments = new Dictionary<string, WarfareAppliedAssignment>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, WarfareAttackSpawnOverrideState> AppliedAttackSpawnOverrides = new Dictionary<string, WarfareAttackSpawnOverrideState>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, WarfareAoeOverrideState> AppliedAoeOverrides = new Dictionary<string, WarfareAoeOverrideState>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, WarfareAttackStatusEffectOverrideState> AppliedAttackStatusEffectOverrides = new Dictionary<string, WarfareAttackStatusEffectOverrideState>(StringComparer.OrdinalIgnoreCase);

		private static readonly ConditionalWeakTable<StatusEffect, WarfareBleedTuningState> BleedTuningsByStatus = new ConditionalWeakTable<StatusEffect, WarfareBleedTuningState>();

		private static readonly ConditionalWeakTable<StatusEffect, WarfareHasteTuningState> HasteTuningsByStatus = new ConditionalWeakTable<StatusEffect, WarfareHasteTuningState>();

		private static readonly ConditionalWeakTable<SharedData, ItemPrefabNameCacheEntry> ItemPrefabNamesBySharedData = new ConditionalWeakTable<SharedData, ItemPrefabNameCacheEntry>();

		private static readonly List<WarfareDotSourceDamageContext> ActiveDotSourceDamageContexts = new List<WarfareDotSourceDamageContext>();

		private static readonly Dictionary<ObjectDB, ObjectDbItemNameCache> ObjectDbItemNameCaches = new Dictionary<ObjectDB, ObjectDbItemNameCache>();

		private static readonly Dictionary<string, ConfiguredWarfareEffectLookup> ConfiguredEffectsByPrefabAndEffectId = new Dictionary<string, ConfiguredWarfareEffectLookup>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, List<ConfiguredWarfareEffectLookup>> ConfiguredTooltipEffectsByPrefabName = new Dictionary<string, List<ConfiguredWarfareEffectLookup>>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Type> LoadedTypesByName = new Dictionary<string, Type>(StringComparer.Ordinal);

		private static readonly Dictionary<Type, WarfareTargetAccessors> TargetAccessorsByEffectType = new Dictionary<Type, WarfareTargetAccessors>();

		private static readonly Dictionary<Type, WarfareTargetSetAccessors> TargetSetAccessorsByType = new Dictionary<Type, WarfareTargetSetAccessors>();

		private static readonly int WarfareHasteStackingHash = StringExtensionMethods.GetStableHashCode("Warfare_Haste_Stacking");

		private static readonly int WarfareFireAndIceHasteStackingHash = StringExtensionMethods.GetStableHashCode("WarfareFireAndIce_Haste_Stacking");

		private const float WarfareSourceDamageDotDuration = 10f;

		private const float WarfareSourceDamageDotTickInterval = 1f;

		private static float? _pendingHasteMoveSpeedMultiplier;

		private static bool _allowWarfareAddToItem;

		private static bool _hooksInstalled;

		private static readonly string[] ChainLightningMistlandsDefaultPrefabs = new string[11]
		{
			"GreatbowDvergr_TW", "BastardDvergr_TW", "AxeDvergr_TW", "BattleaxeDvergr_TW", "BattlehammerDvergr_TW", "ClaymoreDvergr_TW", "FistDvergr_TW", "LanceDvergr_TW", "MaceDvergr_TW", "ThrowAxeDvergr_TW",
			"WarpikeDvergr_TW"
		};

		private static readonly WarfareBuiltInEffectRegistration[] BuiltInRegistrations = new WarfareBuiltInEffectRegistration[22]
		{
			RegisterWarfareAndFireAndIce("adrenaline", "Adrenaline", new string[3] { "KnifeViper_TW:10", "FistBlackmetal_TW:14", "FistDvergr_TW:16" }, new string[5] { "DualHammerRageHatred_TW:20", "DualKnifeNjord_TW:20", "DualKnifeSurtr_TW:20", "KnifeNjord_TW:20", "KnifeSurtr_TW:20" }),
			RegisterWarfareAndFireAndIce("bash", "Bash", new string[5] { "SledgeBonemass_TW:3", "SledgeSilver_TW:2", "SledgeBlackmetal_TW:3", "SledgeDemolisher_TW:4", "SledgeFlametal_TW:5" }, new string[2] { "SledgeNjord_TW:6", "SledgeSurtr_TW:6" }),
			new WarfareBuiltInEffectRegistration("bleeding", "Bleeding", new string[1] { "FistSilver_TW:1" }),
			RegisterWarfareAndFireAndIce("bleedingSecondary", "BleedingSecondaryAttack", new string[2] { "FistQueen_TW:2", "FistChitin_TW:1" }, new string[2] { "DualSwordSkadi_TW:1", "DualSpearSvigaFrekk_TW:1" }, "bleeding_secondary"),
			RegisterWarfareAndFireAndIce("decapitator4", "Decapitator4", new string[5] { "BastardDvergr_TW:100", "BastardFlametal_TW:100", "BattleaxeDvergr_TW:100", "BattleaxeFlametal_TW:100", "DualSwordScimitar_TW:100" }, new string[5] { "BastardSurtr_TW:100", "BastardNjord_TW:100", "BattleaxeSurtr_TW:100", "BattleaxeNjord_TW:100", "DualSwordSkadi_TW:100" }),
			RegisterWarfareAndFireAndIce("decapitator5", "Decapitator5", new string[2] { "FistFlametal_TW:100", "ThrowAxeDvergr_TW:100" }, new string[3] { "ThrowAxeSurtr_TW:100", "ThrowAxeNjord_TW:100", "DualAxeKrom_TW:100" }),
			RegisterWarfareAndFireAndIce("executioner", "Executioner", new string[1] { "ClaymoreDvergr_TW:15" }, new string[6] { "ClaymoreNjord_TW:20", "ClaymoreSurtr_TW:20", "BattleaxeDragon_TW:25", "VolcanicBlade_TW:25", "GlacierBlade_TW:25", "LightningBlade_TW:25" }),
			new WarfareBuiltInEffectRegistration("hackAndSlash", "HacknSlash", new string[1] { "FistQueen_TW:100" }, "hacknslash", "hacknSlash"),
			new WarfareBuiltInEffectRegistration("haste", "Haste", new string[2] { "KnifeViper_TW", "FistBlackmetal_TW" }),
			RegisterWarfareAndFireAndIce("impale", "Impale", new string[2] { "LanceBlackmetal_TW:1", "LanceDvergr_TW:2" }, new string[3] { "LanceNjord_TW:1", "LanceSurtr_TW:1", "ClaymoreJotunn_TW:1" }),
			RegisterWarfareAndFireAndIce("juggernaut", "Juggernaut", new string[7] { "WarpikeBone_TW:100", "WarpikeElder_TW:100", "WarpikeChitin_TW:100", "WarpikeObsidian_TW:100", "WarpikeBlackmetal_TW:100", "WarpikeDvergr_TW:100", "WarpikeFlametal_TW:100" }, new string[3] { "WarpikeNjord_TW:100", "WarpikeSurtr_TW:100", "DualSpearSvigaFrekk_TW:100" }),
			new WarfareBuiltInEffectRegistration("pinning", "Pinned", new string[1] { "GreatbowModer_TW:4" }, "pinned"),
			new WarfareBuiltInEffectRegistration("piercingGreatbowMistlands", "PiercingGreatbowMistlands", new string[1] { "GreatbowDvergr_TW:100" }, "piercing_greatbow_mistlands"),
			new WarfareBuiltInEffectRegistration("piercingGreatbowModer", "PiercingGreatbowModer", new string[1] { "GreatbowModer_TW:100" }, "piercing_greatbow_moder"),
			new WarfareBuiltInEffectRegistration("piercingGreatbowPlains", "PiercingGreatbowPlains", new string[1] { "GreatbowBlackmetal_TW:100" }, "piercing_greatbow_plains"),
			RegisterWarfareAndFireAndIce("smasher", "Smasher", new string[2] { "BattlehammerDvergr_TW:100", "BattlehammerElder_TW:100" }, new string[2] { "BattlehammerNjord_TW:100", "BattlehammerSurtr_TW:100" }),
			new WarfareBuiltInEffectRegistration("vampirism", "Vampirism", new string[1] { "ScytheVampiric_TW:6" }),
			new WarfareBuiltInEffectRegistration("bludgeoner", new WarfareEffectTypeSpec[1]
			{
				new WarfareEffectTypeSpec("WarfareFireAndIce_StatusEffects.StatusEffects", "Bludgeoner", new string[1] { "DualHammerRageHatred_TW:100" })
			}),
			new WarfareBuiltInEffectRegistration("burningSecondary", new WarfareEffectTypeSpec[1]
			{
				new WarfareEffectTypeSpec("WarfareFireAndIce_StatusEffects.StatusEffects", "BurningSecondaryAttack", new string[1] { "FistSurtr_TW:1" })
			}, "burning_secondary"),
			new WarfareBuiltInEffectRegistration("lightningBurst", new WarfareEffectTypeSpec[1]
			{
				new WarfareEffectTypeSpec("WarfareFireAndIce_StatusEffects.StatusEffects", "LightningBurst", new string[2] { "DualHammerStormstrike_TW:1", "FistFenrir_TW:1" })
			}),
			new WarfareBuiltInEffectRegistration("pierceGreatbowFireAndIce", new WarfareEffectTypeSpec[1]
			{
				new WarfareEffectTypeSpec("WarfareFireAndIce_StatusEffects.StatusEffects", "PierceGreatbow", new string[2] { "GreatbowNjord_TW:100", "GreatbowSurtr_TW:100" })
			}, "pierceGreatbow", "piercingGreatbowFireAndIce"),
			new WarfareBuiltInEffectRegistration("smashAndBash", new WarfareEffectTypeSpec[1]
			{
				new WarfareEffectTypeSpec("WarfareFireAndIce_StatusEffects.StatusEffects", "SmashnBash", new string[1] { "FistNjord_TW:100" })
			}, "smashnBash")
		};

		private static readonly Dictionary<string, WarfareBuiltInEffectRegistration> RegistrationsByEffectId = BuildRegistrationLookup();

		private static WarfareBuiltInEffectRegistration RegisterWarfareAndFireAndIce(string id, string patchTypeName, string[] warfarePrefabSpecs, string[] fireAndIcePrefabSpecs, params string[] aliases)
		{
			return new WarfareBuiltInEffectRegistration(id, new WarfareEffectTypeSpec[2]
			{
				new WarfareEffectTypeSpec("Warfare_StatusEffects.StatusEffects", patchTypeName, warfarePrefabSpecs),
				new WarfareEffectTypeSpec("WarfareFireAndIce_StatusEffects.StatusEffects", patchTypeName, fireAndIcePrefabSpecs)
			}, aliases);
		}

		private static Dictionary<string, WarfareBuiltInEffectRegistration> BuildRegistrationLookup()
		{
			Dictionary<string, WarfareBuiltInEffectRegistration> dictionary = new Dictionary<string, WarfareBuiltInEffectRegistration>(StringComparer.OrdinalIgnoreCase);
			WarfareBuiltInEffectRegistration[] builtInRegistrations = BuiltInRegistrations;
			foreach (WarfareBuiltInEffectRegistration warfareBuiltInEffectRegistration in builtInRegistrations)
			{
				string[] effectIds = warfareBuiltInEffectRegistration.EffectIds;
				for (int j = 0; j < effectIds.Length; j++)
				{
					string text = effectIds[j]?.Trim() ?? "";
					if (!string.IsNullOrWhiteSpace(text) && !dictionary.ContainsKey(text))
					{
						dictionary.Add(text, warfareBuiltInEffectRegistration);
					}
				}
			}
			return dictionary;
		}

		internal static void TryInstallHooks()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			if (!_hooksInstalled)
			{
				Harmony harmony = new Harmony("sighsorry.WarfareTweaks");
				int num = TryInstallAttackWeaponContextHook(harmony);
				num += TryInstallBuiltInDirectHitGateHooks(harmony);
				num += TryInstallAddToItemGateHooks(harmony);
				num += TryInstallBleedingTuningHooks(harmony);
				num += TryInstallFixedDamageTuningHooks(harmony);
				num += TryInstallHasteTuningHooks(harmony);
				num += TryInstallAdrenalineTuningHooks(harmony);
				if (num > 0)
				{
					_hooksInstalled = true;
					WarfareTweaksPlugin.ModLogger.LogInfo((object)$"Installed {num} Warfare built-in effect hook(s).");
				}
			}
		}

		internal static void RebuildBuiltInEffects(IReadOnlyDictionary<string, EffectBehaviorConfig> effectConfigs)
		{
			SuppressedEffectsByPrefabName.Clear();
			ManagedEffectsByPrefabName.Clear();
			ManagedChainLightningPrefabs.Clear();
			RebuildConfiguredEffectLookup(effectConfigs);
			WarfareBuiltInEffectRegistration[] builtInRegistrations = BuiltInRegistrations;
			string[] prefabNames;
			foreach (WarfareBuiltInEffectRegistration warfareBuiltInEffectRegistration in builtInRegistrations)
			{
				prefabNames = warfareBuiltInEffectRegistration.PrefabNames;
				for (int j = 0; j < prefabNames.Length; j++)
				{
					AddManagedEffect(prefabNames[j], warfareBuiltInEffectRegistration.Id);
				}
				if (!TryFindConfiguredEffect(effectConfigs, warfareBuiltInEffectRegistration, out EffectBehaviorConfig effectConfig) || effectConfig == null)
				{
					AddSuppressedDefaultAssignments(warfareBuiltInEffectRegistration);
					continue;
				}
				foreach (string configuredPrefabName in GetConfiguredPrefabNames(effectConfig))
				{
					AddManagedEffect(configuredPrefabName, warfareBuiltInEffectRegistration.Id);
				}
				AddSuppressedMissingDefaultAssignments(warfareBuiltInEffectRegistration, effectConfig);
			}
			prefabNames = ChainLightningMistlandsDefaultPrefabs;
			foreach (string item in prefabNames)
			{
				ManagedChainLightningPrefabs.Add(item);
			}
			if (!TryFindConfiguredChainLightningEffect(effectConfigs, out string _, out EffectBehaviorConfig effectConfig2) || effectConfig2 == null)
			{
				return;
			}
			foreach (string configuredPrefabName2 in GetConfiguredPrefabNames(effectConfig2))
			{
				ManagedChainLightningPrefabs.Add(configuredPrefabName2);
			}
		}

		internal static void ApplyConfiguredEffects(ObjectDB objectDb, IReadOnlyDictionary<string, EffectBehaviorConfig> effectConfigs, bool logMissingPrefabWarnings = false)
		{
			List<(string, EffectBehaviorConfig)> list = (from entry in effectConfigs
				where entry.Value != null
				select (entry.Key.Trim(), Value: entry.Value) into entry
				where !string.IsNullOrWhiteSpace(entry.Item1)
				select entry).ToList();
			ResetAppliedConfiguredAssignments();
			ResetAppliedPrefabOverrides();
			if (!IsWarfareLoaded())
			{
				if (list.Count > 0 && WarfareTweaksWarningLog.TryMarkReported("warfare_effects_missing_warfare"))
				{
					WarfareTweaksPlugin.ModLogger.LogWarning((object)"Skipping WarfareTweaks.yml warfare effect assignments: Warfare is not installed.");
				}
				return;
			}
			EnsureWarfareGreatbowStatusEffects(objectDb);
			int num = RemoveBuiltInTargetAssignments(effectConfigs);
			if (num > 0)
			{
				WarfareTweaksPlugin.ModLogger.LogInfo((object)string.Format("Removed {0} Warfare built-in effect target assignment(s) before applying {1}.", num, "WarfareTweaks.yml"));
			}
			int num2 = SuppressNativeAttackStatusEffects(objectDb, effectConfigs);
			if (num2 > 0)
			{
				WarfareTweaksPlugin.ModLogger.LogInfo((object)string.Format("Removed {0} Warfare native attack status effect assignment(s) before applying {1}.", num2, "WarfareTweaks.yml"));
			}
			int appliedCount = 0;
			if (!TryFindConfiguredChainLightningEffect(effectConfigs, out string effectId, out EffectBehaviorConfig _))
			{
				SuppressDefaultChainLightningAssignments(objectDb, ref appliedCount);
			}
			if (list.Count == 0)
			{
				if (appliedCount > 0)
				{
					WarfareTweaksPlugin.ModLogger.LogInfo((object)$"Applied {appliedCount} configured Warfare effect assignment(s).");
				}
				return;
			}
			foreach (var (text, effectBehaviorConfig) in list)
			{
				if (TryApplyChainLightningConfig(objectDb, text, effectBehaviorConfig, logMissingPrefabWarnings, out var appliedCount2))
				{
					appliedCount += appliedCount2;
					continue;
				}
				if (!TryFindRegistration(text, out WarfareBuiltInEffectRegistration registration))
				{
					if (WarfareTweaksWarningLog.TryMarkReported("warfare_effect_unknown_" + text))
					{
						WarfareTweaksPlugin.ModLogger.LogWarning((object)("Skipping warfare effect '" + text + "': no matching Warfare built-in effect is known."));
					}
					continue;
				}
				WarfareBuiltInEffectRegistration warfareBuiltInEffectRegistration = registration;
				if (!TryResolveAnyLoadedEffectTypeName(warfareBuiltInEffectRegistration, out string effectTypeName))
				{
					if (!ShouldSilentlySkipMissingOptionalEffect(warfareBuiltInEffectRegistration, effectBehaviorConfig) && WarfareTweaksWarningLog.TryMarkReported("warfare_effect_type_missing_" + warfareBuiltInEffectRegistration.Id))
					{
						WarfareTweaksPlugin.ModLogger.LogWarning((object)("Skipping warfare effect '" + warfareBuiltInEffectRegistration.Id + "': none of its known Warfare type(s) were found."));
					}
					continue;
				}
				foreach (KeyValuePair<string, EffectBehaviorOverrideConfig> item in effectBehaviorConfig.Prefabs ?? new Dictionary<string, EffectBehaviorOverrideConfig>())
				{
					item.Deconstruct(out effectId, out var value);
					string text2 = effectId;
					EffectBehaviorOverrideConfig prefabOverride = value;
					string text3 = text2?.Trim() ?? "";
					if (string.IsNullOrWhiteSpace(text3))
					{
						continue;
					}
					if (!ContainsObjectDbItem(objectDb, text3))
					{
						if (!ShouldSilentlySkipMissingOptionalDefaultPrefab(warfareBuiltInEffectRegistration, text3) && logMissingPrefabWarnings && WarfareTweaksWarningLog.TryMarkReported("warfare_effect_prefab_missing_" + warfareBuiltInEffectRegistration.Id + "_" + text3))
						{
							WarfareTweaksPlugin.ModLogger.LogWarning((object)("Skipping warfare effect '" + warfareBuiltInEffectRegistration.Id + "' on '" + text3 + "': prefab was not found in ObjectDB."));
						}
						continue;
					}
					string text4 = ResolveEffectTypeNameForPrefab(warfareBuiltInEffectRegistration, text3) ?? effectTypeName;
					Type type = FindLoadedType(text4);
					if (type == null)
					{
						if (WarfareTweaksWarningLog.TryMarkReported("warfare_effect_type_missing_" + warfareBuiltInEffectRegistration.Id + "_" + text3))
						{
							WarfareTweaksPlugin.ModLogger.LogWarning((object)("Skipping warfare effect '" + warfareBuiltInEffectRegistration.Id + "' on '" + text3 + "': Warfare type '" + text4 + "' was not found."));
						}
						continue;
					}
					int? value2 = ResolveConfiguredWarfareValue(warfareBuiltInEffectRegistration, effectBehaviorConfig, prefabOverride, te