Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LethalParrying v1.0.31
Ryokune.LethalParrying.dll
Decompiled 2 years agousing 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 GameNetcodeStuff; using HarmonyLib; using LethalParrying.Patches; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [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 = "")] [assembly: AssemblyCompany("Ryokune")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Lethal Company Parrying")] [assembly: AssemblyFileVersion("1.0.31.0")] [assembly: AssemblyInformationalVersion("1.0.31")] [assembly: AssemblyProduct("LethalParrying")] [assembly: AssemblyTitle("Ryokune.LethalParrying")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.31.0")] [module: UnverifiableCode] namespace LethalParrying { public class ParryNetworkHandler : NetworkBehaviour { } [BepInPlugin("Ryokune.LethalParrying", "LethalParrying", "1.0.31")] [BepInProcess("Lethal Company.exe")] public class LethalParryBase : BaseUnityPlugin { public static LethalParryBase instance; public static ManualLogSource logger; public static bool serverModCheck = true; public static bool stun = false; internal static ConfigEntry<int> DropProbability; internal static ConfigEntry<bool> Notify; internal static ConfigEntry<bool> DisplayCooldown; private readonly Harmony harmony = new Harmony("Ryokune.LethalParrying"); private void NetCodeWeaver() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } } private void Awake() { DropProbability = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Drop chance", 15, "Probability for how often you might drop your weapon when failing to parry or holding F."); Notify = ((BaseUnityPlugin)this).Config.Bind<bool>("Screen Information", "Display Parry Notifications", true, "Enables/Disables screen notifications for parry information. (Will be removed when sounds and effects are added)"); DisplayCooldown = ((BaseUnityPlugin)this).Config.Bind<bool>("Screen Information", "Display Parry Cooldown (Notification)", true, "Will show you a notification if your parry is on cooldown. (Display Parry Notifications does not affect this.)"); if (DropProbability.Value < (int)((ConfigEntryBase)DropProbability).DefaultValue) { DropProbability.Value = (int)((ConfigEntryBase)DropProbability).DefaultValue; } NetCodeWeaver(); if ((Object)(object)instance == (Object)null) { instance = this; logger = ((BaseUnityPlugin)this).Logger; } logger.LogInfo((object)"---[Only skill issue can kill you now..]---"); logger.LogInfo((object)"---[Plugin Ryokune.LethalParrying is loaded!]---"); logger.LogInfo((object)"---[Only skill issue can kill you now..]---"); harmony.PatchAll(typeof(LethalParryBase)); harmony.PatchAll(typeof(PlayerControllerBPatch)); harmony.PatchAll(typeof(ShovelPatch)); } } public static class PluginInfo { public const string PLUGIN_GUID = "Ryokune.LethalParrying"; public const string PLUGIN_NAME = "LethalParrying"; public const string PLUGIN_VERSION = "1.0.31"; } } namespace LethalParrying.Patches { [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatch { internal static bool isPerfectParryFrame = false; internal static bool isSlow = false; internal static float perfectParryWindow = 0.25f; internal static float lastParryTime; internal static float perfectParryCooldown = 2f; internal static GrabbableObject currentItem; internal static Shovel shovel = null; internal static bool ParriedDeath = false; internal static Coroutine currentCoroutine; [HarmonyPatch("KillPlayer")] [HarmonyPrefix] private static bool KillPlayerPatch(PlayerControllerB __instance, CauseOfDeath causeOfDeath) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Invalid comparison between Unknown and I4 //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Invalid comparison between Unknown and I4 //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Invalid comparison between Unknown and I4 if (!LethalParryBase.serverModCheck) { return true; } if (!((NetworkBehaviour)__instance).IsOwner) { return false; } if (__instance.isPlayerDead) { return false; } if (!__instance.AllowPlayerDeath()) { return false; } if (ParriedDeath) { LethalParryBase.logger.LogWarning((object)"Server called KillPlayer method again. Might have to patch this method properly."); ParriedDeath = false; return false; } if ((int)causeOfDeath == 0 || (int)causeOfDeath == 2 || (int)causeOfDeath == 10 || (int)causeOfDeath == 5 || (int)causeOfDeath == 9 || (Object)(object)shovel == (Object)null) { return true; } if (isPerfectParryFrame) { if (LethalParryBase.Notify.Value) { HUDManager.Instance.DisplayTip("Parried Death..", "Nothing can stop you.", true, false, "LC_Tip1"); } HUDManager.Instance.ShakeCamera((ScreenShakeType)3); __instance.DropAllHeldItems(true, false); lastParryTime = 0f; ParriedDeath = true; return false; } return true; } [HarmonyPatch("DamagePlayer")] [HarmonyPrefix] private static bool DamagePlayerPatch(PlayerControllerB __instance, ref int damageNumber, CauseOfDeath causeOfDeath) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Invalid comparison between Unknown and I4 //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) if (!LethalParryBase.serverModCheck) { return true; } if (!((NetworkBehaviour)__instance).IsOwner) { return false; } if (__instance.isPlayerDead) { return false; } if (!__instance.AllowPlayerDeath()) { return false; } if ((int)causeOfDeath == 10 || (int)causeOfDeath == 5 || (int)causeOfDeath == 9 || (Object)(object)shovel == (Object)null) { return true; } if (isPerfectParryFrame) { isSlow = false; if (currentCoroutine == null) { currentCoroutine = ((MonoBehaviour)__instance).StartCoroutine(DoHit(__instance, shovel)); } MakeCriticallyInjured(__instance, enable: false); HUDManager.Instance.ShakeCamera((ScreenShakeType)1); if (LethalParryBase.Notify.Value) { HUDManager.Instance.DisplayTip("Parried!", "Nice job!", false, false, "LC_Tip1"); } __instance.ResetFallGravity(); lastParryTime = 0f; } else if (((ButtonControl)Keyboard.current.fKey).isPressed) { int num = Random.Range(0, damageNumber - Random.Range(0, damageNumber)); damageNumber -= num; if (LethalParryBase.Notify.Value) { HUDManager.Instance.DisplayTip("Blocked Damage", $"Damage negated: {num}", false, false, "LC_Tip1"); } HUDManager.Instance.ShakeCamera((ScreenShakeType)1); int num2 = Random.Range(1, 100); if (num2 <= LethalParryBase.DropProbability.Value && (Object)(object)currentItem != (Object)null) { __instance.DiscardHeldObject(false, (NetworkObject)null, default(Vector3), true); } } return !isPerfectParryFrame; } [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePatch(PlayerControllerB __instance) { if (!LethalParryBase.serverModCheck || ((!((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject)) && !__instance.isTestingPlayer)) { return; } currentItem = __instance.ItemSlots[__instance.currentItemSlot]; if (!((ButtonControl)Keyboard.current.fKey).isPressed || (Object)(object)currentItem == (Object)null || (Object)(object)shovel == (Object)null) { if (__instance.bleedingHeavily) { isSlow = false; return; } if (isSlow && __instance.criticallyInjured) { isSlow = false; MakeCriticallyInjured(__instance, enable: false); } } if ((Object)(object)currentItem == (Object)null) { return; } shovel = (Shovel)((currentItem is Shovel) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)shovel == (Object)null || !((ButtonControl)Keyboard.current.fKey).wasPressedThisFrame) { return; } if (shovel.reelingUp || __instance.bleedingHeavily) { if (LethalParryBase.Notify.Value) { HUDManager.Instance.DisplayTip("Can't parry.", "You are attacking or injured.", false, false, "LC_Tip1"); } } else if (!IsParryOnCooldown()) { ((MonoBehaviour)__instance).StartCoroutine(PerfectParryWindow(__instance, shovel)); MakeCriticallyInjured(__instance, enable: true); LethalParryBase.stun = true; isSlow = true; } else if (!isPerfectParryFrame && LethalParryBase.DisplayCooldown.Value) { HUDManager.Instance.DisplayTip("Can't parry. On cooldown", $"Can parry again after {Math.Round(perfectParryCooldown - Time.time + lastParryTime, 1)} seconds.", false, false, "LC_Tip1"); } } private static IEnumerator DoHit(PlayerControllerB player, Shovel shovel) { AccessTools.Field(typeof(Shovel), "previousPlayerHeldBy").SetValue(shovel, player); shovel.reelingUp = true; if (currentCoroutine == null) { player.activatingItem = true; player.twoHanded = true; player.playerBodyAnimator.ResetTrigger("shovelHit"); player.playerBodyAnimator.SetBool("reelingUp", true); shovel.shovelAudio.PlayOneShot(shovel.reelUp); yield return (object)new WaitForSeconds(0.1f); if (shovel != null) { shovel.SwingShovel(!((GrabbableObject)shovel).isHeld); } yield return (object)new WaitForSeconds(0.15f); if (shovel != null) { shovel.HitShovel(!((GrabbableObject)shovel).isHeld); } shovel.reelingUp = false; AccessTools.Field(typeof(Shovel), "reelingUpCoroutine").SetValue(shovel, null); currentCoroutine = null; } } private static IEnumerator PerfectParryWindow(PlayerControllerB player, Shovel shovel) { if (!isPerfectParryFrame) { isPerfectParryFrame = true; lastParryTime = Time.fixedTime; shovel.shovelAudio.PlayOneShot(shovel.reelUp); shovel.ReelUpSFXServerRpc(); yield return (object)new WaitForSeconds(perfectParryWindow); isPerfectParryFrame = false; } } private static void MakeCriticallyInjured(PlayerControllerB player, bool enable) { player.criticallyInjured = enable; player.playerBodyAnimator.SetBool("Limp", enable); } private static bool IsParryOnCooldown() { return Time.fixedTime - lastParryTime < perfectParryCooldown; } } [HarmonyPatch(typeof(Shovel))] internal class ShovelPatch { [HarmonyPatch("HitShovel")] [HarmonyPostfix] public static void HitShovelPostfix(ref Shovel __instance, ref List<RaycastHit> ___objectsHitByShovelList, ref PlayerControllerB ___previousPlayerHeldBy) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (___objectsHitByShovelList == null && (___objectsHitByShovelList.Count == 0 || !LethalParryBase.stun || !LethalParryBase.serverModCheck)) { return; } LethalParryBase.logger.LogInfo((object)"Got hit list"); EnemyAI val = default(EnemyAI); foreach (RaycastHit ___objectsHitByShovel in ___objectsHitByShovelList) { RaycastHit current = ___objectsHitByShovel; if (((Component)((RaycastHit)(ref current)).transform.parent).TryGetComponent<EnemyAI>(ref val) && (Object)(object)((RaycastHit)(ref current)).transform != (Object)(object)___previousPlayerHeldBy && (Object)(object)val != (Object)null) { try { LethalParryBase.logger.LogInfo((object)$"Stunned enemy {val.enemyType}!"); val.SetEnemyStunned(true, 1f, ___previousPlayerHeldBy); } catch (Exception arg) { Debug.Log((object)$"Exception caught when hitting object with shovel from player #{___previousPlayerHeldBy.playerClientId}: {arg}"); } } } LethalParryBase.stun = false; } } } namespace LethalParrying.Netcode { [HarmonyPatch] public class ServerModCheck { public static PlayerControllerB localPlayer; public static bool hasMod; public static bool synced; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] public static void InitLocalPlayer(PlayerControllerB __instance) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown localPlayer = __instance; if (NetworkManager.Singleton.IsServer) { hasMod = true; NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("LethalParryingOnRequestModCheck", new HandleNamedMessageDelegate(OnRequest)); LethalParryBase.logger.LogInfo((object)"Setting up Server CustomMessagingManager"); SyncOnLocalClient(); } else { NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("LethalParryingOnReceiveModCheck", new HandleNamedMessageDelegate(OnReceive)); LethalParryBase.logger.LogInfo((object)"Setting up Client CustomMessagingManager"); SendRequestToServer(); } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPrefix] public static bool OnDestroy() { if ((Object)(object)NetworkManager.Singleton != (Object)null) { if (NetworkManager.Singleton.IsServer) { NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler("LethalParryingOnRequestModCheck"); LethalParryBase.logger.LogInfo((object)"Destroying Server CustomMessagingManager"); } else { NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler("LethalParryingOnReceiveModCheck"); LethalParryBase.logger.LogInfo((object)"Destroying Client CustomMessagingManager"); } } hasMod = false; LethalParryBase.serverModCheck = false; LethalParryBase.logger.LogInfo((object)"Setting mod check to false"); return true; } public static void SendRequestToServer() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsClient) { LethalParryBase.logger.LogInfo((object)"Sending request to server."); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalParryingOnRequestModCheck", 0uL, val, (NetworkDelivery)3); } else { LethalParryBase.logger.LogError((object)"Faile to send request if server has mod."); } } public static void OnRequest(ulong clientId, FastBufferReader reader) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsServer) { LethalParryBase.logger.LogInfo((object)$"Player_ID: {clientId} Requested for Mod Check."); bool flag = true; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(FastBufferWriter.GetWriteSize<bool>(ref flag, default(ForStructs)), (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalParryingOnReceiveModCheck", clientId, val, (NetworkDelivery)3); } } public static void OnReceive(ulong clientId, FastBufferReader reader) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); hasMod = flag; LethalParryBase.logger.LogInfo((object)$"Received mod check: {hasMod} from server!"); SyncOnLocalClient(); } public static void SyncOnLocalClient() { LethalParryBase.serverModCheck = hasMod; } } }