Decompiled source of GrabRechargeMP v1.1.1

PlayerGrabRecharge.dll

Decompiled 2 weeks ago
using System;
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 ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
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("PlayerGrabRecharge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("3.2.0.0")]
[assembly: AssemblyInformationalVersion("3.2.0")]
[assembly: AssemblyProduct("PlayerGrabRecharge")]
[assembly: AssemblyTitle("PlayerGrabRecharge")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.2.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace PlayerGrabRecharge
{
	[BepInPlugin("aolion.grabrechargemp", "Player Grab Recharge MP", "3.2.1")]
	public class PlayerGrabRechargePlugin : BaseUnityPlugin, IOnEventCallback
	{
		public const string PLUGIN_GUID = "aolion.grabrechargemp";

		public const string PLUGIN_NAME = "Player Grab Recharge MP";

		public const string PLUGIN_VERSION = "3.2.1";

		private const byte EVENT_CHARGE = 143;

		private const float MAX_POWER = 100f;

		private const float COOLDOWN_TIME = 3f;

		private const float REGEN_RATE = 5f;

		internal static ManualLogSource Logger = null;

		private Harmony _harmony;

		internal static bool IsRecharging = false;

		internal static float ModPower = 100f;

		internal static float Cooldown = 0f;

		private static float _chargeAccum = 0f;

		private static ItemBattery? _lastBattery = null;

		private static FieldInfo? _chargeTimerField;

		private static FieldInfo? _isChargingField;

		private static FieldInfo? _goalUITextField;

		private static FieldInfo? _energyUITextField;

		public static ConfigEntry<KeyCode> RechargeKey { get; private set; } = null;


		public static ConfigEntry<bool> ToggleMode { get; private set; } = null;


		public static ConfigEntry<int> RechargeRate { get; private set; } = null;


		public static ConfigEntry<bool> ShowUI { get; private set; } = null;


		public static ConfigEntry<bool> DebugLog { get; private set; } = null;


		public static PlayerGrabRechargePlugin? Instance { get; private set; }

		private void Awake()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			RechargeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Settings", "RechargeKey", (KeyCode)122, "Key to hold (or tap in toggle mode) to recharge the grabbed item.");
			ToggleMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ToggleMode", false, "False = hold to charge. True = tap to toggle.");
			RechargeRate = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "RechargeRate", 10, new ConfigDescription("Battery % restored per second.", (AcceptableValueBase)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			ShowUI = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowChargeBar", true, "Show the mod power bar on the HUD.");
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLogging", false, "Verbose logging — set true to diagnose issues.");
			_harmony = new Harmony("aolion.grabrechargemp");
			_harmony.PatchAll(typeof(PlayerGrabRechargePlugin));
			Logger.LogInfo((object)string.Format("[PGR] v{0} loaded. Key={1}  ToggleMode={2}  RatePerSec={3}", "3.2.1", RechargeKey.Value, ToggleMode.Value, RechargeRate.Value));
		}

		private void OnDestroy()
		{
			_harmony.UnpatchSelf();
			PhotonNetwork.RemoveCallbackTarget((object)this);
		}

		private static ItemBattery? GetGrabbedBattery(PlayerController pc)
		{
			GameObject physGrabObject = pc.physGrabObject;
			if ((Object)(object)physGrabObject == (Object)null)
			{
				return null;
			}
			Transform val = physGrabObject.transform;
			while ((Object)(object)val.parent != (Object)null && (Object)(object)((Component)val.parent).GetComponent<PhysGrabObject>() != (Object)null)
			{
				val = val.parent;
			}
			ItemBattery componentInChildren = ((Component)val).GetComponentInChildren<ItemBattery>(true);
			if (DebugLog.Value && (Object)(object)componentInChildren == (Object)null && (Object)(object)physGrabObject != (Object)null)
			{
				Logger.LogInfo((object)("[PGR] No ItemBattery found under " + ((Object)val).name + " (grabbed=" + ((Object)physGrabObject).name + ")"));
			}
			return componentInChildren;
		}

		private static void EnsureVisualFields()
		{
			if (_chargeTimerField == null)
			{
				_chargeTimerField = typeof(ItemBattery).GetField("chargeTimer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_isChargingField == null)
			{
				_isChargingField = typeof(ItemBattery).GetField("isCharging", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
		}

		private static void SetChargingVisual(ItemBattery battery)
		{
			EnsureVisualFields();
			_chargeTimerField?.SetValue(battery, 0.3f);
			_isChargingField?.SetValue(battery, true);
		}

		private static void StopChargingVisual(ItemBattery? battery)
		{
			if (!((Object)(object)battery == (Object)null))
			{
				EnsureVisualFields();
				_isChargingField?.SetValue(battery, false);
				_chargeTimerField?.SetValue(battery, 0f);
				_chargeAccum = 0f;
				_lastBattery = null;
			}
		}

		private static void ApplyCharge(ItemBattery battery, float amount)
		{
			if ((Object)(object)_lastBattery != (Object)(object)battery)
			{
				_chargeAccum = 0f;
				_lastBattery = battery;
			}
			float num = ((battery.batteryBars > 0) ? (100f / (float)battery.batteryBars) : 100f);
			_chargeAccum += amount;
			if (_chargeAccum >= num)
			{
				_chargeAccum -= num;
				float batteryLife = battery.batteryLife;
				float num2 = Mathf.Clamp(batteryLife + num, num, 100f);
				if (battery.batteryLife <= 0f)
				{
					battery.batteryLife = 0.001f;
				}
				battery.SetBatteryLife(Mathf.RoundToInt(num2));
				if (DebugLog.Value)
				{
					Logger.LogInfo((object)$"[PGR] Bar +1: {batteryLife:F0}→{num2:F0}  bars={battery.batteryBars}  barSize={num:F0}");
				}
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			if (photonEvent.Code != 143 || !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			try
			{
				object[] obj = (object[])photonEvent.CustomData;
				int num = (int)obj[0];
				float num2 = (float)obj[1];
				PhotonView val = PhotonView.Find(num);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				ItemBattery val2 = ((Component)val).GetComponentInChildren<ItemBattery>(true) ?? ((Component)val).GetComponentInParent<ItemBattery>();
				if (!((Object)(object)val2 == (Object)null))
				{
					ApplyCharge(val2, num2);
					if (DebugLog.Value)
					{
						Logger.LogInfo((object)$"[PGR:HOST] Remote charge +{num2:F3} on viewID={num} ({((Object)val).name})");
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[PGR] OnEvent error: " + ex.Message));
			}
		}

		private static void DrawPowerBar(TextMeshProUGUI? tmp)
		{
			if (!ShowUI.Value || (Object)(object)tmp == (Object)null)
			{
				return;
			}
			float num = Mathf.Clamp01(ModPower / 100f);
			string text = $"{Mathf.RoundToInt(num * 100f)}%";
			if (Cooldown > 0f)
			{
				text += $" (CD {Cooldown:F1}s)";
			}
			string text2 = ((num < 0.25f) ? "#ff3333" : ((num < 0.6f) ? "#ffaa00" : "#00ff66"));
			string text3 = "<line-height=70%>\n<color=" + text2 + "><size=22>Charge: " + text + "</size></color>";
			if (!((TMP_Text)tmp).text.Contains("Charge:"))
			{
				((TMP_Text)tmp).text = ((TMP_Text)tmp).text + text3;
				return;
			}
			int num2 = ((TMP_Text)tmp).text.IndexOf("Charge:", StringComparison.Ordinal);
			int num3 = ((TMP_Text)tmp).text.IndexOf('\n', num2 + 1);
			if (num3 < 0)
			{
				num3 = ((TMP_Text)tmp).text.Length;
			}
			string text4 = ((TMP_Text)tmp).text.Substring(0, num2);
			string text5 = ((TMP_Text)tmp).text;
			int num4 = num3;
			((TMP_Text)tmp).text = text4 + text3 + text5.Substring(num4, text5.Length - num4);
		}

		[HarmonyPatch(typeof(PlayerController), "Update")]
		[HarmonyPostfix]
		private static void PlayerControllerUpdate_Postfix(PlayerController __instance)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Expected O, but got Unknown
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)PlayerController.instance)
			{
				return;
			}
			if (Cooldown > 0f)
			{
				Cooldown -= Time.deltaTime;
			}
			else if (ModPower < 100f)
			{
				ModPower = Mathf.Min(ModPower + 5f * Time.deltaTime, 100f);
			}
			if (!ToggleMode.Value)
			{
				IsRecharging = Input.GetKey(RechargeKey.Value);
			}
			else if (Input.GetKeyDown(RechargeKey.Value))
			{
				IsRecharging = !IsRecharging;
				if (IsRecharging && ModPower <= 0.01f)
				{
					IsRecharging = false;
				}
			}
			if (IsRecharging && ModPower <= 0.01f)
			{
				Cooldown = 3f;
				ModPower = 0f;
				IsRecharging = false;
			}
			bool flag = IsRecharging && Cooldown <= 0f && ModPower > 0.01f;
			ItemBattery grabbedBattery = GetGrabbedBattery(__instance);
			if (DebugLog.Value && Input.GetKey(RechargeKey.Value))
			{
				GameObject physGrabObject = __instance.physGrabObject;
				Logger.LogInfo((object)string.Format("[PGR] Z held: grabbed={0}  battery={1}  life={2:F1}  canCharge={3}  power={4:F2}  cd={5:F2}", ((physGrabObject != null) ? ((Object)physGrabObject).name : null) ?? "null", ((grabbedBattery != null) ? ((Object)grabbedBattery).name : null) ?? "null", grabbedBattery?.batteryLife, flag, ModPower, Cooldown));
			}
			if (!flag)
			{
				StopChargingVisual(grabbedBattery);
				return;
			}
			if ((Object)(object)grabbedBattery == (Object)null || grabbedBattery.isUnchargable || grabbedBattery.batteryLife >= 100f)
			{
				StopChargingVisual(grabbedBattery);
				return;
			}
			SetChargingVisual(grabbedBattery);
			float num = (float)RechargeRate.Value * Time.deltaTime;
			ModPower -= num;
			if (PhotonNetwork.IsMasterClient || !PhotonNetwork.IsConnectedAndReady)
			{
				ApplyCharge(grabbedBattery, num);
				return;
			}
			PhotonView val = ((Component)grabbedBattery).GetComponent<PhotonView>() ?? ((Component)grabbedBattery).GetComponentInParent<PhotonView>() ?? ((Component)grabbedBattery).GetComponentInChildren<PhotonView>();
			if ((Object)(object)val == (Object)null)
			{
				ApplyCharge(grabbedBattery, num);
				if (DebugLog.Value)
				{
					Logger.LogInfo((object)"[PGR] No PhotonView on battery — charged locally");
				}
				return;
			}
			RaiseEventOptions val2 = new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)2
			};
			PhotonNetwork.RaiseEvent((byte)143, (object)new object[2] { val.ViewID, num }, val2, SendOptions.SendUnreliable);
			if (DebugLog.Value)
			{
				Logger.LogInfo((object)$"[PGR] Sent charge event viewID={val.ViewID}  amount={num:F4}");
			}
		}

		[HarmonyPatch(typeof(LevelGenerator), "Generate")]
		[HarmonyPostfix]
		private static void LevelGenerator_Generate_Postfix()
		{
			IsRecharging = false;
			ModPower = 100f;
			Cooldown = 0f;
			_chargeAccum = 0f;
			_lastBattery = null;
			PhotonNetwork.AddCallbackTarget((object)Instance);
			if (DebugLog.Value)
			{
				Logger.LogInfo((object)"[PGR] Level generated — state reset, Photon callbacks registered");
			}
		}

		[HarmonyPatch(typeof(PlayerController), "Start")]
		[HarmonyPostfix]
		private static void PlayerControllerStart_Postfix(PlayerController __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)PlayerController.instance))
			{
				PhotonNetwork.AddCallbackTarget((object)Instance);
				if (DebugLog.Value)
				{
					Logger.LogInfo((object)"[PGR] PlayerController.Start — Photon callbacks registered");
				}
			}
		}

		[HarmonyPatch(typeof(GoalUI), "Update")]
		[HarmonyPostfix]
		private static void GoalUI_Update_Postfix(GoalUI __instance)
		{
			if (SemiFunc.RunIsLevel())
			{
				if (_goalUITextField == null)
				{
					_goalUITextField = typeof(GoalUI).GetField("Text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				object? obj = _goalUITextField?.GetValue(__instance);
				DrawPowerBar((TextMeshProUGUI?)((obj is TextMeshProUGUI) ? obj : null));
			}
		}

		[HarmonyPatch(typeof(EnergyUI), "Update")]
		[HarmonyPostfix]
		private static void EnergyUI_Update_Postfix(EnergyUI __instance)
		{
			if (SemiFunc.RunIsShop())
			{
				if (_energyUITextField == null)
				{
					_energyUITextField = typeof(EnergyUI).GetField("Text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				object? obj = _energyUITextField?.GetValue(__instance);
				DrawPowerBar((TextMeshProUGUI?)((obj is TextMeshProUGUI) ? obj : null));
			}
		}

		[HarmonyPatch(typeof(ItemEquippable), "StateIdle")]
		[HarmonyPrefix]
		private static bool ItemEquippable_StateIdle_Prefix(ItemEquippable __instance)
		{
			if (!IsRecharging)
			{
				return true;
			}
			PlayerController instance = PlayerController.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			GameObject physGrabObject = instance.physGrabObject;
			if ((Object)(object)physGrabObject == (Object)null)
			{
				return true;
			}
			Transform val = physGrabObject.transform;
			while ((Object)(object)val.parent != (Object)null && (Object)(object)((Component)val.parent).GetComponent<PhysGrabObject>() != (Object)null)
			{
				val = val.parent;
			}
			if ((Object)(object)((Component)val).GetComponentInChildren<ItemEquippable>(true) == (Object)(object)__instance)
			{
				if (DebugLog.Value)
				{
					Logger.LogInfo((object)"[PGR] ItemEquippable.StateIdle suppressed (recharging)");
				}
				return false;
			}
			return true;
		}
	}
}