using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using StopPullingArrows.Patches;
using StopPullingArrows.Utils;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("StopPullingArrows")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("StopPullingArrows")]
[assembly: AssemblyTitle("StopPullingArrows")]
[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 StopPullingArrows
{
[BepInPlugin("StopPullingArrows", "StopPullingArrows", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "StopPullingArrows";
public const string PluginName = "StopPullingArrows";
public const string PluginVersion = "1.0.0";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<bool> DebugLogging;
private static bool disabledByError;
internal static bool Active
{
get
{
if (!disabledByError && Enabled != null)
{
return Enabled.Value;
}
return false;
}
}
private void Awake()
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Let interactables (chains, ropes, vines, pitons, items...) take priority over arrows stuck in your own character.");
DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Log when an embedded arrow is skipped in favor of another interactable.");
Log.LogInfo((object)"Loaded.");
try
{
InteractionPatch.TryApply(new Harmony("StopPullingArrows"));
}
catch (Exception ex)
{
Log.LogError((object)("Failed to apply interaction patch: " + ex));
Log.LogError((object)"Patch disabled; game behavior remains unchanged.");
}
}
internal static void DisableAfterError(Exception e)
{
if (!disabledByError)
{
disabledByError = true;
Log.LogError((object)("Unexpected error while adjusting interaction priority: " + e));
Log.LogError((object)"Patch disabled; game behavior remains unchanged.");
}
}
}
}
namespace StopPullingArrows.Utils
{
internal static class ArrowInteractionUtils
{
private static readonly RaycastHit[] lineHits = (RaycastHit[])(object)new RaycastHit[64];
private static readonly RaycastHit[] sphereHits = (RaycastHit[])(object)new RaycastHit[100];
private static FieldRef<CharacterRagdoll, List<Collider>> ragdollColliders;
private static Object lastLoggedTarget;
internal static bool Initialize(out string missing)
{
missing = null;
if (AccessTools.Field(typeof(Interaction), "distance") == null)
{
missing = "Interaction.distance";
}
else if (AccessTools.Field(typeof(Interaction), "area") == null)
{
missing = "Interaction.area";
}
else if (AccessTools.Field(typeof(ThornOnMe), "character") == null)
{
missing = "ThornOnMe.character";
}
else if (AccessTools.Field(typeof(ThornOnMe), "stuckIn") == null)
{
missing = "ThornOnMe.stuckIn";
}
else if (AccessTools.PropertyGetter(typeof(ThornOnMe), "isArrow") == null)
{
missing = "ThornOnMe.isArrow";
}
else if (AccessTools.Field(typeof(Character), "localCharacter") == null)
{
missing = "Character.localCharacter";
}
else if (AccessTools.Field(typeof(MainCamera), "instance") == null)
{
missing = "MainCamera.instance";
}
else if (AccessTools.Field(typeof(CharacterRagdoll), "colliderList") == null)
{
missing = "CharacterRagdoll.colliderList";
}
else if (AccessTools.Method(typeof(Item), "TryGetItemFromCollider", (Type[])null, (Type[])null) == null)
{
missing = "Item.TryGetItemFromCollider";
}
else if (AccessTools.Method(typeof(HelperFunctions), "LineCheckAll", (Type[])null, (Type[])null) == null)
{
missing = "HelperFunctions.LineCheckAll";
}
if (missing != null)
{
return false;
}
ragdollColliders = AccessTools.FieldRefAccess<CharacterRagdoll, List<Collider>>("colliderList");
return true;
}
internal static void ApplyPriority(Interaction interaction, ref IInteractible result, bool ignoreInteractable)
{
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter == (Object)null || !IsLocalEmbeddedArrow(result, localCharacter))
{
lastLoggedTarget = null;
}
else
{
if ((Object)(object)MainCamera.instance == (Object)null)
{
return;
}
IInteractible val = FindWorldInteractable(interaction, localCharacter, ignoreInteractable);
if (val == null)
{
lastLoggedTarget = null;
return;
}
if (Plugin.DebugLogging.Value)
{
LogReplacement(val);
}
result = val;
}
}
internal static bool IsLocalEmbeddedArrow(IInteractible interactible, Character local)
{
ThornOnMe val = (ThornOnMe)(object)((interactible is ThornOnMe) ? interactible : null);
if ((Object)(object)val != (Object)null && (val is ArrowOnMe || val.isArrow) && val.stuckIn)
{
return (Object)(object)val.character == (Object)(object)local;
}
return false;
}
internal static bool IsClimbable(IInteractible interactible)
{
if (!(interactible is JungleVine) && !(interactible is RopeSegment))
{
return interactible is ClimbHandle;
}
return true;
}
private static IInteractible FindWorldInteractable(Interaction interaction, Character local, bool ignoreInteractable)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: 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_00b1: 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_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_021c: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_022d: Unknown result type (might be due to invalid IL or missing references)
Transform transform = ((Component)MainCamera.instance).transform;
Vector3 position = transform.position;
Vector3 forward = transform.forward;
float distance = interaction.distance;
float area = interaction.area;
List<Collider> list = ((local.refs != null && (Object)(object)local.refs.ragdoll != (Object)null) ? ragdollColliders.Invoke(local.refs.ragdoll) : null);
Item heldItem = (((Object)(object)local.data != (Object)null) ? local.data.currentItem : null);
int num = HelperFunctions.LineCheckAll(position, position + forward * distance, (LayerType)0, lineHits, 0f, (QueryTriggerInteraction)2);
Collider val = null;
float num2 = distance;
for (int i = 0; i < num; i++)
{
RaycastHit val2 = lineHits[i];
Collider collider = ((RaycastHit)(ref val2)).collider;
if (!((Object)(object)collider == (Object)null) && Object.op_Implicit((Object)(object)((RaycastHit)(ref val2)).transform) && !(((RaycastHit)(ref val2)).distance >= num2) && (list == null || !list.Contains(collider)) && !IsHeldItem(collider, heldItem) && !IsArrowCollider(collider, local))
{
num2 = ((RaycastHit)(ref val2)).distance;
val = collider;
}
}
if ((Object)(object)val != (Object)null)
{
IInteractible componentInParent = ((Component)val).GetComponentInParent<IInteractible>();
if (IsWorldCandidate(componentInParent) && (ignoreInteractable || componentInParent.IsInteractible(local)))
{
return componentInParent;
}
}
int num3 = Physics.SphereCastNonAlloc(position + forward * (area / 2f), area, forward, sphereHits, num2, LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)0)), (QueryTriggerInteraction)2);
IInteractible result = null;
bool flag = false;
float num4 = float.MaxValue;
for (int j = 0; j < num3; j++)
{
RaycastHit val3 = sphereHits[j];
Collider collider2 = ((RaycastHit)(ref val3)).collider;
if ((Object)(object)collider2 == (Object)null || IsHeldItem(collider2, heldItem) || IsArrowCollider(collider2, local))
{
continue;
}
IInteractible componentInParent2 = ((Component)collider2).GetComponentInParent<IInteractible>();
if (!IsWorldCandidate(componentInParent2))
{
continue;
}
bool flag2 = IsClimbable(componentInParent2);
float num5 = Vector3.Angle(((RaycastHit)(ref val3)).point - position, forward);
if ((!flag || flag2) && (flag2 != flag || !(num5 >= num4)) && componentInParent2.IsInteractible(local))
{
RaycastHit val4 = HelperFunctions.LineCheck(position, ((RaycastHit)(ref val3)).point, (LayerType)1, 0f, (QueryTriggerInteraction)2);
if (!((Object)(object)((RaycastHit)(ref val4)).collider != (Object)null) || ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<IInteractible>() == componentInParent2)
{
result = componentInParent2;
flag = flag2;
num4 = num5;
}
}
}
return result;
}
private static bool IsWorldCandidate(IInteractible interactible)
{
if (interactible != null)
{
return !(interactible is ThornOnMe);
}
return false;
}
private static bool IsHeldItem(Collider col, Item heldItem)
{
Item val = default(Item);
if ((Object)(object)heldItem != (Object)null && Item.TryGetItemFromCollider(col, ref val))
{
return (Object)(object)val == (Object)(object)heldItem;
}
return false;
}
private static bool IsArrowCollider(Collider col, Character local)
{
Transform parent = ((Component)col).transform.parent;
ArrowOnMe val = default(ArrowOnMe);
if ((Object)(object)parent != (Object)null && ((Component)parent).TryGetComponent<ArrowOnMe>(ref val))
{
return true;
}
ThornOnMe componentInParent = ((Component)col).GetComponentInParent<ThornOnMe>();
if ((Object)(object)componentInParent != (Object)null && componentInParent.isArrow)
{
return (Object)(object)componentInParent.character == (Object)(object)local;
}
return false;
}
private static void LogReplacement(IInteractible target)
{
Transform transform = target.GetTransform();
Object val = (Object)(object)(((Object)(object)transform != (Object)null) ? transform : null);
if (!(val != (Object)null) || !(val == lastLoggedTarget))
{
lastLoggedTarget = val;
string text = ((target is JungleVine) ? "Chain/Vine" : ((target is RopeSegment) ? "Rope" : ((target is ClimbHandle) ? "ClimbHandle" : ((object)target).GetType().Name)));
string text2 = (((Object)(object)transform != (Object)null) ? ((Object)((Component)transform).gameObject).name : "?");
Plugin.Log.LogInfo((object)("Ignored local embedded arrow in favor of " + text + " (" + text2 + ")."));
}
}
}
}
namespace StopPullingArrows.Patches
{
internal static class InteractionPatch
{
private const string TargetMethod = "DoInteractableRaycasts";
internal static bool TryApply(Harmony harmony)
{
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeof(Interaction), "DoInteractableRaycasts", new Type[3]
{
typeof(IInteractible).MakeByRefType(),
typeof(float),
typeof(bool)
}, (Type[])null);
if (methodInfo == null)
{
Plugin.Log.LogError((object)"Failed to locate interaction target method.");
Plugin.Log.LogError((object)"Patch disabled; game behavior remains unchanged.");
return false;
}
if (!ArrowInteractionUtils.Initialize(out var missing))
{
Plugin.Log.LogError((object)("Failed to locate required game member: " + missing));
Plugin.Log.LogError((object)"Patch disabled; game behavior remains unchanged.");
return false;
}
harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(InteractionPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Plugin.Log.LogInfo((object)"Interaction priority patch applied.");
return true;
}
private static void Postfix(Interaction __instance, ref IInteractible interactableResult, float overrideDistance, bool ignoreInteractable)
{
if (!Plugin.Active || overrideDistance != -1f)
{
return;
}
try
{
ArrowInteractionUtils.ApplyPriority(__instance, ref interactableResult, ignoreInteractable);
}
catch (Exception e)
{
Plugin.DisableAfterError(e);
}
}
}
}