Decompiled source of SimpleTweaks v1.1.0

plugins/SimpleTweaks.dll

Decompiled 2 weeks ago
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";
	}
}