using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("test1")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("test1")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("d85cf9ee-a79b-4912-b9fc-6e9088851772")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace Conversion; [BepInPlugin("yazirushi.Conversion", "Conversion", "1.0.1")] public class Conversion : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("yazirushi.Conversion"); internal static ManualLogSource mls; public static ConfigEntry EnableLogging; public static ConfigEntry Safety; public static ConfigEntry Percent_mode_H; public static ConfigEntry Percent_mode_S; public static ConfigEntry Health; public static ConfigEntry Stamina; public static ConfigEntry ConvertKey; private void Awake() { Percent_mode_S = ((BaseUnityPlugin)this).Config.Bind("Host Setting", "Percent Mode(Stamina)", false, "Whether to convert based on maximum Stamina"); Percent_mode_H = ((BaseUnityPlugin)this).Config.Bind("Host Setting", "Percent Mode (Health)", false, "Whether to convert based on maximum health"); Stamina = ((BaseUnityPlugin)this).Config.Bind("Host Setting", "Gain Stamina", 10, "Amount of stamina recovered during conversion (must be 1 or higher)"); Health = ((BaseUnityPlugin)this).Config.Bind("Host Setting", "HP Cost", 1, "Amount of health consumed during conversion (must be 1 or higher)"); Safety = ((BaseUnityPlugin)this).Config.Bind("Host Setting", "Convert Safety", true, "Whether to abort the conversion if health drops to 0 during the process"); ConvertKey = ((BaseUnityPlugin)this).Config.Bind("Client Setting", "ConvertKey", (KeyCode)102, "Key to press to perform the conversion"); EnableLogging = ((BaseUnityPlugin)this).Config.Bind("DebugLog", "EnableLogging", false, "Display debug logs"); mls = ((BaseUnityPlugin)this).Logger; mls.LogInfo((object)"Starting Conversion..."); if (0 >= Stamina.Value || 0 >= Health.Value) { mls.LogError((object)"Warning! The configuration is set to an invalid value.\nWe recommend changing it to a valid value."); } harmony.PatchAll(); } } [HarmonyPatch(typeof(PlayerAvatar), "Awake")] public class Reset_Patch { private static void Postfix(PlayerAvatar __instance) { if (!((Object)(object)__instance == (Object)null)) { if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } Sync_Patch component = ((Component)__instance).GetComponent(); if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"Awake : init"); } component.enable = false; component.safety = false; component.percent_mode_H = false; component.percent_mode_S = false; component.hurtHealth = 0; component.healEnergy = 0f; component.requestCooltime = 0f; } } } [HarmonyPatch(typeof(PlayerController), "Update")] public class Conversion_Patch { private static readonly FieldInfo fieldHealth = AccessTools.Field(typeof(PlayerHealth), "health"); private static readonly FieldInfo fieldMaxHealth = AccessTools.Field(typeof(PlayerHealth), "maxHealth"); private static void Postfix(PlayerController __instance) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.playerAvatarScript == (Object)null || (!__instance.playerAvatarScript.photonView.IsMine && SemiFunc.IsMultiplayer()) || !Input.GetKey(Conversion.ConvertKey.Value)) { return; } if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"Convert : input"); } Sync_Patch component = ((Component)__instance.playerAvatarScript).GetComponent(); if ((Object)(object)component == (Object)null) { return; } if (component.enable) { int num = (int)fieldHealth.GetValue(__instance.playerAvatarScript.playerHealth); int num2 = (int)fieldMaxHealth.GetValue(__instance.playerAvatarScript.playerHealth); int num3 = ((!component.percent_mode_H) ? component.hurtHealth : Mathf.Max(1, (int)((float)num2 * ((float)component.hurtHealth / 100f)))); float num4 = ((!component.percent_mode_S) ? component.healEnergy : Mathf.Max(1f, __instance.EnergyStart * (component.healEnergy / 100f))); if (num3 > 0 && num4 > 0f && (num - num3 > 0 || !component.safety) && 1f > __instance.EnergyCurrent) { if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"Convert : execute"); } __instance.playerAvatarScript.playerHealth.Hurt(num3, false, -1, false); __instance.EnergyCurrent = Mathf.Min(__instance.EnergyCurrent + num4, __instance.EnergyStart); } } else if (0f >= component.requestCooltime) { if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"Postfix : request permission"); } component.Request(); } else if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"Postfix : currently on cooldown"); } } } public class Sync_Patch : MonoBehaviourPun { public bool enable = false; public bool safety = false; public bool percent_mode_H = false; public bool percent_mode_S = false; public int hurtHealth = 0; public float healEnergy = 0f; public float requestCooltime = 0f; public int requestCount = 0; public void Update() { if (requestCooltime > 0f) { if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)$"Update : requestCooltime = {requestCooltime}s"); } requestCooltime -= Time.deltaTime; } } public void Request() { if (SemiFunc.IsMasterClientOrSingleplayer()) { if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"Request : you is host"); } enable = true; safety = Conversion.Safety.Value; percent_mode_H = Conversion.Percent_mode_H.Value; percent_mode_S = Conversion.Percent_mode_S.Value; hurtHealth = Conversion.Health.Value; healEnergy = Conversion.Stamina.Value; } else { if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"Request : send"); } requestCooltime = 5f; requestCount++; if (requestCount > 3) { Conversion.mls.LogError((object)"Postfix : Warning! The request has failed multiple times. Please check if the host has installed the mod. "); } ((MonoBehaviourPun)this).photonView.RPC("RequestRPC", (RpcTarget)2, Array.Empty()); } } [PunRPC] public void RequestRPC(PhotonMessageInfo _info = default(PhotonMessageInfo)) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"RequestRPC : received"); } Player sender = _info.Sender; ((MonoBehaviourPun)this).photonView.RPC("PermissionRPC", sender, new object[5] { Conversion.Safety.Value, Conversion.Percent_mode_H.Value, Conversion.Percent_mode_S.Value, Conversion.Health.Value, (float)Conversion.Stamina.Value }); } [PunRPC] public void PermissionRPC(bool _safety, bool _percent_mode_H, bool _percent_mode_S, int _hurtHealth, float _healEnergy) { if (Conversion.EnableLogging.Value) { Conversion.mls.LogInfo((object)"PermissionRPC : received"); } enable = true; safety = _safety; percent_mode_H = _percent_mode_H; percent_mode_S = _percent_mode_S; hurtHealth = _hurtHealth; healEnergy = _healEnergy; requestCount = 0; } }