Decompiled source of RunicBowRU v2.0.5

RunicBow.dll

Decompiled 20 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SideLoader;
using UnityEngine;

[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("RunicBow")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RunicBow")]
[assembly: AssemblyTitle("RunicBow")]
[assembly: AssemblyVersion("2.0.2.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_013e: 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)
					{
						float finalManaConsumption = ownerCharacter.Stats.GetFinalManaConsumption((Tag[])null, 5f);
						ownerCharacter.Stats.UseMana((Tag[])null, finalManaConsumption);
					}
					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
		{
			[HarmonyPostfix]
			public static void Postfix(SummonedEquipment __instance, bool _expired)
			{
				if (!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<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.runicbow", "Runic Bow", "2.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RunicBowPlugin : BaseUnityPlugin
	{
		public const string GUID = "com.wrango.runicbow";

		public const string NAME = "Runic Bow";

		public const string VERSION = "2.0.2";

		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.runicbow");
			SL.BeforePacksLoaded += RunicBowManager.BeforePacksLoaded;
			SL.OnPacksLoaded += RunicBowManager.OnPacksLoaded;
			SL.OnGameplayResumedAfterLoading += RunicBowManager.OnGameplayResumed;
			try
			{
				harmony.PatchAll();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Harmony patching failed - the bow will not work correctly: " + ex));
			}
			Log.LogMessage((object)"Runic Bow 2.0.2 loaded.");
		}
	}
}