using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using Photon.Pun;
using UnityEngine;
using Zorro.Core;
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Expelliarmus;
[BepInPlugin("com.dawwnforu.expelliarmus", "Expelliarmus", "1.0.9")]
[BepInProcess("PEAK.exe")]
public class Plugin : BaseUnityPlugin
{
private void Awake()
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Expelliarmus v1.0.9 loading...");
ExpelliarmusBehaviour.Initialize(((BaseUnityPlugin)this).Logger);
((BaseUnityPlugin)this).Logger.LogInfo((object)"Expelliarmus loaded successfully!");
((BaseUnityPlugin)this).Logger.LogInfo((object)" Right click while aiming at a teammate's held item = steal it into your hand.");
}
private void OnDestroy()
{
ExpelliarmusBehaviour.Shutdown();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Expelliarmus unloaded");
}
}
public static class PluginInfo
{
public const string GUID = "com.dawwnforu.expelliarmus";
public const string Name = "Expelliarmus";
public const string Version = "1.0.9";
}
public class ExpelliarmusBehaviour : MonoBehaviour
{
private const float MaxRange = 7.5f;
private const float AimAngle = 25f;
private const float SyncTimeout = 4f;
private static ExpelliarmusBehaviour instance;
private ManualLogSource logger;
private bool busy;
private bool usedThisPress;
private float nextAttempt;
private Item droppedItem;
private Item handoffItem;
private void ReleaseHandoff()
{
//IL_0076: 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)
Item val = handoffItem;
handoffItem = null;
if ((Object)(object)val != (Object)null && val.data != null && IsGroundItem(val, val.data.guid) && (Object)(object)PhotonNetwork.GetPhotonView(((MonoBehaviourPun)val).photonView.ViewID) == (Object)(object)((MonoBehaviourPun)val).photonView)
{
((MonoBehaviourPun)val).photonView.RPC("SetKinematicRPC", (RpcTarget)5, new object[3]
{
false,
val.transform.position,
val.transform.rotation
});
}
}
private void OnDisable()
{
((MonoBehaviour)this).StopAllCoroutines();
ReleaseHandoff();
busy = false;
}
public static void Initialize(ManualLogSource log)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
if (!((Object)(object)instance != (Object)null))
{
GameObject val = new GameObject("ExpelliarmusManager");
Object.DontDestroyOnLoad((Object)(object)val);
instance = val.AddComponent<ExpelliarmusBehaviour>();
instance.logger = log;
}
}
public static void Shutdown()
{
if ((Object)(object)instance != (Object)null)
{
Object.Destroy((Object)(object)((Component)instance).gameObject);
}
instance = null;
}
private void Update()
{
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.input == (Object)null)
{
return;
}
if (!localCharacter.input.useSecondaryIsPressed)
{
usedThisPress = false;
}
else
{
if (busy || usedThisPress || Time.unscaledTime < nextAttempt || !CanAct(localCharacter))
{
return;
}
nextAttempt = Time.unscaledTime + 0.1f;
Character val = FindTarget(localCharacter);
if (!((Object)(object)val == (Object)null))
{
Item currentItem = val.data.currentItem;
ItemSlot val2 = HeldSlot(val, currentItem);
if (val2 != null && val2.itemSlotID <= 2)
{
usedThisPress = true;
busy = true;
((MonoBehaviour)this).StartCoroutine(Transfer(localCharacter, val, currentItem));
}
}
}
}
private static bool CanAct(Character character)
{
if (PhotonNetwork.InRoom && (Object)(object)character != (Object)null && character.IsLocal && (Object)(object)character.data != (Object)null && character.data.fullyConscious && !character.data.isClimbingAnything && character.refs != null && (Object)(object)character.refs.items != (Object)null && (Object)(object)character.player != (Object)null && (Object)(object)GUIManager.instance != (Object)null && !GUIManager.instance.windowBlockingInput)
{
return !GUIManager.instance.wheelActive;
}
return false;
}
private static Character FindTarget(Character local)
{
//IL_0017: 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_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Invalid comparison between Unknown and I4
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
Camera main = Camera.main;
if ((Object)(object)main == (Object)null)
{
return null;
}
RaycastHit[] array = Physics.RaycastAll(new Ray(((Component)main).transform.position, ((Component)main).transform.forward), 7.5f, -1, (QueryTriggerInteraction)1);
Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
RaycastHit[] array2 = array;
for (int num = 0; num < array2.Length; num++)
{
RaycastHit val = array2[num];
Item componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Item>();
Character val2 = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>();
if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.trueHolderCharacter != (Object)null)
{
val2 = componentInParent.trueHolderCharacter;
}
if (!((Object)(object)val2 == (Object)(object)local))
{
if ((Object)(object)val2 == (Object)null || (Object)(object)val2.data == (Object)null)
{
return null;
}
Item currentItem = val2.data.currentItem;
if ((Object)(object)currentItem == (Object)null || (int)currentItem.itemState != 1)
{
return null;
}
Vector3 val3 = currentItem.transform.position - ((Component)main).transform.position;
if (((Vector3)(ref val3)).magnitude > 7.5f)
{
return null;
}
return ((Object)(object)componentInParent == (Object)(object)currentItem || Vector3.Angle(((Component)main).transform.forward, val3) <= 25f) ? val2 : null;
}
}
return null;
}
private static ItemSlot HeldSlot(Character character, Item item)
{
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.items == (Object)null || (Object)(object)character.player == (Object)null || (Object)(object)item == (Object)null || item.data == null || item.data.guid == Guid.Empty || (Object)(object)character.data.currentItem != (Object)(object)item || (Object)(object)item.trueHolderCharacter != (Object)(object)character || !item.UIData.canDrop)
{
return null;
}
Optionable<byte> currentSelectedSlot = character.refs.items.currentSelectedSlot;
if (currentSelectedSlot.IsNone)
{
return null;
}
ItemSlot itemSlot = character.player.GetItemSlot(currentSelectedSlot.Value);
if (itemSlot == null || itemSlot.IsEmpty() || itemSlot.data == null || itemSlot.prefab.itemID != item.itemID || !(itemSlot.data.guid == item.data.guid))
{
return null;
}
return itemSlot;
}
private IEnumerator Transfer(Character local, Character target, Item original)
{
try
{
Guid guid = original.data.guid;
Item localItem = local.data.currentItem;
if ((Object)(object)localItem != (Object)null)
{
yield return DropHeldItem(local, localItem);
if ((Object)(object)droppedItem == (Object)null)
{
yield break;
}
}
if (!CanAct(local) || (Object)(object)local.data.currentItem != (Object)null || (Object)(object)original == (Object)null || original.data.guid != guid || HeldSlot(target, original) == null || !local.player.HasEmptySlot(original.itemID))
{
yield break;
}
Camera camera = Camera.main;
if ((Object)(object)camera == (Object)null)
{
yield break;
}
Vector3 handPosition = ((Component)camera).transform.position + ((Component)camera).transform.forward * 0.6f + Vector3.down * 0.25f;
yield return DropHeldItem(target, original, handPosition);
Item ground = droppedItem;
if ((Object)(object)ground == (Object)null || !CanAct(local) || (Object)(object)local.data.currentItem != (Object)null || !local.player.HasEmptySlot(ground.itemID) || !IsGroundItem(ground, guid))
{
yield break;
}
((MonoBehaviourPun)ground).photonView.RPC("RequestPickup", (RpcTarget)2, new object[1] { ((MonoBehaviourPun)local).photonView });
float deadline = Time.unscaledTime + 4f;
while (Time.unscaledTime < deadline && (Object)(object)local != (Object)null && (Object)(object)local.player != (Object)null)
{
if (InventoryContains(local.player, guid))
{
logger.LogInfo((object)"Expelliarmus: inventory pickup confirmed.");
yield break;
}
yield return (object)new WaitForSecondsRealtime(0.05f);
}
logger.LogWarning((object)"Expelliarmus: pickup not confirmed; no retry or replacement item created.");
}
finally
{
ReleaseHandoff();
busy = false;
nextAttempt = Time.unscaledTime + 0.4f;
}
}
private IEnumerator DropHeldItem(Character character, Item original, Vector3? handPosition = null)
{
droppedItem = null;
ItemSlot slot = HeldSlot(character, original);
if (slot == null)
{
yield break;
}
Guid guid = original.data.guid;
int originalViewID = ((MonoBehaviourPun)original).photonView.ViewID;
if (originalViewID <= 0)
{
yield break;
}
CharacterItems characterItems = character.refs.items;
((MonoBehaviourPun)characterItems).photonView.RPC("DropItemFromSlotRPC", (RpcTarget)2, new object[2]
{
slot.itemSlotID,
(object)(Vector3)(((??)handPosition) ?? (original.transform.position + Vector3.down * 0.2f))
});
float deadline = Time.unscaledTime + 4f;
Item ground = null;
while (Time.unscaledTime < deadline)
{
ground = FindGroundItem(guid);
if ((Object)(object)ground != (Object)null && handPosition.HasValue && (Object)(object)handoffItem == (Object)null)
{
handoffItem = ground;
((MonoBehaviourPun)ground).photonView.RPC("SetKinematicRPC", (RpcTarget)5, new object[3]
{
true,
handPosition.Value,
ground.transform.rotation
});
}
if ((Object)(object)ground != (Object)null && (Object)(object)character != (Object)null && (Object)(object)character.player != (Object)null && !InventoryContains(character.player, guid))
{
break;
}
yield return null;
}
if ((Object)(object)ground == (Object)null || (Object)(object)character == (Object)null || (Object)(object)character.player == (Object)null || InventoryContains(character.player, guid))
{
logger.LogWarning((object)"Expelliarmus: drop not confirmed; held object was not removed by this mod.");
yield break;
}
if ((Object)(object)character.data.currentItem == (Object)(object)original && (Object)(object)original != (Object)null && ((MonoBehaviourPun)original).photonView.ViewID == originalViewID)
{
if (character.IsLocal)
{
characterItems.EquipSlot(Optionable<byte>.None);
}
else
{
((MonoBehaviourPun)characterItems).photonView.RPC("EquipSlotRpc", (RpcTarget)5, new object[2] { -1, -1 });
}
}
deadline = Time.unscaledTime + 4f;
while ((Object)(object)PhotonNetwork.GetPhotonView(originalViewID) != (Object)null && Time.unscaledTime < deadline)
{
yield return null;
}
if ((Object)(object)PhotonNetwork.GetPhotonView(originalViewID) != (Object)null)
{
logger.LogWarning((object)"Expelliarmus: owner release not confirmed; pickup cancelled, ground item retained.");
}
else
{
droppedItem = FindGroundItem(guid);
}
}
private static bool InventoryContains(Player player, Guid guid)
{
ItemSlot[] itemSlots = player.itemSlots;
foreach (ItemSlot slot in itemSlots)
{
if (SlotContains(slot, guid))
{
return true;
}
}
if (!SlotContains(player.GetItemSlot((byte)3), guid))
{
return SlotContains(player.GetItemSlot((byte)250), guid);
}
return true;
}
private static bool SlotContains(ItemSlot slot, Guid guid)
{
if (slot != null && !slot.IsEmpty() && slot.data != null)
{
return slot.data.guid == guid;
}
return false;
}
private static Item FindGroundItem(Guid guid)
{
foreach (Item aLL_ITEM in Item.ALL_ITEMS)
{
if (IsGroundItem(aLL_ITEM, guid))
{
return aLL_ITEM;
}
}
return null;
}
private static bool IsGroundItem(Item item, Guid guid)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)item != (Object)null && item.data != null && item.data.guid == guid && (int)item.itemState == 0 && (Object)(object)item.trueHolderCharacter == (Object)null && (Object)(object)((MonoBehaviourPun)item).photonView != (Object)null && ((MonoBehaviourPun)item).photonView.IsRoomView)
{
return ((MonoBehaviourPun)item).photonView.ViewID > 0;
}
return false;
}
}