Decompiled source of HearthArrows v1.0.0

HearthArrows.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("blackhearthx")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Pull your arrows and bolts back out of the world, and sometimes out of a creature.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HearthArrows")]
[assembly: AssemblyTitle("HearthArrows")]
[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 HearthArrows
{
	public class ArrowPull : MonoBehaviour, Hoverable, Interactable
	{
		private static readonly FieldInfo AttachParentField = AccessTools.Field(typeof(Projectile), "m_attachParent");

		private static int s_groundMask;

		public GameObject ItemPrefab;

		public GameObject ProjectileRoot;

		private bool _returned;

		private bool _inCreature;

		private bool _dropped;

		private Character _stuckIn;

		private Light _glow;

		private float _glowPhase;

		public void WatchCreature(Character character)
		{
			_inCreature = (Object)(object)character != (Object)null;
			_stuckIn = character;
		}

		private void Awake()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (PluginConfig.Glow.Value)
			{
				_glow = ((Component)this).gameObject.AddComponent<Light>();
				_glow.type = (LightType)2;
				_glow.color = new Color(1f, 0.55f, 0.22f);
				_glow.range = 4.5f;
				_glow.intensity = 1.3f;
				_glow.shadows = (LightShadows)0;
				_glow.renderMode = (LightRenderMode)2;
				_glowPhase = Random.Range(0f, 6.28f);
			}
		}

		private void Update()
		{
			if ((Object)(object)_glow != (Object)null)
			{
				_glow.intensity = 1.15f + Mathf.Sin(Time.time * 2.4f + _glowPhase) * 0.25f;
			}
			if (_inCreature && !_dropped && !_returned && (!((Object)(object)_stuckIn != (Object)null) || _stuckIn.IsDead()))
			{
				DropToGround();
			}
		}

		private void DropToGround()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: 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)
			_dropped = true;
			GameObject val = (((Object)(object)ProjectileRoot != (Object)null) ? ProjectileRoot : ((Component)this).gameObject);
			Projectile component = val.GetComponent<Projectile>();
			if ((Object)(object)component != (Object)null && AttachParentField != null)
			{
				AttachParentField.SetValue(component, null);
			}
			Vector3 val2 = val.transform.position;
			if (s_groundMask == 0)
			{
				s_groundMask = LayerMask.GetMask(new string[6] { "terrain", "static_solid", "Default", "Default_small", "piece", "piece_nonsolid" });
			}
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val2 + Vector3.up * 0.25f, Vector3.down, ref val3, 40f, s_groundMask, (QueryTriggerInteraction)1))
			{
				val2 = ((RaycastHit)(ref val3)).point;
			}
			else if ((Object)(object)ZoneSystem.instance != (Object)null)
			{
				val2.y = ZoneSystem.instance.GetGroundHeight(val2);
			}
			val2.y += 0.06f;
			Vector3 forward = val.transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				forward = Vector3.forward;
			}
			val.transform.SetPositionAndRotation(val2, Quaternion.LookRotation(((Vector3)(ref forward)).normalized, Vector3.up));
		}

		public string GetHoverName()
		{
			ItemDrop val = (((Object)(object)ItemPrefab != (Object)null) ? ItemPrefab.GetComponent<ItemDrop>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return "";
			}
			return val.m_itemData.m_shared.m_name;
		}

		public string GetHoverText()
		{
			return Localization.instance.Localize(GetHoverName() + "\n[<color=yellow><b>$KEY_Use</b></color>] $inventory_pickup");
		}

		public float GetHoverOffset()
		{
			return 0.35f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			if (hold || alt || _returned || (Object)(object)ItemPrefab == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			_returned = true;
			Collider component = ((Component)this).GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				component.enabled = false;
			}
			Vector3 val = ((Component)user).transform.position + ((Component)user).transform.forward * 0.75f + Vector3.up * 0.2f;
			Object.Instantiate<GameObject>(ItemPrefab, val, Random.rotation);
			GameObject val2 = (((Object)(object)ProjectileRoot != (Object)null) ? ProjectileRoot : ((Component)this).gameObject);
			Projectile component2 = val2.GetComponent<Projectile>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.SetStayTTL(0f);
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.Destroy(val2);
			}
			else
			{
				Object.Destroy((Object)(object)val2);
			}
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
	internal class ShotAmmo : MonoBehaviour
	{
		public GameObject ItemPrefab;

		public Character Owner;
	}
	[HarmonyPatch(typeof(Projectile), "Setup")]
	internal static class ProjectileSetupPatch
	{
		private static void Postfix(Projectile __instance, Character owner, ItemData ammo)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)owner == (Object)null) && owner.IsPlayer() && ammo != null && ammo.m_shared != null)
			{
				ItemType itemType = ammo.m_shared.m_itemType;
				if (((int)itemType == 9 || (int)itemType == 23) && !((Object)(object)ammo.m_dropPrefab == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<ShotAmmo>() != (Object)null))
				{
					ShotAmmo shotAmmo = ((Component)__instance).gameObject.AddComponent<ShotAmmo>();
					shotAmmo.ItemPrefab = ammo.m_dropPrefab;
					shotAmmo.Owner = owner;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Projectile), "OnHit")]
	internal static class ProjectileOnHitPatch
	{
		private sealed class HitState
		{
			public float StayTtl;

			public bool StayDynamic;

			public bool AttachBone;

			public Character Creature;
		}

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

		private static void Prefix(Projectile __instance, Collider collider, bool water, out HitState __state)
		{
			__state = null;
			if (!PluginConfig.Enabled.Value || (Object)(object)__instance == (Object)null || water)
			{
				return;
			}
			ShotAmmo component = ((Component)__instance).GetComponent<ShotAmmo>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.ItemPrefab == (Object)null || (Object)(object)((Component)__instance).GetComponentInChildren<ArrowPull>(true) != (Object)null || SkipsThisHit(__instance, component, collider, out var creature))
			{
				return;
			}
			if ((Object)(object)creature != (Object)null)
			{
				if (!Roll(PluginConfig.CreatureChance.Value))
				{
					return;
				}
			}
			else if (!StaysInWorld(__instance, collider) || !Roll(PluginConfig.WorldChance.Value))
			{
				return;
			}
			__state = new HitState
			{
				StayTtl = __instance.m_stayTTL,
				StayDynamic = __instance.m_stayAfterHitDynamic,
				AttachBone = __instance.m_attachToClosestBone,
				Creature = creature
			};
			float value = PluginConfig.StaySeconds.Value;
			if (__instance.m_stayTTL < value)
			{
				__instance.m_stayTTL = value;
			}
			if ((Object)(object)creature != (Object)null)
			{
				__instance.m_stayAfterHitDynamic = true;
				__instance.m_attachToClosestBone = true;
			}
		}

		private static void Postfix(Projectile __instance, HitState __state)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			if (__state == null || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			if (!ReadDidHit(__instance))
			{
				__instance.m_stayTTL = __state.StayTtl;
				__instance.m_stayAfterHitDynamic = __state.StayDynamic;
				__instance.m_attachToClosestBone = __state.AttachBone;
				return;
			}
			ShotAmmo component = ((Component)__instance).GetComponent<ShotAmmo>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component.ItemPrefab == (Object)null) && !((Object)(object)((Component)__instance).GetComponentInChildren<ArrowPull>(true) != (Object)null))
			{
				GameObject val = new GameObject("heartharrows_pull");
				val.transform.SetParent(((Component)__instance).transform, false);
				val.layer = 0;
				BoxCollider obj = val.AddComponent<BoxCollider>();
				((Collider)obj).isTrigger = true;
				obj.size = new Vector3(0.22f, 0.22f, 0.9f);
				obj.center = new Vector3(0f, 0f, -0.4f);
				ArrowPull arrowPull = val.AddComponent<ArrowPull>();
				arrowPull.ItemPrefab = component.ItemPrefab;
				arrowPull.ProjectileRoot = ((Component)__instance).gameObject;
				if ((Object)(object)__state.Creature != (Object)null)
				{
					arrowPull.WatchCreature(__state.Creature);
				}
			}
		}

		private static bool ReadDidHit(Projectile projectile)
		{
			if (DidHitField == null)
			{
				return true;
			}
			try
			{
				return (bool)DidHitField.GetValue(projectile);
			}
			catch (Exception)
			{
				return true;
			}
		}

		private static bool Roll(float chance)
		{
			if (chance >= 1f)
			{
				return true;
			}
			if (chance <= 0f)
			{
				return false;
			}
			return Random.value < chance;
		}

		private static bool SkipsThisHit(Projectile projectile, ShotAmmo shot, Collider collider, out Character creature)
		{
			creature = null;
			if (projectile.m_onlyStopOnTerrain && ((Object)(object)collider == (Object)null || (Object)(object)((Component)collider).GetComponent<Heightmap>() == (Object)null))
			{
				return true;
			}
			if ((Object)(object)collider != (Object)null && ((Component)collider).GetComponent<IHitProjectile>() != null)
			{
				return true;
			}
			if ((Object)(object)collider == (Object)null)
			{
				return false;
			}
			GameObject val = Projectile.FindHitObject(collider);
			IDestructible obj = (((Object)(object)val != (Object)null) ? val.GetComponent<IDestructible>() : null);
			Character val2 = (Character)(object)((obj is Character) ? obj : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			creature = val2;
			return !IsValidCreatureHit(projectile, shot, val2);
		}

		private static bool IsValidCreatureHit(Projectile projectile, ShotAmmo shot, Character character)
		{
			if ((Object)(object)character == (Object)(object)shot.Owner && !projectile.m_hitOwner)
			{
				return false;
			}
			if ((Object)(object)shot.Owner != (Object)null && !projectile.m_hitFriendly)
			{
				bool flag = BaseAI.IsEnemy(shot.Owner, character) || ((Object)(object)character.GetBaseAI() != (Object)null && character.GetBaseAI().IsAggravatable() && shot.Owner.IsPlayer());
				if (!shot.Owner.IsPlayer() && !flag)
				{
					return false;
				}
				if (shot.Owner.IsPlayer() && !shot.Owner.IsPVPEnabled() && !flag)
				{
					return false;
				}
			}
			if (projectile.m_dodgeable && character.IsDodgeInvincible())
			{
				return false;
			}
			return true;
		}

		private static bool StaysInWorld(Projectile projectile, Collider collider)
		{
			if ((Object)(object)collider != (Object)null && (Object)(object)collider.attachedRigidbody != (Object)null)
			{
				if (!projectile.m_stayAfterHitDynamic && !projectile.m_attachToClosestBone)
				{
					return projectile.m_attachToRigidBody;
				}
				return true;
			}
			return projectile.m_stayAfterHitStatic;
		}
	}
	[BepInPlugin("com.blackhearthx.heartharrows", "HearthArrows", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class HearthArrowsPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.blackhearthx.heartharrows";

		public const string PluginName = "HearthArrows";

		public const string PluginVersion = "1.0.0";

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			PluginConfig.Bind(((BaseUnityPlugin)this).Config);
			new Harmony("com.blackhearthx.heartharrows").PatchAll(typeof(HearthArrowsPlugin).Assembly);
			Logger.LogInfo((object)"HearthArrows 1.0.0 loaded");
		}
	}
	internal static class PluginConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> WorldChance;

		internal static ConfigEntry<float> CreatureChance;

		internal static ConfigEntry<float> StaySeconds;

		internal static ConfigEntry<bool> Glow;

		internal static void Bind(ConfigFile cfg)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			Enabled = cfg.Bind<bool>("Arrows", "Enabled", true, "Pull spent arrows and bolts back.");
			WorldChance = cfg.Bind<float>("Arrows", "Chance when it sticks", 1f, new ConfigDescription("Chance to keep an arrow you can pull when it sticks in the world (ground, wood, stone). 1 = always.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			CreatureChance = cfg.Bind<float>("Arrows", "Chance when it hits a creature", 0.5f, new ConfigDescription("Chance the arrow stays in a creature so you can pull it out. 0 = never, 1 = always.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			StaySeconds = cfg.Bind<float>("Arrows", "Seconds it stays", 120f, new ConfigDescription("How long a recoverable arrow stays before it vanishes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 600f), Array.Empty<object>()));
			Glow = cfg.Bind<bool>("Arrows", "Glow", true, "A small warm light on arrows you can still pull, so you can find them at night.");
		}
	}
}