using System;
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 Photon.Pun;
using UnityEngine;
using Zorro.Core;
using Zorro.Core.Serizalization;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.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 SimpleTweaks
{
[HarmonyPatch(typeof(CharacterAnimations), "PlayEmote")]
internal static class Patch_BackflipAlwaysSucceed
{
private const string BackflipEmote = "A_Scout_Emote_BackFlip";
private static readonly FieldInfo CharacterField = AccessTools.Field(typeof(CharacterAnimations), "character");
private static bool Prefix(CharacterAnimations __instance, string emoteName)
{
if (!Plugin.cfgEnableBackflipAlwaysSucceed.Value)
{
return true;
}
if (emoteName != "A_Scout_Emote_BackFlip")
{
return true;
}
if (CharacterField == null)
{
return true;
}
object? value = CharacterField.GetValue(__instance);
Character val = (Character)((value is Character) ? value : null);
if (val == null)
{
return true;
}
if (val.refs == null || (Object)(object)val.refs.view == (Object)null)
{
return true;
}
val.refs.view.RPC("RPCA_PlayRemove", (RpcTarget)0, new object[2] { emoteName, false });
return false;
}
}
internal static class PendingClientSwap
{
public static bool Active;
public static byte HandSlotID;
public static byte BackpackSlotID;
public static BackpackReference BackpackRef;
public static float RequestTime;
private const float TimeoutSeconds = 3f;
public static void Set(byte handSlotID, byte backpackSlotID, BackpackReference bpRef)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
Active = true;
HandSlotID = handSlotID;
BackpackSlotID = backpackSlotID;
BackpackRef = bpRef;
RequestTime = Time.time;
}
public static void Clear()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
Active = false;
BackpackRef = default(BackpackReference);
}
public static bool IsValid()
{
if (!Active)
{
return false;
}
if (Time.time - RequestTime > 3f)
{
Clear();
return false;
}
if (!((BackpackReference)(ref BackpackRef)).exists)
{
Clear();
return false;
}
return true;
}
}
internal static class BackpackSwapLogic
{
private static readonly FieldInfo VisualItemsField = AccessTools.Field(typeof(BackpackVisuals), "visualItems");
public static void DoSwapLogic(Character character, byte handSlotID, BackpackReference bpRef, byte bpSlotID)
{
//IL_0063: 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)
if (!PhotonNetwork.IsMasterClient)
{
return;
}
ItemSlot itemSlot = character.player.GetItemSlot(handSlotID);
BackpackData data = ((BackpackReference)(ref bpRef)).GetData();
if (itemSlot != null && data != null)
{
ItemSlot val = data.itemSlots[bpSlotID];
if (val != null)
{
Item prefab = itemSlot.prefab;
ItemInstanceData data2 = itemSlot.data;
Item prefab2 = val.prefab;
ItemInstanceData data3 = val.data;
val.SetItem(prefab, data2);
itemSlot.SetItem(prefab2, data3);
ClearBackpackVisualSlot(bpRef, bpSlotID);
SyncInventory(character);
SyncBackpack(bpRef);
((BackpackReference)(ref bpRef)).GetVisuals().RefreshVisuals();
}
}
}
private static void ClearBackpackVisualSlot(BackpackReference bpRef, byte slotID)
{
BackpackVisuals visuals = ((BackpackReference)(ref bpRef)).GetVisuals();
if ((Object)(object)visuals == (Object)null)
{
return;
}
if (visuals.spawnedVisualItems.TryGetValue(slotID, out var value))
{
if ((Object)(object)value != (Object)null)
{
PhotonNetwork.Destroy(((Component)value).gameObject);
}
visuals.spawnedVisualItems.Remove(slotID);
}
if (VisualItemsField != null)
{
object value2 = VisualItemsField.GetValue(visuals);
value2?.GetType().GetMethod("Remove", new Type[1] { typeof(byte) })?.Invoke(value2, new object[1] { slotID });
}
}
private static void SyncInventory(Character character)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
byte[] array = IBinarySerializable.ToManagedArray<InventorySyncData>(new InventorySyncData(character.player.itemSlots, character.player.backpackSlot, character.player.tempFullSlot));
((MonoBehaviourPun)character.player).photonView.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { array, false });
}
private static void SyncBackpack(BackpackReference bpRef)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
if ((int)bpRef.type == 0)
{
bpRef.view.RPC("SetItemInstanceDataRPC", (RpcTarget)1, new object[1] { ((BackpackReference)(ref bpRef)).GetItemInstanceData() });
}
}
public static void RefreshHandVisual(Character character, byte handSlotID)
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
if (!character.IsLocal)
{
return;
}
CharacterItems val = character.refs?.items;
if (!((Object)(object)val == (Object)null))
{
if (handSlotID == 250)
{
((MonoBehaviourPun)val).photonView.RPC("DestroyHeldItemRpc", (RpcTarget)0, Array.Empty<object>());
val.EquipSlot(Optionable<byte>.Some(handSlotID));
}
else
{
val.EquipSlot(Optionable<byte>.Some(handSlotID));
}
}
}
}
[HarmonyPatch(typeof(Item), "Interact")]
internal static class BackpackSwapPatch
{
private static bool Prefix(Item __instance, Character interactor)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: 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)
PendingClientSwap.Clear();
if (!Plugin.cfgEnableBackpackSwap.Value)
{
return true;
}
if ((int)__instance.itemState != 2)
{
return true;
}
if (!__instance.backpackReference.IsSome)
{
return true;
}
if ((Object)(object)interactor.data.currentItem == (Object)null)
{
return true;
}
if (interactor.refs.items.lastEquippedSlotTime + 0.25f > Time.time)
{
return false;
}
if (!interactor.refs.items.currentSelectedSlot.IsSome)
{
return true;
}
byte value = interactor.refs.items.currentSelectedSlot.Value;
if ((Object)(object)interactor.data.currentItem != (Object)null && !interactor.data.currentItem.UIData.canPocket)
{
return true;
}
if (interactor.data.isClimbing && !__instance.UIData.canPocket)
{
return true;
}
var (b, bpRef) = __instance.backpackReference.Value;
if (PhotonNetwork.IsMasterClient)
{
BackpackSwapLogic.DoSwapLogic(interactor, value, bpRef, b);
BackpackSwapLogic.RefreshHandVisual(interactor, value);
((Component)__instance).gameObject.SetActive(false);
return false;
}
if (!interactor.player.HasEmptySlot(__instance.itemID))
{
return true;
}
if (interactor.data.isClimbingAnything)
{
return true;
}
PendingClientSwap.Set(value, b, bpRef);
return true;
}
}
[HarmonyPatch(typeof(CharacterItems), "OnPickupAccepted")]
internal static class BackpackSwapCompletePatch
{
private static void Prefix(CharacterItems __instance, byte slotID)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: 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_005a: 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)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
if (!PendingClientSwap.IsValid())
{
return;
}
byte handSlotID = PendingClientSwap.HandSlotID;
byte backpackSlotID = PendingClientSwap.BackpackSlotID;
BackpackReference backpackRef = PendingClientSwap.BackpackRef;
PendingClientSwap.Clear();
if (slotID == handSlotID)
{
return;
}
Character component = ((Component)__instance).GetComponent<Character>();
if ((Object)(object)component == (Object)null || !component.IsLocal)
{
return;
}
ItemSlot itemSlot = component.player.GetItemSlot(handSlotID);
if (itemSlot != null && !itemSlot.IsEmpty())
{
if ((int)backpackRef.type == 0)
{
backpackRef.view.RPC("RPCAddItemToBackpack", (RpcTarget)0, new object[3]
{
((MonoBehaviourPun)component.player).photonView,
handSlotID,
backpackSlotID
});
}
else
{
backpackRef.view.RPC("RPCAddItemToCharacterBackpack", (RpcTarget)0, new object[3]
{
((MonoBehaviourPun)component.player).photonView,
handSlotID,
backpackSlotID
});
}
component.player.EmptySlot(Optionable<byte>.Some(handSlotID));
}
}
}
[HarmonyPatch(typeof(Character), "UpdateVariablesFixed")]
internal static class Patch_DeathRegeneration
{
private static void Postfix(Character __instance)
{
if (!Plugin.cfgEnableDeathRegeneration.Value || !((MonoBehaviourPun)__instance).photonView.IsMine)
{
return;
}
CharacterData data = __instance.data;
if (!((Object)(object)data == (Object)null) && data.fullyPassedOut && !((Object)(object)data.carrier == (Object)null) && !__instance.refs.afflictions.willZombify && !__instance.input.interactIsPressed)
{
float num = Mathf.Max(0f, Plugin.cfgDeathRegenerationRate.Value);
if (!(num <= 0f))
{
data.deathTimer = Mathf.Max(0f, data.deathTimer - num * Time.fixedDeltaTime / 60f);
}
}
}
}
internal static class HungerOverflowState
{
private static readonly FieldInfo IncrementalField = AccessTools.Field(typeof(CharacterAfflictions), "currentIncrementalStatuses");
private static float _capturedHunger = 0f;
public static Character GetConsumer(ItemActionBase action)
{
if ((Object)(object)action == (Object)null)
{
return null;
}
Item component = ((Component)action).GetComponent<Item>();
if (!((Object)(object)component != (Object)null))
{
return null;
}
return component.holderCharacter;
}
public static void CaptureBefore(Character character)
{
_capturedHunger = 0f;
if (!((Object)(object)character == (Object)null) && character.IsLocal)
{
CharacterAfflictions val = character.refs?.afflictions;
if (!((Object)(object)val == (Object)null))
{
_capturedHunger = Mathf.Max(0f, val.GetCurrentStatus((STATUSTYPE)1));
}
}
}
public static void Apply(Character character, float restoreAmount)
{
if ((Object)(object)character == (Object)null || !character.IsLocal)
{
return;
}
float capturedHunger = _capturedHunger;
_capturedHunger = 0f;
if (restoreAmount <= 0f)
{
return;
}
float num = Mathf.Max(0f, restoreAmount - capturedHunger);
if (num <= 0f)
{
return;
}
CharacterAfflictions val = character.refs?.afflictions;
if ((Object)(object)val == (Object)null)
{
return;
}
float num2 = val.hungerPerSecond * Ascents.hungerRateMultiplier;
if (num2 <= 0f)
{
return;
}
float num3 = Mathf.Max(0f, Plugin.cfgHungerOverflowSecondsPerPoint.Value);
float num4 = num * 100f * num3;
float num5 = num4 * num2;
if (!(IncrementalField == null) && IncrementalField.GetValue(val) is float[] array && array.Length > 1)
{
array[1] = Mathf.Min(array[1], 0f);
float value = Plugin.cfgHungerOverflowMaxSeconds.Value;
if (value > 0f)
{
float num6 = 0.025f - value * num2;
array[1] = Mathf.Max(array[1] - num5, num6);
}
else
{
array[1] -= num5;
}
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)$"[饥饿溢出] 溢出 {num * 100f:0.#} 点(恢复 {restoreAmount * 100f:0.#},已有 {capturedHunger * 100f:0.#})→ 倒计时延长 {num4:0.#} 秒");
}
}
}
}
[HarmonyPatch(typeof(Action_RestoreHunger), "RunAction")]
internal static class Patch_ActionRestoreHunger_Overflow
{
private static void Prefix(Action_RestoreHunger __instance)
{
if (Plugin.cfgEnableHungerOverflow.Value)
{
HungerOverflowState.CaptureBefore(HungerOverflowState.GetConsumer((ItemActionBase)(object)__instance));
}
}
private static void Postfix(Action_RestoreHunger __instance)
{
if (Plugin.cfgEnableHungerOverflow.Value)
{
HungerOverflowState.Apply(HungerOverflowState.GetConsumer((ItemActionBase)(object)__instance), __instance.restorationAmount);
}
}
}
[HarmonyPatch(typeof(Action_ModifyStatus), "RunAction")]
internal static class Patch_ActionModifyStatus_Overflow
{
private static readonly FieldInfo IfSkeletonField = AccessTools.Field(typeof(Action_ModifyStatus), "ifSkeleton");
private static void Prefix(Action_ModifyStatus __instance, ref bool __state)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
__state = false;
if (!Plugin.cfgEnableHungerOverflow.Value)
{
__state = true;
}
else if ((int)__instance.statusType != 1 || __instance.changeAmount >= 0f)
{
__state = true;
}
else if (IfSkeletonField != null && (bool)IfSkeletonField.GetValue(__instance))
{
__state = true;
}
else
{
HungerOverflowState.CaptureBefore(HungerOverflowState.GetConsumer((ItemActionBase)(object)__instance));
}
}
private static void Postfix(Action_ModifyStatus __instance, bool __state)
{
if (!__state)
{
HungerOverflowState.Apply(HungerOverflowState.GetConsumer((ItemActionBase)(object)__instance), Mathf.Abs(__instance.changeAmount));
}
}
}
internal static class PeakStatsExCompat
{
private const string PeakStatsExTypeName = "PeakStatsEx.StaminaInfoPatch";
private static readonly FieldInfo IncrementalField = AccessTools.Field(typeof(CharacterAfflictions), "currentIncrementalStatuses");
public static void Apply(Harmony harmony)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Expected O, but got Unknown
Type type = AccessTools.TypeByName("PeakStatsEx.StaminaInfoPatch");
if (type == null)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)"PeakStatsEx 未加载,跳过饥饿倒计时显示兼容补丁。");
}
return;
}
MethodInfo methodInfo = AccessTools.Method(type, "GetHungerIncrementalStatus", (Type[])null, (Type[])null);
if (methodInfo == null)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogWarning((object)"PeakStatsEx 已加载,但未找到 GetHungerIncrementalStatus,跳过兼容补丁。");
}
return;
}
MethodInfo methodInfo2 = AccessTools.Method(typeof(PeakStatsExCompat), "PostfixNegativeIncremental", (Type[])null, (Type[])null);
harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
ManualLogSource log3 = Plugin.Log;
if (log3 != null)
{
log3.LogInfo((object)"已应用 PeakStatsEx 饥饿倒计时显示兼容补丁。");
}
}
private static void PostfixNegativeIncremental(CharacterAfflictions afflictions, ref float __result)
{
if (!((Object)(object)afflictions == (Object)null) && !(IncrementalField == null) && IncrementalField.GetValue(afflictions) is float[] array && array.Length > 1)
{
float num = array[1];
if (num < 0f)
{
__result = num;
}
}
}
}
[BepInPlugin("com.simpletweaks.peak", "SimpleTweaks", "1.1.0")]
[BepInProcess("PEAK.exe")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
internal static ConfigEntry<bool> cfgEnableHungerOverflow;
internal static ConfigEntry<float> cfgHungerOverflowSecondsPerPoint;
internal static ConfigEntry<float> cfgHungerOverflowMaxSeconds;
internal static ConfigEntry<bool> cfgEnableBackpackSwap;
internal static ConfigEntry<bool> cfgEnableBackflipAlwaysSucceed;
internal static ConfigEntry<bool> cfgEnableDeathRegeneration;
internal static ConfigEntry<float> cfgDeathRegenerationRate;
internal static ManualLogSource Log;
private void Awake()
{
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
cfgEnableHungerOverflow = ((BaseUnityPlugin)this).Config.Bind<bool>("Hunger", "EnableHungerOverflow", true, "饥饿溢出延长计时开关。吃食物时,超过当前饥饿值的恢复量会按比例延长下一次变饿的倒计时。");
cfgHungerOverflowSecondsPerPoint = ((BaseUnityPlugin)this).Config.Bind<float>("Hunger", "HungerOverflowSecondsPerPoint", 10f, "每溢出 1 点饥饿值(1%)延长饥饿倒计时的秒数。默认 10 秒。");
cfgHungerOverflowMaxSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Hunger", "HungerOverflowMaxSeconds", 120f, "饥饿倒计时延长后的上限(秒)。无论溢出多少,倒计时都不会超过此值,默认 120 秒(2 分钟)。0 表示不限制。");
cfgEnableBackpackSwap = ((BaseUnityPlugin)this).Config.Bind<bool>("Backpack", "EnableBackpackSwap", true, "背包物品替换开关。手上已有物品时点击背包中物品,会将手中物品与背包物品互换位置。");
cfgEnableBackflipAlwaysSucceed = ((BaseUnityPlugin)this).Config.Bind<bool>("Emote", "EnableBackflipAlwaysSucceed", true, "后空翻 100% 成功开关。原版后空翻有 50% 概率失败倒地,开启后必定成功落地。");
cfgEnableDeathRegeneration = ((BaseUnityPlugin)this).Config.Bind<bool>("Death", "EnableDeathRegeneration", true, "死亡计时回复开关。本地玩家被其他玩家背着时,死亡计时(昏迷倒计时)会缓慢回复。");
cfgDeathRegenerationRate = ((BaseUnityPlugin)this).Config.Bind<float>("Death", "DeathRegenerationRate", 1f, "死亡计时回复速率(相对原版消耗速率)。1.0 = 与消耗同速回复(默认);0.5 = 回复速度是消耗速度的一半。0 或负数表示不回复。");
Harmony val = new Harmony("com.simpletweaks.peak");
val.PatchAll();
PeakStatsExCompat.Apply(val);
Log.LogInfo((object)"SimpleTweaks v1.1.0 已加载");
}
}
internal static class PluginInfo
{
public const string PLUGIN_GUID = "com.simpletweaks.peak";
public const string PLUGIN_NAME = "SimpleTweaks";
public const string PLUGIN_VERSION = "1.1.0";
}
}