Decompiled source of Runes Redone v1.0.0

plugins/RunesRedone.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SideLoader;
using SideLoader.Model;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("RunesRedone")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RunesRedone")]
[assembly: AssemblyTitle("RunesRedone")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RunicBow
{
	public static class RunicBowManager
	{
		[HarmonyPatch(typeof(WeaponLoadoutItem), "ShootItemFromLoadout")]
		public class WeaponLoadoutItem_ShootItemFromLoadout
		{
			[HarmonyPrefix]
			public static void Prefix(ProjectileItem _projItem)
			{
				if (!((Object)(object)_projItem == (Object)null) && !((Component)_projItem).gameObject.activeSelf)
				{
					((Component)_projItem).gameObject.SetActive(true);
				}
			}
		}

		[HarmonyPatch]
		public class AttackAttempt_Begin
		{
			public static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(Character), "StartAttack", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Weapon), "OnStartCharging", (Type[])null, (Type[])null);
			}

			[HarmonyPrefix]
			public static void Prefix()
			{
				InAttackAttempt = true;
			}

			[HarmonyFinalizer]
			public static Exception Finalizer()
			{
				InAttackAttempt = false;
				return null;
			}
		}

		[HarmonyPatch(typeof(Character), "AttackReleased")]
		public class Character_AttackReleased
		{
			[HarmonyPostfix]
			public static void Postfix()
			{
				ManaNotified = false;
			}
		}

		[HarmonyPatch(typeof(CharacterUI), "ShowInfoNotificationLoc", new Type[] { typeof(string) })]
		public class CharacterUI_ShowInfoNotificationLoc
		{
			[HarmonyPrefix]
			public static bool Prefix(string _localizationKey)
			{
				if (_localizationKey != "Notification_ProjectileWeapon_NoAmmunition")
				{
					return true;
				}
				if (Time.time - ManaRefusedAt <= 0.5f)
				{
					return false;
				}
				if (Time.time - ArrowRestoreAt <= 0.75f)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(ProjectileItem), "AssignVisual")]
		public class ProjectileItem_AssignVisual
		{
			[HarmonyPrefix]
			public static void Prefix(ref Projectile ___m_projectile, ProjectileItem __instance)
			{
				___m_projectile = ((Component)__instance).GetComponent<Projectile>();
			}
		}

		[HarmonyPatch(typeof(PlayerCharacterStats), "OnUpdateStats")]
		public class PlayerStats_Update
		{
			[HarmonyFinalizer]
			public static Exception Finalizer(PlayerCharacterStats __instance)
			{
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Invalid comparison between Unknown and I4
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Expected O, but got Unknown
				Character component = ((Component)__instance).GetComponent<Character>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					return null;
				}
				if (!CharChargingAttack.Invoke(component) || !CharBowDrawn.Invoke(component))
				{
					return null;
				}
				if (Object.op_Implicit((Object)(object)component.CurrentWeapon) && (int)component.CurrentWeapon.Type == 200)
				{
					WeaponCharger val = (WeaponCharger)((Item)component.CurrentWeapon).GetExtension("WeaponCharger");
					if (!val.ChargeStarted && val.StartChargeTime < 0.0)
					{
						CharChargingAttack.Invoke(component) = false;
						CharBowDrawn.Invoke(component) = false;
					}
				}
				return null;
			}
		}

		[HarmonyPatch(typeof(EffectSynchronizer), "RegisterEffectReference")]
		public class EffectSynchronizer_RegisterEffectReference
		{
			[HarmonyPrefix]
			public static void Prefix(EffectSynchronizer __instance, ref List<string>[] ___m_categoryEffects)
			{
				if (___m_categoryEffects == null)
				{
					___m_categoryEffects = new List<string>[EffectSynchronizer.EffectCategoriesCount];
					for (int i = 0; i < ___m_categoryEffects.Length; i++)
					{
						___m_categoryEffects[i] = new List<string>();
					}
				}
			}
		}

		[HarmonyPatch(typeof(ProjectileWeapon), "UpdateProcessing")]
		public class ProjectileWeapon_UpdateProcessing
		{
			[HarmonyPostfix]
			public static void Postfix(ProjectileWeapon __instance, ref bool ___m_fullyBent)
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				if (IsRunicBow((Item)(object)__instance) & ___m_fullyBent)
				{
					Character ownerCharacter = ((EffectSynchronizer)__instance).OwnerCharacter;
					if (!Object.op_Implicit((Object)(object)ownerCharacter.Inventory.Equipment.GetEquippedItem((EquipmentSlotIDs)8)))
					{
						___m_fullyBent = false;
						CharChargingAttack.Invoke(ownerCharacter) = false;
						ownerCharacter.BowRelease();
						((WeaponCharger)((Item)__instance).GetExtension("WeaponCharger")).ResetCharging();
					}
				}
			}
		}

		[HarmonyPatch(typeof(ProjectileItem), "ForceReturn")]
		public class ProjectileItem_ForceReturn
		{
			[HarmonyFinalizer]
			public static Exception Finalizer()
			{
				return null;
			}
		}

		[HarmonyPatch(typeof(WeaponLoadout), "CanBeLoaded")]
		public class WeaponLoadout_CanBeLoaded
		{
			[HarmonyPrefix]
			public static bool Prefix(WeaponLoadout __instance, ref bool __result)
			{
				Item item = ((ItemExtension)__instance).Item;
				if (IsRunicBow(item))
				{
					Character ownerCharacter = ((EffectSynchronizer)item).OwnerCharacter;
					if (Object.op_Implicit((Object)(object)ownerCharacter) && !ownerCharacter.IsLocalPlayer)
					{
						return true;
					}
					__result = CanBeLoaded(item);
					return false;
				}
				return true;
			}

			public static bool CanBeLoaded(Item item)
			{
				//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: Expected O, but got Unknown
				Character ownerCharacter = ((EffectSynchronizer)item).OwnerCharacter;
				if (!Object.op_Implicit((Object)(object)ownerCharacter))
				{
					Debug.Log((object)"Runic bow has no owner!");
					return false;
				}
				float currentMana = ownerCharacter.Stats.CurrentMana;
				float finalManaConsumption = ownerCharacter.Stats.GetFinalManaConsumption((Tag[])null, 5f);
				if (currentMana - finalManaConsumption < 0f)
				{
					ManaRefusedAt = Time.time;
					if ((InAttackAttempt || Time.time - SkillAttemptAt <= 3f) && !ManaNotified)
					{
						ManaNotified = true;
						ownerCharacter.CharacterUI.ShowInfoNotificationLoc("Notification_Skill_NotEnoughtMana");
					}
					return false;
				}
				Ammunition equippedAmmunition = ownerCharacter.Inventory.GetEquippedAmmunition();
				if ((Object)(object)equippedAmmunition == (Object)null)
				{
					List<Item> ownedItems = ownerCharacter.Inventory.GetOwnedItems(-88001);
					Ammunition val = (Ammunition)((ownedItems == null || ownedItems.Count <= 0) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)(Ammunition)ownedItems[0]));
					ownerCharacter.Inventory.TakeItem((Item)(object)val, true);
					equippedAmmunition = ownerCharacter.Inventory.GetEquippedAmmunition();
				}
				if ((Object)(object)equippedAmmunition == (Object)null || ((Item)equippedAmmunition).ItemID != -88001)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch]
		public class WeaponLoadout_ReduceShotAmount
		{
			[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
			[HarmonyPatch(typeof(WeaponLoadout), "ReduceShotAmount")]
			public static void ReversePatch(object instance, bool _destroyOnEmpty)
			{
				throw new NotImplementedException("WeaponLoadoutRP.ReduceShotAmount");
			}

			[HarmonyPrefix]
			[HarmonyPatch(typeof(WeaponLoadout), "ReduceShotAmount")]
			[HarmonyPatch(typeof(WeaponLoadoutItem), "ReduceShotAmount")]
			[HarmonyBefore(new string[] { "com.SpicerXD.RaidMode" })]
			public static bool Prefix(WeaponLoadout __instance, bool _destroyOnEmpty)
			{
				//IL_0124: Unknown result type (might be due to invalid IL or missing references)
				Item item = ((ItemExtension)__instance).Item;
				if (IsRunicBow(item))
				{
					Character ownerCharacter = ((EffectSynchronizer)item).OwnerCharacter;
					if (Object.op_Implicit((Object)(object)ownerCharacter) && ownerCharacter.IsLocalPlayer)
					{
						ownerCharacter.Stats.UseMana((Tag[])null, 5f);
					}
					RemainingShots.Invoke(__instance)--;
					if (RemainingShots.Invoke(__instance) < 0)
					{
						RemainingShots.Invoke(__instance) = 0;
					}
					if (RemainingShots.Invoke(__instance) == 0)
					{
						__instance.Unload();
					}
					SetHasChanged((ItemExtension)(object)__instance);
					return false;
				}
				WeaponLoadoutItem val = (WeaponLoadoutItem)(object)((__instance is WeaponLoadoutItem) ? __instance : null);
				if (val != null)
				{
					if (!val.ReduceAmmunitionOnLoad)
					{
						Ammunition val2 = LoadedAmmunition.Invoke(val);
						if ((Object)(object)val2 != (Object)null && ((EffectSynchronizer)((ItemExtension)__instance).Item).OwnerCharacter.IsLocalPlayer)
						{
							Global.RPCManager.SendSkillUseItem(((Item)val2).UID, 1);
							if (PhotonNetwork.isNonMasterClientInRoom && ((Item)val2).RemainingAmount < 1)
							{
								int remainingAmount = ((Item)val2).RemainingAmount;
								((Item)val2).RemainingAmount = remainingAmount - 1;
							}
						}
						if (_destroyOnEmpty)
						{
							LoadedAmmunition.Invoke(val) = null;
						}
						else if ((Object)(object)val2 == (Object)null || ((Item)val2).RemainingAmount == 0)
						{
							if (Object.op_Implicit((Object)(object)val2))
							{
								((Item)val2).SaveType = (SaveTypes)2;
							}
							List<Item> list = LastLoadedItems.Invoke(val);
							if (list.Count > 0)
							{
								list.RemoveAt(0);
							}
							if (list.Count > 0)
							{
								ref Ammunition reference = ref LoadedAmmunition.Invoke(val);
								Item obj = list[0];
								reference = (Ammunition)(object)((obj is Ammunition) ? obj : null);
							}
						}
					}
					ReversePatch(__instance, _destroyOnEmpty);
					if (val.ReduceAmmunitionOnLoad)
					{
						((ItemExtension)__instance).DataSynced();
					}
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(AttackSkill), "OwnerHasAllRequiredItems")]
		public class AttackSkill_OwnerHasAllRequiredItems
		{
			[HarmonyPrefix]
			public static bool Prefix(AttackSkill __instance, bool _TryingToActivate, ref bool __result)
			{
				if (!(__instance is RangeAttackSkill))
				{
					return true;
				}
				if (Object.op_Implicit((Object)(object)((EffectSynchronizer)__instance).OwnerCharacter))
				{
					Weapon currentWeapon = ((EffectSynchronizer)__instance).OwnerCharacter.CurrentWeapon;
					ProjectileWeapon val = (ProjectileWeapon)(object)((currentWeapon is ProjectileWeapon) ? currentWeapon : null);
					if (val != null && IsRunicBow((Item)(object)val))
					{
						__result = WeaponLoadout_CanBeLoaded.CanBeLoaded((Item)(object)val);
						return false;
					}
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(UseLoadoutAmunition), "TryTriggerConditions")]
		public class UseLoadoutAmmunition_TryTriggerConditions
		{
			[HarmonyPrefix]
			public static bool Prefix(UseLoadoutAmunition __instance, ref bool __result)
			{
				if (__instance.MainHand)
				{
					Weapon currentWeapon = ((Effect)__instance).OwnerCharacter.CurrentWeapon;
					ProjectileWeapon val = (ProjectileWeapon)(object)((currentWeapon is ProjectileWeapon) ? currentWeapon : null);
					if (val != null && IsRunicBow((Item)(object)val))
					{
						__result = true;
						return false;
					}
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(UseLoadoutAmunition), "ActivateLocally")]
		public class UseLoadoutAmmunition_ActivateLocally
		{
			[HarmonyPrefix]
			public static bool Prefix(UseLoadoutAmunition __instance, Character _affectedCharacter, object[] _infos)
			{
				if (__instance.MainHand)
				{
					Weapon currentWeapon = _affectedCharacter.CurrentWeapon;
					ProjectileWeapon val = (ProjectileWeapon)(object)((currentWeapon is ProjectileWeapon) ? currentWeapon : null);
					if (val != null && IsRunicBow((Item)(object)val))
					{
						WeaponLoadout_ReduceShotAmount.Prefix(((Component)val).GetComponent<WeaponLoadout>(), __instance.DestroyOnEmpty);
						return false;
					}
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(CharacterInventory), "PlayEquipSFX")]
		public class CharacterInventory_PlayEquipSFX
		{
			[HarmonyPrefix]
			public static bool Prefix(CharacterInventory __instance, Equipment _equipment)
			{
				return ((Item)_equipment).ItemID != -88001;
			}
		}

		[HarmonyPatch(typeof(CharacterInventory), "PlayUnequipSFX")]
		public class CharacterInventory_PlayUnequipSFX
		{
			[HarmonyPrefix]
			public static bool Prefix(CharacterInventory __instance, Equipment _equipment)
			{
				return ((Item)_equipment).ItemID != -88001;
			}
		}

		[HarmonyPatch(typeof(Item), "TryQuickSlotUse")]
		public class Item_TryQuickSlotUse
		{
			[HarmonyPrefix]
			public static void Prefix(Item __instance)
			{
				if (__instance is Skill)
				{
					SkillAttemptAt = Time.time;
					ManaNotified = false;
				}
			}
		}

		[HarmonyPatch(typeof(Equipment), "OnEquip")]
		public class Equipment_OnEquip
		{
			[HarmonyPostfix]
			public static void Postfix(Equipment __instance, Character _char)
			{
				if (Object.op_Implicit((Object)(object)__instance))
				{
					Ammunition val = (Ammunition)(object)((__instance is Ammunition) ? __instance : null);
					bool num = (Object)(object)val != (Object)null && ((Item)val).ItemID != -88001;
					bool flag = ((Item)__instance).ItemID == -88000;
					if ((num || flag) && Object.op_Implicit((Object)(object)_char) && _char.IsLocalPlayer && !((Object)(object)_char.Inventory == (Object)null) && _char.Inventory.OwnsItem(-88000) && Object.op_Implicit((Object)(object)RunicBowPlugin.Instance))
					{
						ArrowRestoreAt = Time.time;
						((MonoBehaviour)RunicBowPlugin.Instance).StartCoroutine(RestoreRunicArrowNextFrame(_char));
					}
				}
			}
		}

		[HarmonyPatch(typeof(CharacterEquipment), "UnequipItem", new Type[]
		{
			typeof(Equipment),
			typeof(bool),
			typeof(ItemContainer)
		})]
		public class CharacterEquipment_UnequipItem
		{
			[HarmonyPostfix]
			public static void Postfix(CharacterEquipment __instance, Equipment _itemToUnequip)
			{
				if (Object.op_Implicit((Object)(object)_itemToUnequip) && ((Item)_itemToUnequip).ItemID == -88001)
				{
					Character ownerCharacter = ((EffectSynchronizer)_itemToUnequip).OwnerCharacter;
					if (Object.op_Implicit((Object)(object)ownerCharacter) && ownerCharacter.IsLocalPlayer && !((Object)(object)ownerCharacter.Inventory == (Object)null) && ownerCharacter.Inventory.OwnsItem(-88000) && Object.op_Implicit((Object)(object)RunicBowPlugin.Instance))
					{
						ArrowRestoreAt = Time.time;
						((MonoBehaviour)RunicBowPlugin.Instance).StartCoroutine(ReEquipArrowNextFrame(ownerCharacter, _itemToUnequip));
					}
				}
			}
		}

		[HarmonyPatch(typeof(SummonedEquipment), "FreeSummon")]
		public class SummonedEquipment_FreeSummon
		{
			private static readonly HashSet<string> Held = new HashSet<string>();

			[HarmonyPrefix]
			public static bool Prefix(SummonedEquipment __instance, bool _expired, out bool __state)
			{
				__state = false;
				if (!_expired || !Object.op_Implicit((Object)(object)__instance))
				{
					return true;
				}
				Item item = ((ItemExtension)__instance).Item;
				if (!Object.op_Implicit((Object)(object)item) || item.ItemID != -88000)
				{
					return true;
				}
				Character ownerCharacter = ((EffectSynchronizer)item).OwnerCharacter;
				if (!Object.op_Implicit((Object)(object)ownerCharacter) || (!CharChargingAttack.Invoke(ownerCharacter) && !ownerCharacter.RangeSkillAim))
				{
					if (Held.Remove(item.UID))
					{
						RunicBowPlugin.Log.LogMessage((object)"Runic Bow expired after the draw ended.");
					}
					return true;
				}
				if (Held.Add(item.UID))
				{
					RunicBowPlugin.Log.LogMessage((object)"Runic Bow expired mid-draw - held until the draw ends.");
				}
				SummonUnsummonWanted.Invoke(__instance) = true;
				__state = true;
				return false;
			}

			[HarmonyPostfix]
			public static void Postfix(SummonedEquipment __instance, bool _expired, bool __state)
			{
				if (__state || !Object.op_Implicit((Object)(object)__instance))
				{
					return;
				}
				Item item = ((ItemExtension)__instance).Item;
				if (!Object.op_Implicit((Object)(object)item) || item.ItemID != -88000)
				{
					return;
				}
				Character ownerCharacter = ((EffectSynchronizer)item).OwnerCharacter;
				if (Object.op_Implicit((Object)(object)ownerCharacter) && !((Object)(object)ownerCharacter.StatusEffectMngr == (Object)null))
				{
					StatusEffect statusEffectOfName = ownerCharacter.StatusEffectMngr.GetStatusEffectOfName("RunicBow");
					if (Object.op_Implicit((Object)(object)statusEffectOfName))
					{
						ownerCharacter.StatusEffectMngr.CleanseStatusEffect(statusEffectOfName);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Item), "ChangeOwner")]
		public class Item_ChangeOwner
		{
			[HarmonyPrefix]
			public static void Prefix(Item __instance, Character _newOwner, out Character __state)
			{
				__state = null;
				if (IsRunicBow(__instance) && (Object)(object)((EffectSynchronizer)__instance).OwnerCharacter != (Object)(object)_newOwner)
				{
					__state = ((EffectSynchronizer)__instance).OwnerCharacter;
				}
			}

			[HarmonyPostfix]
			public static void Postfix(Character __state)
			{
				if ((Object)(object)__state != (Object)null)
				{
					CleanupArrowsIfBowGone(__state);
				}
			}
		}

		[HarmonyPatch(typeof(Item), "AboutToBeDestroyed")]
		public class Item_AboutToBeDestroyed
		{
			[HarmonyPatch(typeof(StatusEffectManager), "AddStatusEffect", new Type[]
			{
				typeof(StatusEffect),
				typeof(Character),
				typeof(string[])
			})]
			public class StatusEffectManager_AddStatusEffect_BanishedBossGate
			{
				private static readonly FieldRef<StatusEffectManager, Character> ManagerCharacter = AccessTools.FieldRefAccess<StatusEffectManager, Character>("m_character");

				[HarmonyPrefix]
				public static bool Prefix(StatusEffectManager __instance, StatusEffect _statusEffect, ref StatusEffect __result)
				{
					if ((Object)(object)_statusEffect == (Object)null || _statusEffect.IdentifierName != "Banished")
					{
						return true;
					}
					Character val = ManagerCharacter.Invoke(__instance);
					if (!Object.op_Implicit((Object)(object)val) || !val.HasEventOnDeath)
					{
						return true;
					}
					__result = null;
					return false;
				}
			}

			[HarmonyPatch(typeof(StatusEffectManager), "AddStatusEffect", new Type[]
			{
				typeof(StatusEffect),
				typeof(Character),
				typeof(string[])
			})]
			public class StatusEffectManager_AddStatusEffect_BanishedRestore
			{
				private static readonly FieldRef<StatusEffectManager, Character> ManagerCharacter = AccessTools.FieldRefAccess<StatusEffectManager, Character>("m_character");

				[HarmonyPostfix]
				public static void Postfix(StatusEffectManager __instance, StatusEffect __result)
				{
					if (!((Object)(object)__result == (Object)null) && !(__result.IdentifierName != "Banished") && !((Component)__result).gameObject.activeInHierarchy)
					{
						Character val = ManagerCharacter.Invoke(__instance);
						if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val.StatusEffectMngr == (Object)null) && Object.op_Implicit((Object)(object)RunicBowPlugin.Instance))
						{
							((MonoBehaviour)RunicBowPlugin.Instance).StartCoroutine(CleanseBanishedNextFrame(val));
						}
					}
				}
			}

			[HarmonyPrefix]
			public static void Prefix(Item __instance)
			{
				if (IsRunicBow(__instance))
				{
					Character ownerCharacter = ((EffectSynchronizer)__instance).OwnerCharacter;
					if (Object.op_Implicit((Object)(object)ownerCharacter) && Object.op_Implicit((Object)(object)RunicBowPlugin.Instance))
					{
						((MonoBehaviour)RunicBowPlugin.Instance).StartCoroutine(CleanupNextFrame(ownerCharacter));
					}
				}
			}

			private static IEnumerator CleanseBanishedNextFrame(Character affected)
			{
				yield return null;
				if (Object.op_Implicit((Object)(object)affected) && !((Object)(object)affected.StatusEffectMngr == (Object)null))
				{
					StatusEffect statusEffectOfName = affected.StatusEffectMngr.GetStatusEffectOfName("Banished");
					if (Object.op_Implicit((Object)(object)statusEffectOfName))
					{
						affected.StatusEffectMngr.CleanseStatusEffect(statusEffectOfName);
					}
				}
			}
		}

		private const string RunicBowTagString = "RunicBow";

		public const int RunicArrowID = -88001;

		public const int RunicBowID = -88000;

		public const float RunicBowCost = 5f;

		public static Tag RunicBowTag;

		private static float ManaRefusedAt = -99f;

		private const float ManaRefusalWindow = 0.5f;

		private static bool InAttackAttempt;

		private static float SkillAttemptAt = -99f;

		private const float SkillAttemptWindow = 3f;

		private static bool ManaNotified;

		private const float ArrowUnequipSettleWindow = 0.5f;

		private static float ArrowRestoreAt = -999f;

		private const float ArrowRestoreWindow = 0.75f;

		private const float LoadWaitTimeout = 15f;

		private const float LoadSettleGrace = 0.25f;

		private const string RunicBowStatusIdentifier = "RunicBow";

		private const string BanishedStatusIdentifier = "Banished";

		private static readonly FieldRef<Character, bool> CharChargingAttack = AccessTools.FieldRefAccess<Character, bool>("m_currentlyChargingAttack");

		private static readonly FieldRef<Character, bool> CharBowDrawn = AccessTools.FieldRefAccess<Character, bool>("m_bowDrawn");

		private static readonly FieldRef<SummonedEquipment, bool> SummonUnsummonWanted = AccessTools.FieldRefAccess<SummonedEquipment, bool>("m_unsummonWanted");

		private static readonly FieldRef<CharacterEquipment, Character> EquipmentOwner = AccessTools.FieldRefAccess<CharacterEquipment, Character>("m_character");

		private static readonly FieldRef<ProjectileItem, int> ProjectileItemID = AccessTools.FieldRefAccess<ProjectileItem, int>("m_itemID");

		private static readonly FieldRef<ProjectileItem, Item> ProjectileItemPrefab = AccessTools.FieldRefAccess<ProjectileItem, Item>("m_item");

		private static readonly FieldRef<WeaponLoadout, int> RemainingShots = AccessTools.FieldRefAccess<WeaponLoadout, int>("m_remainingShots");

		private static readonly FieldRef<WeaponLoadoutItem, Ammunition> LoadedAmmunition = AccessTools.FieldRefAccess<WeaponLoadoutItem, Ammunition>("m_loadedAmmunition");

		private static readonly FieldRef<WeaponLoadoutItem, List<Item>> LastLoadedItems = AccessTools.FieldRefAccess<WeaponLoadoutItem, List<Item>>("m_lastLoadedItems");

		private static readonly Action<ItemExtension> SetHasChanged = AccessTools.MethodDelegate<Action<ItemExtension>>(AccessTools.Method(typeof(ItemExtension), "SetHasChanged", (Type[])null, (Type[])null), (object)null, true);

		public static bool IsRunicBow(Item item)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)item))
			{
				return item.HasTag(RunicBowTag);
			}
			return false;
		}

		private static void CleanupArrowsIfBowGone(Character owner)
		{
			if (!PhotonNetwork.isMasterClient || !Object.op_Implicit((Object)(object)owner) || (Object)(object)owner.Inventory == (Object)null || owner.Inventory.OwnsItem(-88000))
			{
				return;
			}
			List<string> list = new List<string>();
			Ammunition equippedAmmunition = owner.Inventory.GetEquippedAmmunition();
			if (Object.op_Implicit((Object)(object)equippedAmmunition) && ((Item)equippedAmmunition).ItemID == -88001)
			{
				list.Add(((Item)equippedAmmunition).UID);
			}
			List<Item> ownedItems = owner.Inventory.GetOwnedItems(-88001);
			if (ownedItems != null)
			{
				for (int i = 0; i < ownedItems.Count; i++)
				{
					if ((Object)(object)ownedItems[i] != (Object)null && !list.Contains(ownedItems[i].UID))
					{
						list.Add(ownedItems[i].UID);
					}
				}
			}
			for (int j = 0; j < list.Count; j++)
			{
				ItemManager.Instance.DestroyItem(list[j]);
			}
		}

		private static IEnumerator CleanupNextFrame(Character owner)
		{
			yield return null;
			CleanupArrowsIfBowGone(owner);
		}

		private static bool AnyRunicBowExists()
		{
			ItemManager instance = ItemManager.Instance;
			if (!Object.op_Implicit((Object)(object)instance) || instance.WorldItems == null)
			{
				return true;
			}
			for (int i = 0; i < instance.WorldItems.Count; i++)
			{
				Item val = instance.WorldItems.Values[i];
				if (Object.op_Implicit((Object)(object)val) && val.ItemID == -88000)
				{
					return true;
				}
			}
			return false;
		}

		private static Character LocalPlayer()
		{
			if (!Object.op_Implicit((Object)(object)CharacterManager.Instance))
			{
				return null;
			}
			foreach (Character value in CharacterManager.Instance.Characters.Values)
			{
				if (Object.op_Implicit((Object)(object)value) && value.IsLocalPlayer)
				{
					return value;
				}
			}
			return null;
		}

		internal static void OnGameplayResumed()
		{
			if (Object.op_Implicit((Object)(object)RunicBowPlugin.Instance))
			{
				((MonoBehaviour)RunicBowPlugin.Instance).StartCoroutine(ReconcileBowStatusAfterLoad());
			}
		}

		private static IEnumerator ReconcileBowStatusAfterLoad()
		{
			while (Object.op_Implicit((Object)(object)NetworkLevelLoader.Instance) && NetworkLevelLoader.Instance.IsGameplayPaused)
			{
				yield return null;
			}
			float deadline = Time.time + 15f;
			while (Object.op_Implicit((Object)(object)ItemManager.Instance) && (!ItemManager.Instance.SceneLoaded || !ItemManager.Instance.FirstSyncCompleted))
			{
				if (Time.time > deadline)
				{
					yield break;
				}
				yield return null;
			}
			yield return (object)new WaitForSeconds(0.25f);
			Character val = LocalPlayer();
			if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val.StatusEffectMngr == (Object)null) && !AnyRunicBowExists())
			{
				StatusEffect statusEffectOfName = val.StatusEffectMngr.GetStatusEffectOfName("RunicBow");
				if (Object.op_Implicit((Object)(object)statusEffectOfName))
				{
					val.StatusEffectMngr.CleanseStatusEffect(statusEffectOfName);
					RunicBowPlugin.Log.LogMessage((object)"Cleared an orphaned Runic Bow status - the bow did not survive the load.");
				}
			}
		}

		public static void BeforePacksLoaded()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			RunicBowTag = CustomTags.CreateTag("RunicBow");
			Type typeByName = At.GetTypeByName("RaidMode.CharacterEquipment_Update");
			if (typeByName != null)
			{
				MethodInfo method = typeByName.GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public);
				RunicBowPlugin.harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(RunicBowManager), "FixRaidModePatch", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		public static bool FixRaidModePatch(CharacterEquipment __0)
		{
			return !IsRunicBow((Item)(object)EquipmentOwner.Invoke(__0).CurrentWeapon);
		}

		public static void OnPacksLoaded()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			Item itemPrefab = ResourcesPrefabManager.Instance.GetItemPrefab(-88001);
			Ammunition val = (Ammunition)(object)((itemPrefab is Ammunition) ? itemPrefab : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Debug.LogError((object)("[Runic Bow] Could not find the Runic Arrow prefab (ID " + -88001 + "). Check that SideLoader/Items/-88001_RunicArrow is present and its New_ItemID matches."));
				return;
			}
			ItemVisualsLink orAddVisualLink = CustomItemVisuals.GetOrAddVisualLink((Item)(object)val);
			orAddVisualLink.ItemSpecialVisuals = new GameObject("RunicQuiverDummy").transform;
			Object.DontDestroyOnLoad((Object)(object)((Component)orAddVisualLink.ItemSpecialVisuals).gameObject);
			GameObject gameObject = ((Component)val.ProjectileFXPrefab).gameObject;
			gameObject.SetActive(false);
			val.ProjectileFXPrefab = Object.Instantiate<GameObject>(gameObject).transform;
			gameObject.SetActive(true);
			Item itemPrefab2 = ResourcesPrefabManager.Instance.GetItemPrefab(-88000);
			StatusEffect statusEffectPrefab = ResourcesPrefabManager.Instance.GetStatusEffectPrefab("RunicBow");
			if (Object.op_Implicit((Object)(object)itemPrefab2) && Object.op_Implicit((Object)(object)statusEffectPrefab))
			{
				SummonedEquipment component = ((Component)itemPrefab2).GetComponent<SummonedEquipment>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.StatusIcon = statusEffectPrefab.StatusIcon;
				}
				else
				{
					Debug.LogWarning((object)"[Runic Bow] No SummonedEquipment on the bow prefab - check that SideLoader/Items/-88000_RunicBow has the SL_SummonedEquipment extension.");
				}
			}
			Object.DontDestroyOnLoad((Object)(object)((Component)val.ProjectileFXPrefab).gameObject);
			ProjectileItem component2 = ((Component)val.ProjectileFXPrefab).GetComponent<ProjectileItem>();
			component2.CollisionBehavior = (CollisionBehaviorTypes)2;
			component2.EphemeralProjectile = true;
			ProjectileItemID.Invoke(component2) = -88001;
			ProjectileItemPrefab.Invoke(component2) = ResourcesPrefabManager.Instance.GetItemPrefab(-88001);
			RaycastProjectile component3 = ((Component)component2).GetComponent<RaycastProjectile>();
			((Projectile)component3).ProjectileVisualsToDisable = ((Component)component2).gameObject;
			((Projectile)component3).ImpactSoundMaterial = (EquipmentSoundMaterials)0;
			((MonoBehaviour)RunicBowPlugin.Instance).StartCoroutine(LateFix());
		}

		private static IEnumerator LateFix()
		{
			yield return (object)new WaitForSeconds(1f);
			foreach (int item in new List<int> { 8200100, 8200101, 8200102, 8200103, 2502001, 8200310 })
			{
				Item itemPrefab = ResourcesPrefabManager.Instance.GetItemPrefab(item);
				AttackSkill val = (AttackSkill)(object)((itemPrefab is AttackSkill) ? itemPrefab : null);
				if (val != null && !val.RequiredWeaponTypes.Contains((WeaponType)200))
				{
					val.RequiredWeaponTypes.Add((WeaponType)200);
				}
			}
		}

		private static IEnumerator RestoreRunicArrowNextFrame(Character owner)
		{
			yield return null;
			if (!Object.op_Implicit((Object)(object)owner) || (Object)(object)owner.Inventory == (Object)null || !owner.Inventory.OwnsItem(-88000))
			{
				yield break;
			}
			Ammunition equippedAmmunition = owner.Inventory.GetEquippedAmmunition();
			if (Object.op_Implicit((Object)(object)equippedAmmunition) && ((Item)equippedAmmunition).ItemID == -88001)
			{
				yield break;
			}
			Equipment arrow = null;
			float waited = 0f;
			while (waited < 0.5f)
			{
				if (!Object.op_Implicit((Object)(object)owner) || (Object)(object)owner.Inventory == (Object)null || !owner.Inventory.OwnsItem(-88000))
				{
					yield break;
				}
				List<Item> ownedItems = owner.Inventory.GetOwnedItems(-88001);
				arrow = (Equipment)((ownedItems != null && ownedItems.Count > 0) ? /*isinst with value type is only supported in some contexts*/: null);
				if (Object.op_Implicit((Object)(object)arrow))
				{
					break;
				}
				waited += Time.deltaTime;
				yield return null;
			}
			if (Object.op_Implicit((Object)(object)arrow))
			{
				owner.Inventory.Equipment.EquipItem(arrow, false);
				yield break;
			}
			equippedAmmunition = owner.Inventory.GetEquippedAmmunition();
			if (Object.op_Implicit((Object)(object)equippedAmmunition))
			{
				owner.Inventory.Equipment.UnequipItem((Equipment)(object)equippedAmmunition, false, owner.Inventory.Pouch);
			}
		}

		private static IEnumerator ReEquipArrowNextFrame(Character owner, Equipment arrow)
		{
			yield return null;
			if (!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)arrow) || (Object)(object)owner.Inventory == (Object)null || !owner.Inventory.OwnsItem(-88000))
			{
				yield break;
			}
			float waited = 0f;
			while (waited < 0.5f)
			{
				if (!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)arrow) || (Object)(object)owner.Inventory == (Object)null || !owner.Inventory.OwnsItem(-88000))
				{
					yield break;
				}
				Ammunition equippedAmmunition = owner.Inventory.GetEquippedAmmunition();
				if (!Object.op_Implicit((Object)(object)equippedAmmunition) || ((Item)equippedAmmunition).ItemID != -88001)
				{
					break;
				}
				waited += Time.deltaTime;
				yield return null;
			}
			Ammunition equippedAmmunition2 = owner.Inventory.GetEquippedAmmunition();
			if (!Object.op_Implicit((Object)(object)equippedAmmunition2) || ((Item)equippedAmmunition2).ItemID != -88001)
			{
				owner.Inventory.Equipment.EquipItem(arrow, false);
			}
		}
	}
	[BepInPlugin("com.wrango.runesredone.bow", "Runes Redone - Bow", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency("com.wrango.customeffects", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RunicBowPlugin : BaseUnityPlugin
	{
		public const string GUID = "com.wrango.runesredone.bow";

		public const string NAME = "Runes Redone - Bow";

		public const string VERSION = "1.0.0";

		public static RunicBowPlugin Instance;

		public static Harmony harmony;

		internal static ManualLogSource Log;

		internal void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("com.wrango.runesredone.bow");
			SL.BeforePacksLoaded += RunicBowManager.BeforePacksLoaded;
			SL.OnPacksLoaded += RunicBowManager.OnPacksLoaded;
			SL.OnGameplayResumedAfterLoading += RunicBowManager.OnGameplayResumed;
			try
			{
				Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(RunicBowPlugin).Assembly);
				foreach (Type type in typesFromAssembly)
				{
					if (type.Namespace == "RunicBow")
					{
						harmony.CreateClassProcessor(type).Patch();
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Harmony patching failed - the bow will not work correctly: " + ex));
			}
			Log.LogMessage((object)"Runes Redone - Bow 1.0.0 loaded.");
		}
	}
}
namespace RunesRedone
{
	internal static class Info
	{
		internal const string VERSION = "1.0.0";

		internal const string GUID = "com.wrango.runesredone";

		internal const string NAME = "Runes Redone";
	}
}
namespace RunicBarrier
{
	[HarmonyPatch(typeof(Item), "Start")]
	internal static class Item_Start_NameSync
	{
		private static readonly FieldRef<Item, string> ItemRawName = AccessTools.FieldRefAccess<Item, string>("m_name");

		private static int _logged;

		private const int LOG_LIMIT = 5;

		[HarmonyPriority(0)]
		private static void Postfix(Item __instance)
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)__instance) || string.IsNullOrEmpty(__instance.UID))
				{
					return;
				}
				string text = ItemRawName.Invoke(__instance);
				if (string.IsNullOrEmpty(text))
				{
					return;
				}
				string text2 = ((__instance.UID.Length > 10) ? __instance.UID.Substring(0, 10) : __instance.UID);
				string text3 = __instance.ItemID + "_" + text.Replace(" ", string.Empty) + "_" + text2;
				string text4 = __instance.ToShortString();
				if (!(((Object)__instance).name != text3) && !(text3 == text4))
				{
					((Object)__instance).name = text4;
					if (_logged < 5)
					{
						_logged++;
						RunicBarrierPlugin.Log.LogMessage((object)("[NameSync] (" + _logged + "/" + 5 + ") renamed '" + text3 + "' -> '" + text4 + "' to match the other clients"));
					}
				}
			}
			catch (Exception ex)
			{
				RunicBarrierPlugin.Log.LogError((object)("[NameSync] rename check threw: " + ex));
			}
		}
	}
	internal static class LoadOrder
	{
		private const string PACK = "Wrango-Runes_Redone";

		private const int MARKER_ITEM = -88003;

		private static readonly MethodInfo ApplyActual = AccessTools.Method(typeof(ContentTemplate), "ApplyActualTemplate", (Type[])null, (Type[])null);

		private static readonly FieldInfo FolderPacks = AccessTools.Field(typeof(SL), "folderPacks");

		private static bool _installed;

		internal static void Install()
		{
			if (!_installed)
			{
				_installed = true;
				if (SL.PacksLoaded)
				{
					Run();
				}
				else
				{
					SL.OnPacksLoaded += Run;
				}
			}
		}

		private static void Run()
		{
			try
			{
				Dictionary<string, SLPack> dictionary = ((FolderPacks != null) ? (FolderPacks.GetValue(null) as Dictionary<string, SLPack>) : null);
				if (dictionary == null || ApplyActual == null)
				{
					RunicBarrierPlugin.Log.LogWarning((object)"[LoadOrder] SideLoader's packs or apply method not found - RR's overrides are left to SideLoader's order.");
					return;
				}
				SLPack val = FindRR(dictionary);
				if (val == null)
				{
					RunicBarrierPlugin.Log.LogWarning((object)"[LoadOrder] RR's SideLoader pack not found - nothing re-applied.");
					return;
				}
				Dictionary<int, string> dictionary2 = new Dictionary<int, string>();
				Dictionary<string, string> dictionary3 = new Dictionary<string, string>();
				foreach (KeyValuePair<string, SLPack> item in dictionary)
				{
					if (item.Value == val)
					{
						continue;
					}
					foreach (SL_Item value3 in item.Value.GetContentOfType<SL_Item>().Values)
					{
						int key = AppliedID(value3);
						if (!dictionary2.ContainsKey(key))
						{
							dictionary2[key] = item.Key;
						}
					}
					foreach (SL_StatusEffect value4 in item.Value.GetContentOfType<SL_StatusEffect>().Values)
					{
						string text = AppliedIdentifier(value4);
						if (!string.IsNullOrEmpty(text) && !dictionary3.ContainsKey(text))
						{
							dictionary3[text] = item.Key;
						}
					}
				}
				int num = 0;
				string text2 = "";
				foreach (SL_Item value5 in val.GetContentOfType<SL_Item>().Values)
				{
					int key2 = AppliedID(value5);
					if (dictionary2.TryGetValue(key2, out var value))
					{
						if (!InPlace(value5))
						{
							text2 = text2 + "\n    WARNING item " + key2 + " '" + value5.Name + "' is a new item of RR's, and " + value + " uses the same ID - not re-applied";
						}
						else
						{
							ApplyActual.Invoke(value5, null);
							num++;
							text2 = text2 + "\n    item " + key2 + " '" + value5.Name + "' (also in " + value + ")";
						}
					}
				}
				foreach (SL_StatusEffect value6 in val.GetContentOfType<SL_StatusEffect>().Values)
				{
					string text3 = AppliedIdentifier(value6);
					if (!string.IsNullOrEmpty(text3) && dictionary3.TryGetValue(text3, out var value2))
					{
						if (!InPlace(value6))
						{
							text2 = text2 + "\n    WARNING status '" + text3 + "' is a new status of RR's, and " + value2 + " uses the same identifier - not re-applied";
						}
						else
						{
							ApplyActual.Invoke(value6, null);
							num++;
							text2 = text2 + "\n    status '" + text3 + "' (also in " + value2 + ")";
						}
					}
				}
				if (text2.Length == 0)
				{
					RunicBarrierPlugin.Log.LogMessage((object)"[LoadOrder] no other pack overrides RR's items or statuses - nothing to re-apply.");
				}
				else
				{
					RunicBarrierPlugin.Log.LogMessage((object)("[LoadOrder] RR's overrides re-applied after every pack (" + num + "):" + text2));
				}
			}
			catch (Exception ex)
			{
				RunicBarrierPlugin.Log.LogError((object)("[LoadOrder] threw: " + ex));
			}
		}

		private static SLPack FindRR(Dictionary<string, SLPack> packs)
		{
			if (packs.TryGetValue("Wrango-Runes_Redone", out var value) && value != null)
			{
				return value;
			}
			foreach (SLPack value2 in packs.Values)
			{
				foreach (SL_Item value3 in value2.GetContentOfType<SL_Item>().Values)
				{
					if (value3.New_ItemID == -88003)
					{
						return value2;
					}
				}
			}
			return null;
		}

		private static int AppliedID(SL_Item t)
		{
			if (t.New_ItemID == -1)
			{
				return t.Target_ItemID;
			}
			return t.New_ItemID;
		}

		private static bool InPlace(SL_Item t)
		{
			if (t.New_ItemID != -1)
			{
				return t.New_ItemID == t.Target_ItemID;
			}
			return true;
		}

		private static string AppliedIdentifier(SL_StatusEffect s)
		{
			if (!string.IsNullOrEmpty(s.StatusIdentifier))
			{
				return s.StatusIdentifier;
			}
			return s.TargetStatusIdentifier;
		}

		private static bool InPlace(SL_StatusEffect s)
		{
			if (!string.IsNullOrEmpty(s.StatusIdentifier))
			{
				return s.StatusIdentifier == s.TargetStatusIdentifier;
			}
			return true;
		}
	}
	internal static class OverchargeBlast
	{
		private const int DEZ_ITEM_ID = 8100210;

		private const string BRANCH = "RunicOvercharge";

		private static readonly float WAVE_SCALE = 1f;

		private static readonly float WAVE_SPEED = 0.3f;

		private static readonly float WAVE_MAX_PARTICLE_SIZE = 100f;

		private static readonly float FX_MARGIN = 0.1f;

		private const string CREST_EMITTER = "NewFire";

		private static readonly float CREST_TICK = 0.05f;

		private static readonly float CREST_MARGIN = 0.1f;

		private const int MAX_ATTEMPTS = 15;

		private static bool _done;

		private static int _attempts;

		private static bool _gaveUp;

		private static bool _crestReady;

		private static AnimationCurve _crestCurve;

		private static float _crestPeak = 1f;

		private static float _crestDelay;

		private static float _crestLife = 1f;

		private static float _crestSim = 1f;

		internal static float CrestRadius(float radius, float age)
		{
			if (!_crestReady)
			{
				return radius;
			}
			float num = (age * _crestSim - _crestDelay) / _crestLife;
			if (num >= 1f)
			{
				return radius;
			}
			if (num < 0f)
			{
				num = 0f;
			}
			return radius * Mathf.Clamp01(_crestCurve.Evaluate(num) / _crestPeak);
		}

		private static float CrestTravel()
		{
			if (!_crestReady)
			{
				return 0f;
			}
			return (_crestDelay + _crestLife) / _crestSim;
		}

		private static string ReadCrest(Blast blast)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Invalid comparison between Unknown and I4
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Expected O, but got Unknown
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystem[] componentsInChildren = ((Component)blast).GetComponentsInChildren<ParticleSystem>(true);
			ParticleSystem val = null;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (((Object)componentsInChildren[i]).name == "NewFire")
				{
					val = componentsInChildren[i];
					break;
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				return "no 'NewFire' emitter - crest OFF, hits land all at once";
			}
			SizeOverLifetimeModule sizeOverLifetime = val.sizeOverLifetime;
			MinMaxCurve size = ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size;
			if (!((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled || (int)((MinMaxCurve)(ref size)).mode != 1 || ((MinMaxCurve)(ref size)).curve == null)
			{
				return "'NewFire' size-over-lifetime is " + (((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled ? ((object)((MinMaxCurve)(ref size)).mode/*cast due to .constrained prefix*/).ToString() : "off") + ", not a curve - crest OFF, hits land all at once";
			}
			Keyframe[] keys = ((MinMaxCurve)(ref size)).curve.keys;
			float num = 0f;
			string text = "";
			for (int j = 0; j < keys.Length; j++)
			{
				if (((Keyframe)(ref keys[j])).value > num)
				{
					num = ((Keyframe)(ref keys[j])).value;
				}
				text = text + ((j > 0) ? " " : "") + "(" + ((Keyframe)(ref keys[j])).time.ToString("F2") + "," + ((Keyframe)(ref keys[j])).value.ToString("F2") + ")";
			}
			MainModule main = val.main;
			if (!(num <= 0f))
			{
				MinMaxCurve val2 = ((MainModule)(ref main)).startLifetime;
				if (!(((MinMaxCurve)(ref val2)).constantMax <= 0f) && !(((MainModule)(ref main)).simulationSpeed <= 0f))
				{
					_crestCurve = new AnimationCurve(keys);
					_crestPeak = num;
					val2 = ((MainModule)(ref main)).startDelay;
					_crestDelay = ((MinMaxCurve)(ref val2)).constantMax;
					val2 = ((MainModule)(ref main)).startLifetime;
					_crestLife = ((MinMaxCurve)(ref val2)).constantMax;
					_crestSim = ((MainModule)(ref main)).simulationSpeed;
					_crestReady = true;
					return "follows 'NewFire' curve " + text + ", delay " + _crestDelay.ToString("F2") + ", life " + _crestLife.ToString("F2") + ", speed x" + _crestSim.ToString("0.##") + " -> reaches the edge " + CrestTravel().ToString("F2") + " s after the cast";
				}
			}
			return "'NewFire' curve peak, lifetime or speed is zero - crest OFF";
		}

		internal static void TryOnce()
		{
			if (!_done && !_gaveUp)
			{
				_attempts++;
				try
				{
					_done = Apply();
				}
				catch (Exception ex)
				{
					RunicBarrierPlugin.Log.LogError((object)("[RunicBarrier] overcharge wave threw: " + ex));
					_gaveUp = true;
					return;
				}
				if (!_done && _attempts >= 15)
				{
					_gaveUp = true;
					RunicBarrierPlugin.Log.LogWarning((object)("[RunicBarrier] overcharge wave gave up after " + _attempts + " attempts - no 'RunicOvercharge' blast found on item " + 8100210 + ". The wave plays at native speed."));
				}
			}
		}

		private static bool Apply()
		{
			if (ResourcesPrefabManager.Instance == null)
			{
				return false;
			}
			Item itemPrefab = ResourcesPrefabManager.Instance.GetItemPrefab(8100210);
			if (!Object.op_Implicit((Object)(object)itemPrefab))
			{
				return false;
			}
			Transform val = ((Component)itemPrefab).transform.Find("RunicOvercharge");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			ShootBlast[] componentsInChildren = ((Component)val).GetComponentsInChildren<ShootBlast>(true);
			if (componentsInChildren.Length == 0)
			{
				return false;
			}
			string text = componentsInChildren.Length.ToString();
			float wAVE_SPEED = WAVE_SPEED;
			string text2 = "[RunicBarrier] overcharge wave, " + text + " blast(s) under 'RunicOvercharge', speed x" + wAVE_SPEED.ToString("0.##");
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Blast baseBlast = componentsInChildren[i].BaseBlast;
				text2 = text2 + "\n    [" + i + "] ";
				text2 += (Object.op_Implicit((Object)(object)baseBlast) ? Slow(baseBlast) : "no BaseBlast - left alone");
			}
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				if (_crestReady)
				{
					break;
				}
				if (Object.op_Implicit((Object)(object)componentsInChildren[j].BaseBlast))
				{
					text2 = text2 + "\n    crest: " + ReadCrest(componentsInChildren[j].BaseBlast);
				}
			}
			if (_crestReady)
			{
				for (int k = 0; k < componentsInChildren.Length; k++)
				{
					text2 = text2 + "\n    [" + k + "] " + ArmCrest(componentsInChildren[k]);
				}
			}
			RunicBarrierPlugin.Log.LogMessage((object)text2);
			return true;
		}

		private static string ArmCrest(ShootBlast shooter)
		{
			Blast baseBlast = shooter.BaseBlast;
			if (!Object.op_Implicit((Object)(object)baseBlast))
			{
				return "no BaseBlast - crest not armed";
			}
			float blastLifespan = shooter.BlastLifespan;
			float refreshTime = baseBlast.RefreshTime;
			bool ignoreStop = shooter.IgnoreStop;
			shooter.BlastLifespan = CrestTravel() + CREST_MARGIN;
			baseBlast.RefreshTime = CREST_TICK;
			shooter.IgnoreStop = true;
			if (!Object.op_Implicit((Object)(object)((Component)baseBlast).GetComponent<OverchargeCrest>()))
			{
				((Component)baseBlast).gameObject.AddComponent<OverchargeCrest>();
			}
			return "crest armed: lifespan " + blastLifespan.ToString("F2") + " -> " + shooter.BlastLifespan.ToString("F2") + ", tick " + refreshTime.ToString("F2") + " -> " + baseBlast.RefreshTime.ToString("F2") + ", IgnoreStop " + ignoreStop + " -> " + shooter.IgnoreStop + ", radius " + baseBlast.Radius.ToString("F1");
		}

		private static float LastEmission(ParticleSystem ps, out string by)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			EmissionModule emission = ps.emission;
			if (!((EmissionModule)(ref emission)).enabled)
			{
				by = "emission off";
				return 0f;
			}
			if (((EmissionModule)(ref emission)).rateOverTimeMultiplier > 0f || ((EmissionModule)(ref emission)).rateOverDistanceMultiplier > 0f)
			{
				by = "rate, whole cycle";
				MainModule main = ps.main;
				return ((MainModule)(ref main)).duration;
			}
			int burstCount = ((EmissionModule)(ref emission)).burstCount;
			if (burstCount <= 0)
			{
				by = "no rate, no bursts";
				return 0f;
			}
			Burst[] array = (Burst[])(object)new Burst[burstCount];
			((EmissionModule)(ref emission)).GetBursts(array);
			float num = 0f;
			for (int i = 0; i < burstCount; i++)
			{
				float num2 = ((Burst)(ref array[i])).time;
				if (((Burst)(ref array[i])).cycleCount > 1)
				{
					num2 += (float)(((Burst)(ref array[i])).cycleCount - 1) * ((Burst)(ref array[i])).repeatInterval;
				}
				if (num2 > num)
				{
					num = num2;
				}
			}
			by = burstCount + " burst(s)";
			return num;
		}

		private static string Slow(Blast blast)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			if (WAVE_SPEED <= 0f)
			{
				return "WAVE_SPEED must be above zero - left alone";
			}
			string text = "'" + ((Object)blast).name + "'";
			float num = 0f;
			ParticleSystem[] componentsInChildren = ((Component)blast).GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				MainModule main = componentsInChildren[i].main;
				float simulationSpeed = ((MainModule)(ref main)).simulationSpeed;
				((MainModule)(ref main)).simulationSpeed = WAVE_SPEED;
				float num2 = (((MainModule)(ref main)).startSize3D ? ((MainModule)(ref main)).startSizeXMultiplier : ((MainModule)(ref main)).startSizeMultiplier);
				if (((MainModule)(ref main)).startSize3D)
				{
					((MainModule)(ref main)).startSizeXMultiplier = ((MainModule)(ref main)).startSizeXMultiplier * WAVE_SCALE;
					((MainModule)(ref main)).startSizeYMultiplier = ((MainModule)(ref main)).startSizeYMultiplier * WAVE_SCALE;
					((MainModule)(ref main)).startSizeZMultiplier = ((MainModule)(ref main)).startSizeZMultiplier * WAVE_SCALE;
				}
				else
				{
					((MainModule)(ref main)).startSizeMultiplier = ((MainModule)(ref main)).startSizeMultiplier * WAVE_SCALE;
				}
				float num3 = (((MainModule)(ref main)).startSize3D ? ((MainModule)(ref main)).startSizeXMultiplier : ((MainModule)(ref main)).startSizeMultiplier);
				string text2 = ", no renderer";
				ParticleSystemRenderer component = ((Component)componentsInChildren[i]).GetComponent<ParticleSystemRenderer>();
				if (Object.op_Implicit((Object)(object)component))
				{
					float maxParticleSize = component.maxParticleSize;
					component.maxParticleSize = WAVE_MAX_PARTICLE_SIZE;
					text2 = ", screen cap " + maxParticleSize.ToString("F2") + " -> " + component.maxParticleSize.ToString("F2");
				}
				string by;
				float num4 = LastEmission(componentsInChildren[i], out by);
				MinMaxCurve val = ((MainModule)(ref main)).startDelay;
				float num5 = ((MinMaxCurve)(ref val)).constantMax + num4;
				val = ((MainModule)(ref main)).startLifetime;
				float num6 = num5 + ((MinMaxCurve)(ref val)).constantMax;
				if (num6 > num)
				{
					num = num6;
				}
				string[] obj = new string[24]
				{
					text,
					"\n        ",
					((Object)componentsInChildren[i]).name,
					" speed ",
					simulationSpeed.ToString("F2"),
					" -> ",
					((MainModule)(ref main)).simulationSpeed.ToString("F2"),
					", size ",
					num2.ToString("F2"),
					" -> ",
					num3.ToString("F2"),
					((MainModule)(ref main)).startSize3D ? " (3D)" : "",
					text2,
					", life=",
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				val = ((MainModule)(ref main)).startLifetime;
				obj[14] = ((MinMaxCurve)(ref val)).constantMax.ToString("F2");
				obj[15] = ", dur=";
				obj[16] = ((MainModule)(ref main)).duration.ToString("F2");
				obj[17] = ", last emit ";
				obj[18] = num4.ToString("F2");
				obj[19] = " (";
				obj[20] = by;
				obj[21] = "), gone by ";
				obj[22] = (num6 / WAVE_SPEED).ToString("F2");
				obj[23] = " s";
				text = string.Concat(obj);
			}
			Transform val2 = ((Component)blast).transform.Find("ExplosionFX");
			ParticleSystem val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponent<ParticleSystem>() : null);
			if (!Object.op_Implicit((Object)(object)val3))
			{
				return text + "\n        NO ExplosionFX - the blast switches off right after its lifespan, so the expiry was not touched.";
			}
			MainModule main2 = val3.main;
			float duration = ((MainModule)(ref main2)).duration;
			float num7 = num / WAVE_SPEED - duration + FX_MARGIN;
			float addedTimeForFX = blast.AddedTimeForFX;
			if (num7 > blast.AddedTimeForFX)
			{
				blast.AddedTimeForFX = num7;
			}
			return text + "\n        expiry: ExplosionFX dur " + duration.ToString("F2") + " + AddedTimeForFX " + addedTimeForFX.ToString("F2") + " -> " + blast.AddedTimeForFX.ToString("F2") + " (slowed tail " + (num / WAVE_SPEED).ToString("F2") + " s)";
		}
	}
	internal class OverchargeCrest : MonoBehaviour
	{
		private static readonly FieldRef<Blast, float> ShotTime = AccessTools.FieldRefAccess<Blast, float>("m_shotTime");

		private readonly HashSet<int> _hit = new HashSet<int>();

		private float _shot = float.MinValue;

		internal void Filter(Blast blast, List<Hitbox> targets)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			float num = ShotTime.Invoke(blast);
			if (num != _shot)
			{
				_shot = num;
				_hit.Clear();
			}
			float age = Time.time - _shot;
			float num2 = OverchargeBlast.CrestRadius(blast.Radius, age);
			Vector3 position = ((Component)blast).transform.position;
			for (int num3 = targets.Count - 1; num3 >= 0; num3--)
			{
				Hitbox val = targets[num3];
				Character val2 = (Object.op_Implicit((Object)(object)val) ? val.OwnerChar : null);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					targets.RemoveAt(num3);
				}
				else
				{
					int instanceID = ((Object)val2).GetInstanceID();
					if (_hit.Contains(instanceID))
					{
						targets.RemoveAt(num3);
					}
					else
					{
						Vector3 val3 = ((Component)val2).transform.position - position;
						val3.y = 0f;
						float magnitude = ((Vector3)(ref val3)).magnitude;
						if (magnitude > num2)
						{
							targets.RemoveAt(num3);
						}
						else
						{
							_hit.Add(instanceID);
							RunicBarrierPlugin.Log.LogMessage((object)("[RunicBarrier] crest hit " + val2.Name + " at " + magnitude.ToString("F1") + " m, " + age.ToString("F2") + " s after the cast (crest " + num2.ToString("F1") + " m)"));
						}
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Blast), "AffectHit")]
	public class Blast_AffectHit_Crest
	{
		[HarmonyPrefix]
		public static void Prefix(Blast __instance, List<Hitbox> _hitTargets)
		{
			try
			{
				if (Object.op_Implicit((Object)(object)__instance) && _hitTargets != null && _hitTargets.Count != 0)
				{
					OverchargeCrest component = ((Component)__instance).GetComponent<OverchargeCrest>();
					if (Object.op_Implicit((Object)(object)component))
					{
						component.Filter(__instance, _hitTargets);
					}
				}
			}
			catch (Exception ex)
			{
				RunicBarrierPlugin.Log.LogError((object)("[RunicBarrier] crest filter threw: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(CharacterInventory), "TakeItemToPouch")]
	internal static class CharacterInventory_TakeItemToPouch_RunicArrow
	{
		private static int _logged;

		private const int LOG_LIMIT = 3;

		private static bool Prefix(Character ___m_character, Item _item)
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)_item) || _item.ItemID != -88001)
				{
					return true;
				}
				if (!Object.op_Implicit((Object)(object)___m_character) || (Object)(object)___m_character.OwnerPlayerSys != (Object)null)
				{
					return true;
				}
				if (!PhotonNetwork.isNonMasterClientInRoom)
				{
					ItemManager.Instance.DestroyItem(_item.UID);
				}
				if (_logged < 3)
				{
					_logged++;
					RunicBarrierPlugin.Log.LogMessage((object)("[RunicArrow] (" + _logged + "/" + 3 + ") kept a Runic Arrow out of " + ___m_character.Name + "'s pouch"));
				}
				return false;
			}
			catch (Exception ex)
			{
				RunicBarrierPlugin.Log.LogError((object)("[RunicArrow] pouch check threw: " + ex));
				return true;
			}
		}
	}
	[BepInPlugin("com.wrango.runesredone.barrier", "Runes Redone - Barrier", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RunicBarrierPlugin : BaseUnityPlugin
	{
		internal enum Tier
		{
			None,
			Normal,
			Amplified
		}

		public const string GUID = "com.wrango.runesredone.barrier";

		public const string NAME = "Runes Redone - Barrier";

		public const string VERSION = "1.0.0";

		internal static ManualLogSource Log;

		internal static RunicBarrierPlugin Instance;

		private string _mitigationSig;

		private static readonly bool DIAG = false;

		private const bool APPLY_MANA_REDUCTION = true;

		private const string IMPACT_SOUNDS = "CS_GolemShielded_ShieldImpact_01,CS_GolemShielded_ShieldImpact_02,CS_GolemShielded_ShieldImpact_03,CS_GolemShielded_ShieldImpact_04";

		private const float PITCH_MIN = 1f;

		private const float PITCH_MAX = 1f;

		private const float VOLUME_MIN = 1f;

		private const float VOLUME_MAX = 1f;

		private const ProjectilePrefabs SPARK_PROJECTILE = (ProjectilePrefabs)0;

		private const float SPARK_LIFESPAN = 0f;

		private const float SPARK_FORCE = 0f;

		private const float SPARK_SCALE = 1f;

		private const string SPARK_HIDE_EMITTERS = "ProjectileFX";

		private const BlastPrefabs SPARK_BLAST = (BlastPrefabs)63;

		private const float SPARK_BLAST_LIFESPAN = 5f;

		private const float SPARK_BLAST_SCALE = 0.07f;

		private Sounds[] _sounds = (Sounds[])(object)new Sounds[0];

		private int _lastIndex = -1;

		private readonly Dictionary<Sounds, int> _soundTally = new Dictionary<Sounds, int>();

		internal static int AbsorbFrame = -1;

		internal static int AbsorbVictimId;

		internal static float AbsorbTook;

		internal static bool LogHits;

		private static Harmony _harmony;

		private static int _cueFrame = -1;

		private bool _hurtboxLogged;

		private static int _awaitingPointFrame = -1;

		private static int _awaitingPointHit;

		private static string _awaitingPointSrc = "";

		private const float CUE_HOLD_SECONDS = 8f;

		private readonly Dictionary<int, UnityAction<Object, DamageList>> _subs = new Dictionary<int, UnityAction<Object, DamageList>>();

		private Character _localPlayer;

		private float _nextScan;

		private float _manaSpent;

		private float _healthLet;

		private float _negated;

		private int _hits;

		private int _observed;

		private bool _wardWasUp;

		private static FieldInfo _manaField;

		private static bool _manaFieldResolved;

		internal const string STATUS_ID = "RunicBarrier";

		internal const string STATUS_ID_AMPLIFIED = "RunicBarrierAmplified";

		private const float HEALTH_SHARE = 0.6f;

		private const float MANA_SHARE = 0.6f;

		private const float HEALTH_SHARE_AMPLIFIED = 0.5f;

		private const float MANA_SHARE_AMPLIFIED = 0.5f;

		private readonly Dictionary<int, Tier> _allyWard = new Dictionary<int, Tier>();

		private static bool ResolveManaField(CharacterStats stats)
		{
			if (_manaFieldResolved)
			{
				return _manaField != null;
			}
			_manaFieldResolved = true;
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			float currentMana = stats.CurrentMana;
			Type type = ((object)stats).GetType();
			List<string> list = new List<string>();
			FieldInfo[] fields = type.GetFields(bindingAttr);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.FieldType != typeof(float))
				{
					continue;
				}
				float num;
				try
				{
					num = (float)fieldInfo.GetValue(stats);
				}
				catch (Exception)
				{
					continue;
				}
				float num2 = num - currentMana;
				if (num2 < 0f)
				{
					num2 = 0f - num2;
				}
				if (!(num2 > 0.0001f))
				{
					list.Add(fieldInfo.Name);
					if (fieldInfo.Name == "m_mana")
					{
						_manaField = fieldInfo;
					}
				}
			}
			if (_manaField == null && list.Count == 1)
			{
				_manaField = type.GetField(list[0], bindingAttr);
			}
			if (_manaField != null)
			{
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] mana field = " + _manaField.Name + "  (candidates: " + string.Join(", ", list.ToArray()) + ")"));
			}
			else
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] COULD NOT RESOLVE the mana backing field. Candidates matching CurrentMana=" + currentMana.ToString("F2") + ": " + string.Join(", ", list.ToArray()) + ". The ward is disabled - it must never take damage it cannot charge for."));
			}
			return _manaField != null;
		}

		private static string Stamp()
		{
			return DateTime.Now.ToString("HH:mm:ss.fff");
		}

		internal void Awake()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Log.LogMessage((object)(Stamp() + " [RunicBarrier 1.0.0] loaded, WARD model. split=" + 0.6f.ToString("0.##") + "/" + 0.6f.ToString("0.##") + " amplified=" + 0.5f.ToString("0.##") + "/" + 0.5f.ToString("0.##") + " (fixed) ApplyManaReduction=" + true + " Spark=" + ((object)(ProjectilePrefabs)0/*cast due to .constrained prefix*/).ToString()));
			LogHits = DIAG;
			InstallHitPointHook();
			ParseImpactSounds();
			LoadOrder.Install();
			SummonIcon.Install();
			RunicTrapColour.Install();
		}

		internal void LateUpdate()
		{
			RunicTrapColour.LateTick();
		}

		internal void Update()
		{
			if (Object.op_Implicit((Object)(object)_localPlayer) && _localPlayer.IsLocalPlayer)
			{
				TrackWardSession(_localPlayer);
			}
			RunicPortals.Tick();
			RunicFlameBlast.Tick();
			RunicSpeed.Tick();
			RunicTrapStatus.Tick();
			CollapseAtZeroMana();
			if (Time.time < _nextScan)
			{
				return;
			}
			_nextScan = Time.time + 2f;
			VFXTrim.TryOnce();
			OverchargeBlast.TryOnce();
			RunicFlameBlast.TryOnce();
			StealthFX.TryOnce();
			TouchFX.TryOnce();
			SpeedFX.TryOnce();
			if ((Object)(object)CharacterManager.Instance == (Object)null)
			{
				return;
			}
			List<int> list = new List<int>();
			foreach (Character value in CharacterManager.Instance.Characters.Values)
			{
				if (!Object.op_Implicit((Object)(object)value) || value.IsAI)
				{
					continue;
				}
				int instanceID = ((Object)value).GetInstanceID();
				list.Add(instanceID);
				if (value.IsLocalPlayer)
				{
					_localPlayer = value;
				}
				if (value.IsLocalPlayer)
				{
					LogMitigation(value);
				}
				else
				{
					LogAllyWard(value, instanceID);
				}
				if (!_subs.ContainsKey(instanceID))
				{
					Character victim = value;
					UnityAction<Object, DamageList> val = delegate(Object src, DamageList dmg)
					{
						OnHit(victim, src, dmg);
					};
					value.OnHitPreResistance = (UnityAction<Object, DamageList>)(object)Delegate.Combine((Delegate?)(object)value.OnHitPreResistance, (Delegate?)(object)val);
					_subs.Add(instanceID, val);
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] watching " + Describe(value)));
					LogHurtbox(value);
				}
			}
			List<int> list2 = new List<int>();
			foreach (int key in _subs.Keys)
			{
				if (!list.Contains(key))
				{
					list2.Add(key);
				}
			}
			foreach (int item in list2)
			{
				_subs.Remove(item);
			}
		}

		private void ParseImpactSounds()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				List<Sounds> list = new List<Sounds>();
				List<string> list2 = new List<string>();
				string text = "CS_GolemShielded_ShieldImpact_01,CS_GolemShielded_ShieldImpact_02,CS_GolemShielded_ShieldImpact_03,CS_GolemShielded_ShieldImpact_04";
				if (!string.IsNullOrEmpty(text))
				{
					string[] array = text.Split(new char[1] { ',' });
					for (int i = 0; i < array.Length; i++)
					{
						string text2 = array[i].Trim();
						if (text2.Length == 0)
						{
							continue;
						}
						try
						{
							Sounds val = (Sounds)Enum.Parse(typeof(Sounds), text2, ignoreCase: true);
							if ((int)val != 0)
							{
								list.Add(val);
							}
						}
						catch (Exception)
						{
							list2.Add(text2);
						}
					}
				}
				_sounds = list.ToArray();
				if (list2.Count > 0)
				{
					Log.LogError((object)(Stamp() + " [RunicBarrier] these ImpactSounds are not valid sound names and were skipped: " + string.Join(", ", list2.ToArray()) + ". Copy them exactly from the ListSoundsMatching output."));
				}
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] impact sounds: " + _sounds.Length + ((_sounds.Length == 0) ? " (silent)" : " in rotation")));
			}
			catch (Exception ex2)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] could not parse ImpactSounds: " + ex2));
				_sounds = (Sounds[])(object)new Sounds[0];
			}
		}

		private unsafe string PlayImpactSound(Transform at)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_sounds.Length == 0 || (Object)(object)Global.AudioManager == (Object)null || !Object.op_Implicit((Object)(object)at))
				{
					return null;
				}
				int num;
				if (_sounds.Length > 1 && _lastIndex >= 0)
				{
					num = Random.Range(0, _sounds.Length - 1);
					if (num >= _lastIndex)
					{
						num++;
					}
				}
				else
				{
					num = Random.Range(0, _sounds.Length);
				}
				Sounds val = _sounds[num];
				_lastIndex = num;
				if ((int)val == 0)
				{
					return "(NONE in the list)";
				}
				_soundTally.TryGetValue(val, out var value);
				_soundTally[val] = value + 1;
				Global.AudioManager.PlaySoundAndFollow(val, at, 0f, 1f, 1f, 1f, 1f);
				return ((object)(*(Sounds*)(&val))/*cast due to .constrained prefix*/).ToString();
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] impact sound failed: " + ex));
				return "(threw)";
			}
		}

		internal static Tier TierOf(Character c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return Tier.None;
			}
			StatusEffectManager statusEffectMngr = c.StatusEffectMngr;
			if ((Object)(object)statusEffectMngr != (Object)null)
			{
				if (statusEffectMngr.HasStatusEffect("RunicBarrierAmplified"))
				{
					return Tier.Amplified;
				}
				if (statusEffectMngr.HasStatusEffect("RunicBarrier"))
				{
					return Tier.Normal;
				}
			}
			return Tier.None;
		}

		private void SharesFor(Tier tier, out float hShare, out float mShare)
		{
			if (tier == Tier.Amplified)
			{
				hShare = 0.5f;
				mShare = 0.5f;
			}
			else
			{
				hShare = 0.6f;
				mShare = 0.6f;
			}
		}

		private void TrackWardSession(Character c)
		{
			try
			{
				if (Object.op_Implicit((Object)(object)c) && c.IsLocalPlayer)
				{
					bool flag = TierOf(c) != Tier.None;
					if (flag && !_wardWasUp)
					{
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] ward session started"));
					}
					else if (!flag && _wardWasUp)
					{
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] ward ended - dismissed, expired or collapsed; this edge does not say which"));
					}
					_wardWasUp = flag;
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] ward session tracking threw: " + ex));
			}
		}

		private void LogMitigation(Character c)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)c == (Object)null || (Object)(object)c.Stats == (Object)null)
				{
					return;
				}
				float[] damageProtection = c.Stats.DamageProtection;
				float[] damageResistance = c.Stats.DamageResistance;
				if (damageProtection == null || damageResistance == null)
				{
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] mitigation: arrays unavailable"));
					return;
				}
				string text = "";
				for (int i = 0; i < damageProtection.Length; i++)
				{
					string text2 = ((i < 9) ? ((object)(Types)i/*cast due to .constrained prefix*/).ToString() : ("?" + i));
					text = text + " " + text2 + "=" + damageProtection[i].ToString("F2") + "/" + (damageResistance[i] * 100f).ToString("F0") + "%";
				}
				float num = c.Stats.GetFinalManaConsumption((Tag[])null, 100f) / 100f;
				float manaRegen = c.Stats.ManaRegen;
				string text3 = text + "|" + c.Stats.GetBarrier().ToString("F2") + "|" + num.ToString("F3") + "|" + manaRegen.ToString("F3");
				if (!(text3 == _mitigationSig))
				{
					bool flag = _mitigationSig != null;
					_mitigationSig = text3;
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] mitigation of " + c.Name + (flag ? " CHANGED" : "") + " | flat/resist by type:" + text + " | Barrier=" + c.Stats.GetBarrier().ToString("F2") + " | manaMod x" + num.ToString("F3") + ((num > 1.001f) ? " (a PENALTY, not a reduction)" : "") + " | manaRegenStat " + manaRegen.ToString("F3") + "/s" + ((manaRegen < -0.001f) ? " (rate negative; food may still carry it positive)" : ((manaRegen < 0.001f) ? " (rate suspended)" : ""))));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] mitigation dump threw: " + ex));
			}
		}

		private float ManaBillBase(Character victim, DamageList dmg, float mShare, out float flatUsed)
		{
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected I4, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected I4, but got Unknown
			flatUsed = 0f;
			if ((Object)(object)victim == (Object)null || (Object)(object)victim.Stats == (Object)null)
			{
				return dmg.TotalDamage * mShare;
			}
			float[] damageProtection = victim.Stats.DamageProtection;
			float[] damageResistance = victim.Stats.DamageResistance;
			if (damageProtection == null || damageResistance == null)
			{
				return dmg.TotalDamage * mShare;
			}
			float barrier = victim.Stats.GetBarrier();
			int num = -1;
			if (barrier > 0f)
			{
				float num2 = 0f;
				float num3 = 0f;
				for (int i = 0; i < dmg.Count; i++)
				{
					DamageType val = dmg[i];
					if ((int)val.Type != 0)
					{
						int num4 = (int)val.Type;
						if (num4 >= 0 && num4 < damageResistance.Length && (num < 0 || damageResistance[num4] < num2 || (damageResistance[num4] == num2 && val.Damage > num3)))
						{
							num = num4;
							num2 = damageResistance[num4];
							num3 = val.Damage;
						}
					}
				}
			}
			float num5 = 0f;
			for (int j = 0; j < dmg.Count; j++)
			{
				DamageType obj = dmg[j];
				int num6 = (int)obj.Type;
				float num7 = ((num6 >= 0 && num6 < damageProtection.Length) ? damageProtection[num6] : 0f);
				if (num6 == num)
				{
					num7 += barrier;
				}
				float num8 = obj.Damage * mShare;
				float num9 = num8 - num7;
				if (num9 < 0f)
				{
					num9 = 0f;
				}
				flatUsed += num8 - num9;
				num5 += num9;
			}
			return num5;
		}

		private void Collapse(Character victim)
		{
			try
			{
				if (Object.op_Implicit((Object)(object)victim) && !((Object)(object)victim.StatusEffectMngr == (Object)null))
				{
					bool flag = false;
					if (victim.StatusEffectMngr.HasStatusEffect("RunicBarrier"))
					{
						victim.StatusEffectMngr.CleanseStatusEffect("RunicBarrier");
						flag = true;
					}
					if (victim.StatusEffectMngr.HasStatusEffect("RunicBarrierAmplified"))
					{
						victim.StatusEffectMngr.CleanseStatusEffect("RunicBarrierAmplified");
						flag = true;
					}
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] WARD COLLAPSED on " + victim.Name + " - out of Mana" + (flag ? ", status removed" : ", no status was present")));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] collapse threw: " + ex));
			}
		}

		private void CollapseAtZeroMana()
		{
			if (Object.op_Implicit((Object)(object)NetworkLevelLoader.Instance) && !NetworkLevelLoader.Instance.IsOverallLoadingDone)
			{
				return;
			}
			CharacterManager instance = CharacterManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			foreach (Character value in instance.Characters.Values)
			{
				if (Object.op_Implicit((Object)(object)value) && value.IsLocalPlayer && Object.op_Implicit((Object)(object)value.Stats) && !(value.Stats.CurrentMana > 0f) && TierOf(value) != Tier.None)
				{
					Collapse(value);
				}
			}
		}

		internal static bool WardIsUp(Character c)
		{
			return TierOf(c) != Tier.None;
		}

		private void LogAllyWard(Character c, int id)
		{
			try
			{
				if (!((Object)(object)c == (Object)null))
				{
					Tier tier = TierOf(c);
					if (!_allyWard.TryGetValue(id, out var value) || value != tier)
					{
						bool flag = _allyWard.ContainsKey(id);
						_allyWard[id] = tier;
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] ally " + c.Name + ": ward " + ((tier == Tier.None) ? "None" : tier.ToString()) + (flag ? " (changed - as THIS client sees it)" : " (first sighting)")));
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] ally ward watch threw: " + ex));
			}
		}

		private void LogObserved(Character victim, Object src, DamageList dmg)
		{
			try
			{
				string text = "";
				for (int i = 0; i < dmg.Count; i++)
				{
					DamageType val = dmg[i];
					if (i > 0)
					{
						text += "/";
					}
					text = text + ((object)Unsafe.As<Types, Types>(ref val.Type)/*cast due to .constrained prefix*/).ToString() + ":" + val.Damage.ToString("F1");
				}
				float before = (Object.op_Implicit((Object)(object)victim.Stats) ? victim.Stats.CurrentHealth : (-1f));
				_observed++;
				int observed = _observed;
				string text2 = Stamp() + " [RunicBarrier] OBSERVED #" + observed + " on " + (victim.Name ?? "?") + " (NOT ours - nothing touched) | src=" + (Object.op_Implicit(src) ? ((object)src).GetType().Name : "null") + " | entries=" + dmg.Count + " [" + text + "] raw=" + dmg.TotalDamage.ToString("F2") + " | health before=" + before.ToString("F2");
				Log.LogMessage((object)text2);
				((MonoBehaviour)this).StartCoroutine(ReportObservedHealth(victim, before, observed));
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] observer threw: " + ex));
			}
		}

		private IEnumerator ReportObservedHealth(Character victim, float before, int n)
		{
			yield return null;
			float afterOne = ((Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)victim.Stats)) ? victim.Stats.CurrentHealth : (-1f));
			yield return (object)new WaitForSeconds(0.25f);
			float num = ((Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)victim.Stats)) ? victim.Stats.CurrentHealth : (-1f));
			Log.LogMessage((object)(Stamp() + " [RunicBarrier] OBSERVED #" + n + " health " + before.ToString("F2") + " -> " + afterOne.ToString("F2") + " (1 frame) -> " + num.ToString("F2") + " (0.25s) | TOOK " + (before - num).ToString("F2") + " as this client sees it"));
		}

		private IEnumerator ReportOwnHealth(Character victim, float before, int hit)
		{
			yield return null;
			yield return (object)new WaitForSeconds(0.25f);
			float num = ((Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)victim.Stats)) ? victim.Stats.CurrentHealth : (-1f));
			Log.LogMessage((object)(Stamp() + " [RunicBarrier] SPLIT #" + hit + " health " + before.ToString("F2") + " -> " + num.ToString("F2") + " (0.25s) | TOOK " + (before - num).ToString("F2") + " as OUR client sees it"));
		}

		private void LogSoundTally()
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (_soundTally.Count == 0)
			{
				return;
			}
			int num = 0;
			foreach (KeyValuePair<Sounds, int> item in _soundTally)
			{
				num += item.Value;
			}
			Log.LogMessage((object)(Stamp() + " [RunicBarrier] sound tally over " + num + " plays:"));
			foreach (KeyValuePair<Sounds, int> item2 in _soundTally)
			{
				Log.LogMessage((object)("    " + ((object)item2.Key/*cast due to .constrained prefix*/).ToString() + " x" + item2.Value + "  (" + (100f * (float)item2.Value / (float)num).ToString("F0") + "%)"));
			}
			if (_soundTally.Count < _sounds.Length)
			{
				Log.LogMessage((object)("    NOTE: only " + _soundTally.Count + " of " + _sounds.Length + " configured sounds were ever picked."));
			}
		}

		private void OnHit(Character victim, Object src, DamageList dmg)
		{
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Object.op_Implicit((Object)(object)victim) || dmg == null)
				{
					return;
				}
				if (!victim.IsLocalPlayer)
				{
					if (DIAG)
					{
						LogObserved(victim, src, dmg);
					}
					return;
				}
				string text = (Object.op_Implicit(src) ? ((object)src).GetType().Name : "null");
				string text2 = "";
				for (int i = 0; i < dmg.Count; i++)
				{
					DamageType val = dmg[i];
					if (i > 0)
					{
						text2 += "/";
					}
					text2 = text2 + ((object)Unsafe.As<Types, Types>(ref val.Type)/*cast due to .constrained prefix*/).ToString() + ":" + val.Damage.ToString("F1");
				}
				string text3 = "entries=" + dmg.Count + " [" + text2 + "] raw=" + dmg.TotalDamage.ToString("F2");
				Tier tier = TierOf(victim);
				if (tier == Tier.None)
				{
					if (DIAG)
					{
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] ward DOWN, hit passes whole src=" + text + " " + text3));
					}
					return;
				}
				float before = (Object.op_Implicit((Object)(object)victim.Stats) ? victim.Stats.CurrentHealth : (-1f));
				float totalDamage = dmg.TotalDamage;
				if (totalDamage <= 0f)
				{
					return;
				}
				SharesFor(tier, out var hShare, out var mShare);
				float num = Mathf.Max(0f, 1f - hShare - mShare);
				if (mShare <= 0f)
				{
					if (DIAG)
					{
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] Mana share is 0, nothing to charge src=" + text + " " + text3));
					}
				}
				else
				{
					if (!ResolveManaField(victim.Stats))
					{
						return;
					}
					LogMitigation(victim);
					float flatUsed;
					float num2 = ManaBillBase(victim, dmg, mShare, out flatUsed);
					float num3 = num2;
					num3 = victim.Stats.GetFinalManaConsumption((Tag[])null, num2);
					float currentMana = victim.Stats.CurrentMana;
					float num4 = 1f;
					bool flag = false;
					if (num3 > currentMana)
					{
						num4 = ((num3 > 0f) ? Mathf.Clamp01(currentMana / num3) : 0f);
						flag = true;
					}
					float num5 = num3 * num4;
					float num6 = mShare * num4;
					float num7 = mShare * (1f - num4);
					float num8 = hShare + num7;
					List<DamageType> list = new List<DamageType>();
					for (int j = 0; j < dmg.Count; j++)
					{
						DamageType val2 = dmg[j];
						val2.Damage *= num8;
						if (val2.Damage <= 0.001f)
						{
							list.Add(val2);
						}
					}
					foreach (DamageType item in list)
					{
						dmg.Remove(item.Type);
					}
					_manaField.SetValue(victim.Stats, currentMana - num5);
					_hits++;
					_manaSpent += num5;
					_healthLet += totalDamage * num8;
					_negated += totalDamage * num;
					if (_awaitingPointFrame >= 0)
					{
						Log.LogWarning((object)(Stamp() + " [RunicBarrier] split #" + _awaitingPointHit + " (" + _awaitingPointSrc + ") never received a hit point - no impact sound and no spark for it."));
					}
					if (DIAG)
					{
						((MonoBehaviour)this).StartCoroutine(ReportOwnHealth(victim, before, _hits));
					}
					_awaitingPointFrame = Time.frameCount;
					_awaitingPointHit = _hits;
					_awaitingPointSrc = text;
					AbsorbFrame = Time.frameCount;
					AbsorbVictimId = ((Object)victim).GetInstanceID();
					AbsorbTook = totalDamage * num6;
					if (flag)
					{
						Collapse(victim);
					}
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] " + (flag ? "SPLIT+COLLAPSE #" : "SPLIT #") + _hits + " src=" + text + " tier=" + tier.ToString() + " (" + hShare.ToString("0.##") + "/" + mShare.ToString("0.##") + " = " + (hShare + mShare).ToString("0.##") + "x raw) | raw=" + totalDamage.ToString("F2") + " -> health=" + (totalDamage * num8).ToString("F2") + " mana=" + (totalDamage * num6).ToString("F2") + " negated=" + (totalDamage * num).ToString("F2") + " | cost=" + num3.ToString("F2") + " (flat -" + flatUsed.ToString("F2") + ((num3 <= 0.001f) ? ", FREE" : "") + ") spent=" + num5.ToString("F2") + ((num3 < num2 - 0.01f) ? (" (reduced from " + num2.ToString("F2") + ")") : "") + " | mana " + currentMana.ToString("F2") + " -> " + victim.Stats.CurrentMana.ToString("F2") + " | " + text3 + " | list now=" + dmg.TotalDamage.ToString("F2") + (flag ? (" | WARD DOWN, " + (totalDamage * num7).ToString("F2") + " fell back to Health") : "") + " | totals mana=" + _manaSpent.ToString("F1") + " healthShare=" + _healthLet.ToString("F1") + " negated=" + _negated.ToString("F1")));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] handler threw: " + ex));
			}
		}

		private void InstallHitPointHook()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			try
			{
				Type[] array = new Type[9]
				{
					typeof(Weapon),
					typeof(float),
					typeof(DamageList),
					typeof(Vector3),
					typeof(Vector3),
					typeof(float),
					typeof(float),
					typeof(Character),
					typeof(float)
				};
				MethodInfo methodInfo = AccessTools.Method(typeof(Character), "OnReceiveHit", array, (Type[])null);
				if (methodInfo == null)
				{
					Log.LogError((object)(Stamp() + " [RunicBarrier] OnReceiveHit not found with that signature - no hit point, so the spark cannot fire."));
					return;
				}
				_harmony = new Harmony("com.wrango.runesredone.barrier");
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(RunicBarrierPlugin).GetMethod("OnReceiveHitPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.PatchAll(typeof(Projectile_Shoot_KeepAlive));
				_harmony.PatchAll(typeof(Blast_AffectHit_Crest));
				_harmony.PatchAll(typeof(Shooter_GetActivationInfos_RunicFlame));
				_harmony.PatchAll(typeof(Blast_Shoot_RunicFlame));
				_harmony.PatchAll(typeof(ItemVisual_AddImbueFX_RunicBlade));
				_harmony.PatchAll(typeof(DetectabilityEmitter_Detectability_RunicSpeed));
				_harmony.PatchAll(typeof(DetectabilityEmitter_VisualDetectability_RunicSpeed));
				_harmony.PatchAll(typeof(CharacterStats_GetFinalStaminaConsumption_RunicSpeed));
				_harmony.PatchAll(typeof(ShootProjectile_ProcessAffectInfos_Sight));
				_harmony.PatchAll(typeof(DeployableTrap_StartInit_RunicTrapColour));
				_harmony.PatchAll(typeof(CharacterInventory_TakeItemToPouch_RunicArrow));
				_harmony.PatchAll(typeof(RunicBlade_ActivateLocally_PrefixLifespan));
				_harmony.PatchAll(typeof(Item_Start_NameSync));
				_harmony.PatchAll(typeof(ShootProjectileAmmoVisuals_ActivateLocally_LoadedVisual));
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] OnReceiveHit hook installed."));
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] could not install the hook: " + ex));
			}
		}

		private static void OnReceiveHitPrefix(Character __instance, Weapon _weapon, float _damage, DamageList _damageList, Vector3 _hitDir, Vector3 _hitPoint, float _angle, float _angleDir, Character _dealerChar, float _knockBack)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Object.op_Implicit((Object)(object)__instance) || __instance.IsAI)
				{
					return;
				}
				bool flag = __instance.IsLocalPlayer && Time.frameCount == AbsorbFrame && ((Object)__instance).GetInstanceID() == AbsorbVictimId;
				bool flag2 = !__instance.IsLocalPlayer && WardIsUp(__instance);
				if (!flag && !flag2 && !LogHits)
				{
					return;
				}
				string text = null;
				string text2 = null;
				string text3 = null;
				if ((flag || flag2) && (Object)(object)Instance != (Object)null)
				{
					if (flag)
					{
						_awaitingPointFrame = -1;
					}
					if (Time.frameCount == _cueFrame)
					{
						text = "(suppressed, same frame)";
					}
					else
					{
						_cueFrame = Time.frameCount;
						GameObject val = Spark.CreateCue(__instance, _hitPoint, _hitDir, 8f);
						text2 = Instance.PlayImpactSound(val.transform);
						text = Spark.Fire(val, __instance, (ProjectilePrefabs)0, 0f, 0f, 1f, "ProjectileFX");
						text3 = SparkBlast.Fire(val, __instance, (BlastPrefabs)63, 5f, 0.07f, "ProjectileFX");
					}
				}
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] OnReceiveHit" + (flag ? ("  *** same frame as a split taking " + AbsorbTook.ToString("F2") + " ***") : "") + (flag2 ? ("  *** ALLY " + (__instance.Name ?? "?") + ", ward up - cue only, no split on this client ***") : "") + ((text2 == null) ? "" : (" | sound=" + text2)) + ((text == null) ? "" : (" | spark=" + text)) + ((text3 == null) ? "" : (" | blast=" + text3)) + " | _damage=" + _damage.ToString("F2") + " | list=" + ((_damageList == null) ? "null" : (_damageList.Count + " entries total=" + _damageList.TotalDamage.ToString("F2"))) + " | " + Offset(__instance, _hitPoint) + " | _hitPoint=" + ((Vector3)(ref _hitPoint)).ToString("F2") + " | _hitDir=" + ((Vector3)(ref _hitDir)).ToString("F2") + " | _knockBack=" + _knockBack.ToString("F2") + " | dealer=" + (Object.op_Implicit((Object)(object)_dealerChar) ? _dealerChar.Name : "null")));
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] OnReceiveHit prefix threw: " + ex));
			}
		}

		private static string Offset(Character victim, Vector3 hitPoint)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)victim))
			{
				return "offset=(no character)";
			}
			Vector3 val = ((Component)victim).transform.InverseTransformPoint(hitPoint);
			Vector3 val2 = hitPoint - ((Component)victim).transform.position;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			return "offset r=" + val.x.ToString("F2") + " u=" + val.y.ToString("F2") + " f=" + val.z.ToString("F2") + " dist=" + magnitude.ToString("F2");
		}

		private void LogHurtbox(Character c)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_hurtboxLogged || !Object.op_Implicit((Object)(object)c))
				{
					return;
				}
				_hurtboxLogged = true;
				Collider[] componentsInChildren = ((Component)c).GetComponentsInChildren<Collider>(true);
				string[] obj = new string[7]
				{
					Stamp(),
					" [RunicBarrier] hurtbox of ",
					c.Name,
					": ",
					componentsInChildren.Length.ToString(),
					" collider(s), root at ",
					null
				};
				Vector3 val = ((Component)c).transform.position;
				obj[6] = ((Vector3)(ref val)).ToString("F2");
				string text = string.Concat(obj);
				foreach (Collider val2 in componentsInChildren)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						Bounds bounds = val2.bounds;
						string[] obj2 = new string[12]
						{
							text,
							"\n    ",
							((object)val2).GetType().Name,
							" '",
							((Object)val2).name,
							"'",
							val2.enabled ? "" : " (disabled)",
							val2.isTrigger ? " (trigger)" : "",
							" | extents=",
							null,
							null,
							null
						};
						val = ((Bounds)(ref bounds)).extents;
						obj2[9] = ((Vector3)(ref val)).ToString("F2");
						obj2[10] = " | centre offset from root=";
						val = ((Component)c).transform.InverseTransformPoint(((Bounds)(ref bounds)).center);
						obj2[11] = ((Vector3)(ref val)).ToString("F2");
						text = string.Concat(obj2);
					}
				}
				Log.LogMessage((object)text);
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] hurtbox dump failed: " + ex));
			}
		}

		private static string Describe(Character c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return "<null>";
			}
			return c.Name + "(local=" + c.IsLocalPlayer + ",id=" + ((Object)c).GetInstanceID() + ")";
		}

		internal void OnDestroy()
		{
			foreach (KeyValuePair<int, UnityAction<Object, DamageList>> sub in _subs)
			{
				if ((Object)(object)CharacterManager.Instance == (Object)null)
				{
					break;
				}
				foreach (Character value in CharacterManager.Instance.Characters.Values)
				{
					if (Object.op_Implicit((Object)(object)value) && ((Object)value).GetInstanceID() == sub.Key)
					{
						value.OnHitPreResistance = (UnityAction<Object, DamageList>)(object)Delegate.Remove((Delegate?)(object)value.OnHitPreResistance, (Delegate?)(object)sub.Value);
					}
				}
			}
			_subs.Clear();
			if (_harmony != null)
			{
				try
				{
					_harmony.UnpatchSelf();
				}
				catch (Exception)
				{
				}
				_harmony = null;
			}
			if (_awaitingPointFrame >= 0 && Log != null)
			{
				Log.LogWarning((object)(Stamp() + " [RunicBarrier] split #" + _awaitingPointHit + " (" + _awaitingPointSrc + ") never received a hit point - no impact sound and no spark for it."));
				_awaitingPointFrame = -1;
			}
			LogSoundTally();
			if (Log != null)
			{
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] unloaded. hits=" + _hits + " mana=" + _manaSpent.ToString("F1") + " healthShare=" + _healthLet.ToString("F1") + " negated=" + _negated.ToString("F1")));
			}
		}
	}
	internal static class RunicBladeImbueFix
	{
		private static readonly int[] Blades = new int[2] { 2000100, 2100999 };

		private static int _logged;

		private const int LOG_LIMIT = 6;

		private static void FixBow(ItemVisual visual, ImbueStack stack, Weapon weapon)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Invalid comparison between Unknown and I4
			if (stack.ParticleSystems == null || stack.ParticleSystems.Length == 0)
			{
				return;
			}
			SkinnedMeshRenderer componentInChildren = ((Component)visual).GetComponentInChildren<SkinnedMeshRenderer>(true);
			if (!Object.op_Implicit((Object)(object)componentInChildren))
			{
				return;
			}
			string text = "";
			for (int i = 0; i < stack.ParticleSystems.Length; i++)
			{
				ParticleSystem val = stack.ParticleSystems[i];
				if (Object.op_Implicit((Object)(object)val))
				{
					ShapeModule shape = val.shape;
					if (i == 0)
					{
						text = ((object)((ShapeModule)(ref shape)).shapeType/*cast due to .constrained prefix*/).ToString() + (((int)((ShapeModule)(ref shape)).shapeType == 13) ? (" on " + (Object.op_Implicit((Object)(object)((ShapeModule)(ref shape)).meshRenderer) ? ((Object)((ShapeModule)(ref shape)).meshRenderer).name : "nothing")) : "");
					}
					((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)14;
					((ShapeModule)(ref shape)).skinnedMeshRenderer = componentInChildren;
					((ShapeModule)(ref shape)).meshRenderer = null;
					val.Play();
				}
			}
			if (_logged < 6)
			{
				_logged++;
				RunicBarrierPlugin.Log.LogMessage((object)("[RunicBow] imbue (" + _logged + "/" + 6 + ") " + ((Item)weapon).Name + ": " + stack.ParticleSystems.Length + " system(s) " + (Object.op_Implicit((Object)(object)stack.ImbueFX) ? ((Object)stack.ImbueFX).name : "?") + " was " + text + " -> the bow's skinned mesh " + ((Object)componentInChildren).name));
			}
		}

		internal static void Fix(ItemVisual visual, ImbueStack stack, Weapon weapon)
		{
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Invalid comparison between Unknown and I4
			if (!Object.op_Implicit((Object)(object)visual) || stack == null || !Object.op_Implicit((Object)(object)weapon))
			{
				return;
			}
			if (((Item)weapon).ItemID == -88000)
			{
				FixBow(visual, stack, weapon);
			}
			else
			{
				if (Array.IndexOf(Blades, ((Item)weapon).ItemID) < 0 || stack.ParticleSystems == null || stack.ParticleSystems.Length == 0 || Object.op_Implicit((Object)(object)((Component)visual).GetComponentInChildren<SkinnedMeshRenderer>(true)))
				{
					return;
				}
				MeshRenderer val = BladeMesh(visual);
				if (!Object.op_Implicit((Object)(object)val))
				{
					if (_logged < 6)
					{
						_logged++;
						RunicBarrierPlugin.Log.LogWarning((object)("[RunicBlade] imbue (" + _logged + "/" + 6 + ") " + ((Item)weapon).Name + ": no blade mesh found under " + ((Object)visual).name + " - imbue left as it is"));
					}
					return;
				}
				string text = "";
				for (int i = 0; i < stack.ParticleSystems.Length; i++)
				{
					ParticleSystem val2 = stack.ParticleSystems[i];
					if (Object.op_Implicit((Object)(object)val2))
					{
						ShapeModule shape = val2.shape;
						if (i == 0)
						{
							text = ((object)((ShapeModule)(ref shape)).shapeType/*cast due to .constrained prefix*/).ToString() + (((int)((ShapeModule)(ref shape)).shapeType == 14) ? (" on " + (Object.op_Implicit((Object)(object)((ShapeModule)(ref shape)).skinnedMeshRenderer) ? ((Object)((ShapeModule)(ref shape)).skinnedMeshRenderer).name : "nothing")) : "");
						}
						((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)13;
						((ShapeModule)(ref shape)).meshRenderer = val;
						((ShapeModule)(ref shape)).skinnedMeshRenderer = null;
						val2.Play();
					}
				}
				if (_logged < 6)
				{
					_logged++;
					RunicBarrierPlugin.Log.LogMessage((object)("[RunicBlade] imbue (" + _logged + "/" + 6 + ") " + ((Item)weapon).Name + ": " + stack.ParticleSystems.Length + " system(s) " + (Object.op_Implicit((Object)(object)stack.ImbueFX) ? ((Object)stack.ImbueFX).name : "?") + " was " + text + " -> the blade's mesh " + ((Object)val).name));
				}
			}
		}

		private static MeshRenderer BladeMesh(ItemVisual visual)
		{
			MeshRenderer[] componentsInChildren = ((Component)visual).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)((Component)val).GetComponent<WeaponTrail>()) && !((Object)val).name.Contains("LeftHand"))
				{
					return val;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(ItemVisual), "AddImbueFX")]
	public class ItemVisual_AddImbueFX_RunicBlade
	{
		[HarmonyPostfix]
		public static void Postfix(ItemVisual __instance, ImbueStack __0, Weapon __1)
		{
			try
			{
				RunicBladeImbueFix.Fix(__instance, __0, __1);
			}
			catch (Exception ex)
			{
				RunicBarrierPlugin.Log.LogError((object)("[RunicBlade] imbue fix threw: " + ex));
			}
		}
	}
	internal static class RunicFlameBlast
	{
		private class Swell
		{
			public Blast Shot;

			public ParticleSystem[] Mouth;

			public Transform Core;

			public float ShotAt;

			public bool Releasing;

			public float Level;

			public Vector3 Scale;

			public ParticleSystem[] Systems;

			public ParticleSystemScalingMode[] Modes;

			public Transform[] Embers;

			public Vector3[] EmberScales;

			public Light[] Lights;

			public float[] Intensities;
		}

		private const int FAL_ITEM_ID = 8100240;

		private const string BRANCH = "RunicLightning";