using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 TradeForReviveMod
{
[BepInPlugin("REPOJP.TradeForRevive", "TradeForRevive", "1.1.0")]
public sealed class TradeForRevivePlugin : BaseUnityPlugin
{
public const string PluginGuid = "REPOJP.TradeForRevive";
public const string PluginName = "TradeForRevive";
public const string PluginVersion = "1.1.0";
internal static TradeForRevivePlugin Instance;
internal static ManualLogSource Log;
private void Awake()
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
try
{
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
((Component)this).transform.parent = null;
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
GameObject val = new GameObject("TradeForReviveManager");
val.transform.parent = null;
((Object)val).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)val);
val.AddComponent<TradeForReviveManager>();
((BaseUnityPlugin)this).Logger.LogInfo((object)"TradeForRevive 1.1.0 loaded");
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Awake failed\n" + ex));
}
}
}
internal sealed class TradeForReviveManager : MonoBehaviour
{
private sealed class HoldState
{
public int ItemKey;
public float StartTime;
}
private sealed class TradeCandidate
{
public PlayerDeathHead DeathHead;
public PlayerAvatar PlayerAvatar;
public PhysGrabObject PhysGrabObject;
public ItemAttributes ItemAttributes;
public string SourceLabel;
public int TargetHp;
public bool IsUsedHealthPack;
public float DistanceSqr;
}
private struct ReviveValueResult
{
public bool Valid;
public int TargetHp;
public string SourceLabel;
public bool IsUsedHealthPack;
}
[CompilerGenerated]
private sealed class <ExecuteTradeReviveRoutine>d__36 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public TradeCandidate candidate;
public int headViewId;
public int itemKey;
public TradeForReviveManager <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ExecuteTradeReviveRoutine>d__36(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (!<>4__this.CanExecuteTrade(candidate))
{
<>4__this.ReleaseTradeLocks(headViewId, itemKey, consumed: false);
return false;
}
<>4__this.ForceReleaseAllGrabbers(candidate.PhysGrabObject);
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
if (!<>4__this.CanExecuteTrade(candidate))
{
<>4__this.ReleaseTradeLocks(headViewId, itemKey, consumed: false);
return false;
}
<>4__this.ExecuteTradeCore(candidate);
<>2__current = null;
<>1__state = 2;
return true;
case 2:
<>1__state = -1;
<>2__current = null;
<>1__state = 3;
return true;
case 3:
<>1__state = -1;
<>2__current = null;
<>1__state = 4;
return true;
case 4:
<>1__state = -1;
<>4__this.FinalizeReviveHealth(candidate, headViewId);
<>4__this.ReleaseTradeLocks(headViewId, itemKey, consumed: true);
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static ConfigEntry<bool> configEnableMod;
private static ConfigEntry<float> configDetectRadius;
private static ConfigEntry<float> configTouchHoldSeconds;
private static ConfigEntry<float> configScanInterval;
private static ConfigEntry<float> configHeadCooldown;
private static ConfigEntry<bool> configRequirePurchasedItem;
private static ConfigEntry<bool> configAllowBatteryItems;
private static ConfigEntry<bool> configAllowHealthPacks;
private static ConfigEntry<bool> configAllowUsedHealthPacks;
private static ConfigEntry<bool> configAllowZeroBatteryRevive;
private static ConfigEntry<bool> configConsumeItem;
private static ConfigEntry<bool> configDestroyWithEffects;
private static ConfigEntry<bool> configDebugLog;
private static readonly FieldInfo FieldPlayerDeathHeadTriggered = typeof(PlayerDeathHead).GetField("triggered", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo FieldPlayerDeathHeadInExtractionPoint = typeof(PlayerDeathHead).GetField("inExtractionPoint", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo FieldPlayerAvatarIsDisabled = typeof(PlayerAvatar).GetField("isDisabled", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo FieldPlayerHealthHealth = typeof(PlayerHealth).GetField("health", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo FieldPlayerHealthMaxHealth = typeof(PlayerHealth).GetField("maxHealth", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo FieldItemAttributesInstanceName = typeof(ItemAttributes).GetField("instanceName", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo FieldItemHealthPackUsed = typeof(ItemHealthPack).GetField("used", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo FieldPhysGrabObjectImpactDetector = typeof(PhysGrabObject).GetField("impactDetector", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo FieldPlayerDeathHeadPhysGrabObject = typeof(PlayerDeathHead).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.NonPublic);
private readonly Dictionary<int, float> headCooldownUntil = new Dictionary<int, float>();
private readonly HashSet<int> runningHeadIds = new HashSet<int>();
private readonly HashSet<int> runningItemIds = new HashSet<int>();
private readonly HashSet<int> consumedItemIds = new HashSet<int>();
private readonly Dictionary<int, HoldState> holdStates = new Dictionary<int, HoldState>();
private float scanTimer;
private void Awake()
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Expected O, but got Unknown
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Expected O, but got Unknown
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Expected O, but got Unknown
try
{
if (configEnableMod == null)
{
ConfigFile config = ((BaseUnityPlugin)TradeForRevivePlugin.Instance).Config;
configEnableMod = config.Bind<bool>("General", "EnableMod", true, "Enable revive trading system.蘇生トレード機能の有効化");
configDetectRadius = config.Bind<float>("General", "DetectRadius", 0.55f, new ConfigDescription("Detection radius around a death head for trade items.デスヘッド周囲で引き換えアイテムを検知する半径", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
configTouchHoldSeconds = config.Bind<float>("General", "TouchHoldSeconds", 2f, new ConfigDescription("Required continuous contact time before revive trade activates.蘇生トレードが発動するまでに必要な連続接触時間 秒", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
configScanInterval = config.Bind<float>("General", "ScanInterval", 0.05f, new ConfigDescription("Scan interval in seconds.検知処理の実行間隔 秒", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
configHeadCooldown = config.Bind<float>("General", "HeadCooldown", 0.75f, new ConfigDescription("Cooldown per death head after a successful trade.蘇生成功後の同一デスヘッド再判定クールダウン 秒", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
configRequirePurchasedItem = config.Bind<bool>("General", "RequirePurchasedItem", true, "Only allow purchased items to be traded.購入済みアイテムのみ引き換え対象にする");
configAllowBatteryItems = config.Bind<bool>("General", "AllowBatteryItems", true, "Allow battery powered items as revive payment.バッテリー付きアイテムを蘇生素材として許可する");
configAllowHealthPacks = config.Bind<bool>("General", "AllowHealthPacks", true, "Allow health packs as revive payment.ヘルスパックを蘇生素材として許可する");
configAllowUsedHealthPacks = config.Bind<bool>("General", "AllowUsedHealthPacks", true, "Allow used health packs to revive with 1 HP.使用済みヘルスパックによるHP1蘇生を許可する");
configAllowZeroBatteryRevive = config.Bind<bool>("General", "AllowZeroBatteryRevive", true, "Allow battery items with zero charge to revive with 1 HP.残量0のバッテリーでもHP1で蘇生を許可する");
configConsumeItem = config.Bind<bool>("General", "ConsumeItem", true, "Consume the traded item on success.蘇生成功時にアイテムを消費する");
configDestroyWithEffects = config.Bind<bool>("General", "DestroyWithEffects", true, "Destroy normal consumed items with break effects. 空のヘルスパック以外の消費アイテムを破壊演出ありで消す");
configDebugLog = config.Bind<bool>("Debug", "DebugLog", false, "Enable verbose debug logging.詳細デバッグログの有効化");
}
((Component)this).transform.parent = null;
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("Manager Awake failed\n" + ex));
}
}
private void Update()
{
try
{
if (configEnableMod == null || !configEnableMod.Value || !SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.RunIsLevel())
{
return;
}
scanTimer -= Time.deltaTime;
if (scanTimer > 0f)
{
return;
}
scanTimer = configScanInterval.Value;
if (!((Object)(object)GameDirector.instance == (Object)null) && GameDirector.instance.PlayerList != null)
{
for (int i = 0; i < GameDirector.instance.PlayerList.Count; i++)
{
PlayerAvatar player = GameDirector.instance.PlayerList[i];
TryProcessPlayerDeathHead(player);
}
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("Update failed\n" + ex));
}
}
private void TryProcessPlayerDeathHead(PlayerAvatar player)
{
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)player == (Object)null || (Object)(object)player.playerDeathHead == (Object)null || (Object)(object)player.playerHealth == (Object)null || !GetPlayerIsDisabled(player))
{
return;
}
PlayerDeathHead playerDeathHead = player.playerDeathHead;
PhysGrabObject deathHeadPhysGrabObject = GetDeathHeadPhysGrabObject(playerDeathHead);
if (!IsDeathHeadTriggered(playerDeathHead) || (Object)(object)deathHeadPhysGrabObject == (Object)null)
{
return;
}
PhotonView component = ((Component)playerDeathHead).GetComponent<PhotonView>();
int num = (((Object)(object)component != (Object)null) ? component.ViewID : ((Object)playerDeathHead).GetInstanceID());
if (runningHeadIds.Contains(num) || (headCooldownUntil.TryGetValue(num, out var value) && Time.time < value))
{
return;
}
Collider[] array = Physics.OverlapSphere(deathHeadPhysGrabObject.centerPoint, configDetectRadius.Value, -1, (QueryTriggerInteraction)2);
if (array == null || array.Length == 0)
{
return;
}
TradeCandidate tradeCandidate = null;
for (int i = 0; i < array.Length; i++)
{
TradeCandidate tradeCandidate2 = BuildCandidateFromCollider(array[i], playerDeathHead);
if (tradeCandidate2 != null && (tradeCandidate == null || tradeCandidate2.DistanceSqr < tradeCandidate.DistanceSqr))
{
tradeCandidate = tradeCandidate2;
}
}
if (tradeCandidate == null)
{
ClearHoldState(num);
}
else if (UpdateHoldStateAndCheckReady(num, tradeCandidate))
{
int tradeItemKey = GetTradeItemKey(tradeCandidate.PhysGrabObject, tradeCandidate.ItemAttributes);
if (!TryLockTradeItem(tradeItemKey))
{
ClearHoldState(num);
return;
}
runningHeadIds.Add(num);
ClearHoldState(num);
ClearHoldStatesByItem(tradeItemKey);
((MonoBehaviour)this).StartCoroutine(ExecuteTradeReviveRoutine(tradeCandidate, num, tradeItemKey));
}
}
private TradeCandidate BuildCandidateFromCollider(Collider hitCollider, PlayerDeathHead deathHead)
{
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)hitCollider == (Object)null)
{
return null;
}
PlayerDeathHead componentInParent = ((Component)hitCollider).GetComponentInParent<PlayerDeathHead>();
if ((Object)(object)componentInParent != (Object)null)
{
return null;
}
PhysGrabObject componentInParent2 = ((Component)hitCollider).GetComponentInParent<PhysGrabObject>();
if ((Object)(object)componentInParent2 == (Object)null)
{
return null;
}
PhysGrabObject deathHeadPhysGrabObject = GetDeathHeadPhysGrabObject(deathHead);
if ((Object)(object)componentInParent2 == (Object)(object)deathHeadPhysGrabObject)
{
return null;
}
ItemAttributes val = ((Component)componentInParent2).GetComponent<ItemAttributes>();
if ((Object)(object)val == (Object)null)
{
val = ((Component)componentInParent2).GetComponentInParent<ItemAttributes>();
}
if ((Object)(object)val == (Object)null || (Object)(object)val.item == (Object)null)
{
return null;
}
if (!IsTradeItemCurrentlyHeld(componentInParent2))
{
return null;
}
int tradeItemKey = GetTradeItemKey(componentInParent2, val);
if (IsTradeItemLocked(tradeItemKey))
{
return null;
}
int playerMaxHealth = GetPlayerMaxHealth(deathHead.playerAvatar);
ReviveValueResult reviveValue = GetReviveValue(val, componentInParent2, playerMaxHealth);
if (!reviveValue.Valid)
{
return null;
}
if (configRequirePurchasedItem.Value && !IsPurchasedTradeItem(val) && (!reviveValue.IsUsedHealthPack || !configAllowUsedHealthPacks.Value))
{
return null;
}
if ((Object)(object)deathHeadPhysGrabObject == (Object)null)
{
return null;
}
TradeCandidate tradeCandidate = new TradeCandidate();
tradeCandidate.DeathHead = deathHead;
tradeCandidate.PlayerAvatar = deathHead.playerAvatar;
tradeCandidate.PhysGrabObject = componentInParent2;
tradeCandidate.ItemAttributes = val;
tradeCandidate.SourceLabel = reviveValue.SourceLabel;
tradeCandidate.TargetHp = Mathf.Clamp(reviveValue.TargetHp, 1, playerMaxHealth);
tradeCandidate.IsUsedHealthPack = reviveValue.IsUsedHealthPack;
Vector3 val2 = componentInParent2.centerPoint - deathHeadPhysGrabObject.centerPoint;
tradeCandidate.DistanceSqr = ((Vector3)(ref val2)).sqrMagnitude;
return tradeCandidate;
}
private bool UpdateHoldStateAndCheckReady(int headViewId, TradeCandidate candidate)
{
if (candidate == null || (Object)(object)candidate.PhysGrabObject == (Object)null)
{
ClearHoldState(headViewId);
return false;
}
int tradeItemKey = GetTradeItemKey(candidate.PhysGrabObject, candidate.ItemAttributes);
float time = Time.time;
if (!holdStates.TryGetValue(headViewId, out var value))
{
value = new HoldState();
value.ItemKey = tradeItemKey;
value.StartTime = time;
holdStates[headViewId] = value;
return false;
}
if (value.ItemKey != tradeItemKey)
{
value.ItemKey = tradeItemKey;
value.StartTime = time;
holdStates[headViewId] = value;
return false;
}
if (time - value.StartTime < configTouchHoldSeconds.Value)
{
return false;
}
return true;
}
private void ClearHoldState(int headViewId)
{
if (holdStates.ContainsKey(headViewId))
{
holdStates.Remove(headViewId);
}
}
private int GetTradeItemKey(PhysGrabObject physGrabObject, ItemAttributes itemAttributes)
{
if ((Object)(object)physGrabObject != (Object)null)
{
PhotonView component = ((Component)physGrabObject).GetComponent<PhotonView>();
if ((Object)(object)component != (Object)null)
{
return component.ViewID;
}
}
if ((Object)(object)itemAttributes != (Object)null)
{
string instanceName = GetInstanceName(itemAttributes);
if (!string.IsNullOrEmpty(instanceName))
{
return instanceName.GetHashCode();
}
}
if ((Object)(object)physGrabObject != (Object)null)
{
return ((Object)physGrabObject).GetInstanceID();
}
return 0;
}
private ReviveValueResult GetReviveValue(ItemAttributes itemAttributes, PhysGrabObject physGrabObject, int playerMaxHealth)
{
ReviveValueResult result = default(ReviveValueResult);
result.Valid = false;
result.TargetHp = 0;
result.SourceLabel = string.Empty;
result.IsUsedHealthPack = false;
if (configAllowHealthPacks.Value)
{
ItemHealthPack val = ((Component)physGrabObject).GetComponent<ItemHealthPack>();
if ((Object)(object)val == (Object)null)
{
val = ((Component)physGrabObject).GetComponentInParent<ItemHealthPack>();
}
if ((Object)(object)val != (Object)null)
{
bool flag = IsHealthPackUsed(val);
if (flag && !configAllowUsedHealthPacks.Value)
{
return result;
}
result.Valid = true;
result.TargetHp = (flag ? 1 : Mathf.Clamp(val.healAmount, 1, playerMaxHealth));
result.SourceLabel = (flag ? (GetDisplayItemName(itemAttributes) + " Used") : GetDisplayItemName(itemAttributes));
result.IsUsedHealthPack = flag;
return result;
}
}
if (configAllowBatteryItems.Value)
{
ItemBattery val2 = ((Component)physGrabObject).GetComponent<ItemBattery>();
if ((Object)(object)val2 == (Object)null)
{
val2 = ((Component)physGrabObject).GetComponentInParent<ItemBattery>();
}
if ((Object)(object)val2 != (Object)null)
{
string instanceName = GetInstanceName(itemAttributes);
float batteryPercent = GetBatteryPercent(val2, instanceName);
int targetHp;
if (batteryPercent <= 0f)
{
if (!configAllowZeroBatteryRevive.Value)
{
return result;
}
targetHp = 1;
}
else
{
targetHp = Mathf.Max(1, Mathf.FloorToInt((float)playerMaxHealth * batteryPercent));
}
result.Valid = true;
result.TargetHp = targetHp;
result.SourceLabel = GetDisplayItemName(itemAttributes);
return result;
}
}
return result;
}
[IteratorStateMachine(typeof(<ExecuteTradeReviveRoutine>d__36))]
private IEnumerator ExecuteTradeReviveRoutine(TradeCandidate candidate, int headViewId, int itemKey)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ExecuteTradeReviveRoutine>d__36(0)
{
<>4__this = this,
candidate = candidate,
headViewId = headViewId,
itemKey = itemKey
};
}
private bool CanExecuteTrade(TradeCandidate candidate)
{
try
{
if (candidate == null)
{
return false;
}
if ((Object)(object)candidate.DeathHead == (Object)null || (Object)(object)candidate.PlayerAvatar == (Object)null || (Object)(object)candidate.PlayerAvatar.playerHealth == (Object)null)
{
return false;
}
if ((Object)(object)candidate.PhysGrabObject == (Object)null || (Object)(object)candidate.ItemAttributes == (Object)null || (Object)(object)candidate.ItemAttributes.item == (Object)null)
{
return false;
}
if (!GetPlayerIsDisabled(candidate.PlayerAvatar))
{
return false;
}
if (!IsDeathHeadTriggered(candidate.DeathHead))
{
return false;
}
return true;
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("CanExecuteTrade failed\n" + ex));
return false;
}
}
private void ExecuteTradeCore(TradeCandidate candidate)
{
try
{
if (configConsumeItem.Value)
{
ConsumePurchasedItem(candidate.ItemAttributes);
RemoveFromShoppingList(candidate.ItemAttributes);
DestroyTradeItem(candidate);
}
SetDeathHeadInExtractionPoint(candidate.DeathHead, value: true);
candidate.DeathHead.Revive();
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("ExecuteTradeCore failed\n" + ex));
}
}
private void FinalizeReviveHealth(TradeCandidate candidate, int headViewId)
{
try
{
if (candidate != null && !((Object)(object)candidate.PlayerAvatar == (Object)null) && !((Object)(object)candidate.PlayerAvatar.playerHealth == (Object)null) && !GetPlayerIsDisabled(candidate.PlayerAvatar))
{
int playerCurrentHealth = GetPlayerCurrentHealth(candidate.PlayerAvatar);
int playerMaxHealth = GetPlayerMaxHealth(candidate.PlayerAvatar);
int num = Mathf.Clamp(candidate.TargetHp, 1, playerMaxHealth);
int num2 = num - playerCurrentHealth;
if (num2 > 0)
{
candidate.PlayerAvatar.playerHealth.HealOther(num2, true);
}
headCooldownUntil[headViewId] = Time.time + configHeadCooldown.Value;
if (configDebugLog.Value)
{
TradeForRevivePlugin.Log.LogInfo((object)("Revived " + GetPlayerName(candidate.PlayerAvatar) + " with " + num + " HP by " + candidate.SourceLabel));
}
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("FinalizeReviveHealth failed\n" + ex));
}
}
private bool IsTradeItemLocked(int itemKey)
{
if (itemKey == 0)
{
return true;
}
return runningItemIds.Contains(itemKey) || consumedItemIds.Contains(itemKey);
}
private bool TryLockTradeItem(int itemKey)
{
if (IsTradeItemLocked(itemKey))
{
return false;
}
runningItemIds.Add(itemKey);
return true;
}
private void ReleaseTradeLocks(int headViewId, int itemKey, bool consumed)
{
runningHeadIds.Remove(headViewId);
runningItemIds.Remove(itemKey);
if (consumed && itemKey != 0)
{
consumedItemIds.Add(itemKey);
}
}
private void ClearHoldStatesByItem(int itemKey)
{
List<int> list = new List<int>();
foreach (KeyValuePair<int, HoldState> holdState in holdStates)
{
if (holdState.Value != null && holdState.Value.ItemKey == itemKey)
{
list.Add(holdState.Key);
}
}
for (int i = 0; i < list.Count; i++)
{
holdStates.Remove(list[i]);
}
}
private bool IsTradeItemCurrentlyHeld(PhysGrabObject physGrabObject)
{
try
{
if ((Object)(object)physGrabObject == (Object)null)
{
return false;
}
if (physGrabObject.playerGrabbing != null && physGrabObject.playerGrabbing.Count > 0)
{
return true;
}
if (physGrabObject.grabbed || physGrabObject.grabbedLocal)
{
return true;
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("IsTradeItemCurrentlyHeld failed\n" + ex));
}
return false;
}
private void ForceReleaseAllGrabbers(PhysGrabObject physGrabObject)
{
try
{
if ((Object)(object)physGrabObject == (Object)null)
{
return;
}
List<PhysGrabber> list = new List<PhysGrabber>(physGrabObject.playerGrabbing);
PhotonView component = ((Component)physGrabObject).GetComponent<PhotonView>();
if ((Object)(object)component == (Object)null)
{
return;
}
for (int i = 0; i < list.Count; i++)
{
PhysGrabber val = list[i];
if (!((Object)(object)val == (Object)null) && !((Object)(object)val.photonView == (Object)null))
{
val.photonView.RPC("ReleaseObjectRPC", (RpcTarget)0, new object[3] { false, 0.1f, component.ViewID });
}
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("ForceReleaseAllGrabbers failed\n" + ex));
}
}
private void ConsumePurchasedItem(ItemAttributes itemAttributes)
{
try
{
if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null || (Object)(object)StatsManager.instance == (Object)null)
{
return;
}
string instanceName = GetInstanceName(itemAttributes);
if (!string.IsNullOrEmpty(instanceName) && StatsManager.instance.item.ContainsKey(instanceName))
{
StatsManager.instance.ItemRemove(instanceName);
}
else
{
int num = 0;
if (StatsManager.instance.itemsPurchased.ContainsKey(((Object)itemAttributes.item).name))
{
num = StatsManager.instance.itemsPurchased[((Object)itemAttributes.item).name];
}
StatsManager.instance.SetItemPurchase(itemAttributes.item, Mathf.Max(0, num - 1));
}
if ((Object)(object)ItemManager.instance != (Object)null)
{
ItemManager.instance.purchasedItems.Remove(itemAttributes.item);
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("ConsumePurchasedItem failed\n" + ex));
}
}
private void RemoveFromShoppingList(ItemAttributes itemAttributes)
{
try
{
if ((Object)(object)itemAttributes != (Object)null && (Object)(object)ShopManager.instance != (Object)null)
{
ShopManager.instance.ShoppingListItemRemove(itemAttributes);
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("RemoveFromShoppingList failed\n" + ex));
}
}
private void DestroyTradeItem(TradeCandidate candidate)
{
try
{
if (candidate == null || (Object)(object)candidate.PhysGrabObject == (Object)null)
{
return;
}
PhysGrabObject physGrabObject = candidate.PhysGrabObject;
ForceReleaseAllGrabbers(physGrabObject);
if (candidate.IsUsedHealthPack)
{
physGrabObject.dead = true;
physGrabObject.DestroyPhysGrabObject();
return;
}
PhysGrabObjectImpactDetector val = GetImpactDetector(physGrabObject);
if ((Object)(object)val == (Object)null)
{
val = ((Component)physGrabObject).GetComponent<PhysGrabObjectImpactDetector>();
}
if ((Object)(object)val == (Object)null)
{
physGrabObject.dead = true;
physGrabObject.DestroyPhysGrabObject();
}
else
{
val.DestroyObject(configDestroyWithEffects.Value);
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("DestroyTradeItem failed\n" + ex));
}
}
private bool IsHealthPackUsed(ItemHealthPack itemHealthPack)
{
try
{
if ((Object)(object)itemHealthPack == (Object)null || FieldItemHealthPackUsed == null)
{
return false;
}
object value = FieldItemHealthPackUsed.GetValue(itemHealthPack);
return value is bool && (bool)value;
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("IsHealthPackUsed failed\n" + ex));
return false;
}
}
private float GetBatteryPercent(ItemBattery itemBattery, string instanceName)
{
try
{
if ((Object)(object)StatsManager.instance != (Object)null && !string.IsNullOrEmpty(instanceName) && StatsManager.instance.itemStatBattery.ContainsKey(instanceName))
{
int batteryLevel = StatsManager.instance.GetBatteryLevel(instanceName);
return Mathf.Clamp01((float)batteryLevel / 100f);
}
if ((Object)(object)itemBattery != (Object)null)
{
return Mathf.Clamp01(itemBattery.batteryLife / 100f);
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("GetBatteryPercent failed\n" + ex));
}
return 0f;
}
private bool IsPurchasedTradeItem(ItemAttributes itemAttributes)
{
try
{
if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null || (Object)(object)StatsManager.instance == (Object)null)
{
return false;
}
string instanceName = GetInstanceName(itemAttributes);
if (!string.IsNullOrEmpty(instanceName) && StatsManager.instance.item.ContainsKey(instanceName))
{
return true;
}
if (StatsManager.instance.itemsPurchased.ContainsKey(((Object)itemAttributes.item).name))
{
return StatsManager.instance.itemsPurchased[((Object)itemAttributes.item).name] > 0;
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("IsPurchasedTradeItem failed\n" + ex));
}
return false;
}
private bool IsDeathHeadTriggered(PlayerDeathHead deathHead)
{
try
{
if ((Object)(object)deathHead == (Object)null || FieldPlayerDeathHeadTriggered == null)
{
return false;
}
object value = FieldPlayerDeathHeadTriggered.GetValue(deathHead);
return value is bool && (bool)value;
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("IsDeathHeadTriggered failed\n" + ex));
return false;
}
}
private void SetDeathHeadInExtractionPoint(PlayerDeathHead deathHead, bool value)
{
try
{
if ((Object)(object)deathHead != (Object)null && FieldPlayerDeathHeadInExtractionPoint != null)
{
FieldPlayerDeathHeadInExtractionPoint.SetValue(deathHead, value);
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("SetDeathHeadInExtractionPoint failed\n" + ex));
}
}
private bool GetPlayerIsDisabled(PlayerAvatar playerAvatar)
{
try
{
if ((Object)(object)playerAvatar == (Object)null || FieldPlayerAvatarIsDisabled == null)
{
return false;
}
object value = FieldPlayerAvatarIsDisabled.GetValue(playerAvatar);
return value is bool && (bool)value;
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("GetPlayerIsDisabled failed\n" + ex));
return false;
}
}
private int GetPlayerCurrentHealth(PlayerAvatar playerAvatar)
{
try
{
if ((Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.playerHealth == (Object)null || FieldPlayerHealthHealth == null)
{
return 1;
}
object value = FieldPlayerHealthHealth.GetValue(playerAvatar.playerHealth);
if (value is int)
{
return (int)value;
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("GetPlayerCurrentHealth failed\n" + ex));
}
return 1;
}
private int GetPlayerMaxHealth(PlayerAvatar playerAvatar)
{
try
{
if ((Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.playerHealth == (Object)null || FieldPlayerHealthMaxHealth == null)
{
return 100;
}
object value = FieldPlayerHealthMaxHealth.GetValue(playerAvatar.playerHealth);
if (value is int)
{
return Mathf.Max(1, (int)value);
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("GetPlayerMaxHealth failed\n" + ex));
}
return 100;
}
private string GetPlayerName(PlayerAvatar playerAvatar)
{
try
{
if ((Object)(object)playerAvatar == (Object)null)
{
return "Unknown";
}
return ((Object)playerAvatar).name;
}
catch
{
return "Unknown";
}
}
private string GetDisplayItemName(ItemAttributes itemAttributes)
{
try
{
if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null)
{
return "Unknown Item";
}
return itemAttributes.item.itemName;
}
catch
{
return "Unknown Item";
}
}
private string GetInstanceName(ItemAttributes itemAttributes)
{
try
{
if ((Object)(object)itemAttributes == (Object)null || FieldItemAttributesInstanceName == null)
{
return string.Empty;
}
object value = FieldItemAttributesInstanceName.GetValue(itemAttributes);
if (value is string)
{
return (string)value;
}
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("GetInstanceName failed\n" + ex));
}
return string.Empty;
}
private PhysGrabObject GetDeathHeadPhysGrabObject(PlayerDeathHead deathHead)
{
try
{
if ((Object)(object)deathHead == (Object)null || FieldPlayerDeathHeadPhysGrabObject == null)
{
return null;
}
object? value = FieldPlayerDeathHeadPhysGrabObject.GetValue(deathHead);
return (PhysGrabObject)((value is PhysGrabObject) ? value : null);
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("GetDeathHeadPhysGrabObject failed\n" + ex));
return null;
}
}
private PhysGrabObjectImpactDetector GetImpactDetector(PhysGrabObject physGrabObject)
{
try
{
if ((Object)(object)physGrabObject == (Object)null || FieldPhysGrabObjectImpactDetector == null)
{
return null;
}
object? value = FieldPhysGrabObjectImpactDetector.GetValue(physGrabObject);
return (PhysGrabObjectImpactDetector)((value is PhysGrabObjectImpactDetector) ? value : null);
}
catch (Exception ex)
{
TradeForRevivePlugin.Log.LogError((object)("GetImpactDetector failed\n" + ex));
return null;
}
}
}
}