using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using CadaverBloomDamagePatch.NetcodePatcher; using CadaverBloomDamagePatch.Patches; using CadaverBloomDamagePatch.Util; using HarmonyLib; using Microsoft.CodeAnalysis; [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 = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] internal class { static () { } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 CadaverBloomDamagePatch { [BepInPlugin("com.github.WhiteSpike.CadaverBloomDamagePatch", "Cadaver Bloom Damage Patch", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static readonly Harmony harmony = new Harmony("com.github.WhiteSpike.CadaverBloomDamagePatch"); internal static readonly ManualLogSource mls = Logger.CreateLogSource("Cadaver Bloom Damage Patch"); private void Awake() { harmony.PatchAll(typeof(CadaverBloomAIPatcher)); mls.LogInfo((object)"Cadaver Bloom Damage Patch 1.0.0 has been loaded successfully."); } } public static class PluginInfo { public const string PLUGIN_GUID = "CadaverBloomDamagePatch"; public const string PLUGIN_NAME = "CadaverBloomDamagePatch"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace CadaverBloomDamagePatch.Util { internal static class Tools { public static void FindCodeInstruction(ref int index, ref List codes, object findValue, MethodInfo addCode, bool skip = false, bool requireInstance = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, string errorMessage = "Not found") { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown bool flag = false; while (index < codes.Count) { if (CheckCodeInstruction(codes[index], findValue)) { flag = true; if (!skip) { if (andInstruction) { codes.Insert(index + 1, new CodeInstruction(OpCodes.And, (object)null)); } if (!andInstruction && orInstruction) { codes.Insert(index + 1, new CodeInstruction(OpCodes.Or, (object)null)); } if (notInstruction) { codes.Insert(index + 1, new CodeInstruction(OpCodes.Not, (object)null)); } codes.Insert(index + 1, new CodeInstruction(OpCodes.Call, (object)addCode)); if (requireInstance) { codes.Insert(index + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null)); } } break; } index++; } if (!flag) { Plugin.mls.LogError((object)errorMessage); } index++; } public static void FindLocalField(ref int index, ref List codes, int localIndex, object addCode = null, bool skip = false, bool store = false, bool requireInstance = false, string errorMessage = "Not found") { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown bool flag = false; while (index < codes.Count) { if (CheckCodeInstruction(codes[index], localIndex, store)) { flag = true; if (!skip) { codes.Insert(index + 1, new CodeInstruction(OpCodes.Call, addCode)); if (requireInstance) { codes.Insert(index + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null)); } } break; } index++; } if (!flag) { Plugin.mls.LogError((object)errorMessage); } index++; } public static void FindString(ref int index, ref List codes, string findValue, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { FindCodeInstruction(ref index, ref codes, findValue, addCode, skip, requireInstance, notInstruction, andInstruction, orInstruction, errorMessage); } public static void FindField(ref int index, ref List codes, FieldInfo findField, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { FindCodeInstruction(ref index, ref codes, findField, addCode, skip, requireInstance, notInstruction, andInstruction, orInstruction, errorMessage); } public static void FindMethod(ref int index, ref List codes, MethodInfo findMethod, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { FindCodeInstruction(ref index, ref codes, findMethod, addCode, skip, requireInstance, notInstruction, andInstruction, orInstruction, errorMessage); } public static void FindFloat(ref int index, ref List codes, float findValue, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { FindCodeInstruction(ref index, ref codes, findValue, addCode, skip, requireInstance, notInstruction, andInstruction, orInstruction, errorMessage); } public static void FindInteger(ref int index, ref List codes, sbyte findValue, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { FindCodeInstruction(ref index, ref codes, findValue, addCode, skip, requireInstance, notInstruction, andInstruction, orInstruction, errorMessage); } public static void FindSub(ref int index, ref List codes, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { object findValue = OpCodes.Sub; bool notInstruction2 = notInstruction; bool andInstruction2 = andInstruction; bool orInstruction2 = orInstruction; FindCodeInstruction(ref index, ref codes, findValue, addCode, skip, requireInstance, notInstruction2, andInstruction2, orInstruction2, errorMessage); } public static void FindDiv(ref int index, ref List codes, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { object findValue = OpCodes.Div; bool notInstruction2 = notInstruction; bool andInstruction2 = andInstruction; bool orInstruction2 = orInstruction; FindCodeInstruction(ref index, ref codes, findValue, addCode, skip, requireInstance, notInstruction2, andInstruction2, orInstruction2, errorMessage); } public static void FindAdd(ref int index, ref List codes, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { object findValue = OpCodes.Add; bool notInstruction2 = notInstruction; bool andInstruction2 = andInstruction; bool orInstruction2 = orInstruction; FindCodeInstruction(ref index, ref codes, findValue, addCode, skip, requireInstance, notInstruction2, andInstruction2, orInstruction2, errorMessage); } public static void FindMul(ref int index, ref List codes, MethodInfo addCode = null, bool skip = false, bool notInstruction = false, bool andInstruction = false, bool orInstruction = false, bool requireInstance = false, string errorMessage = "Not found") { object findValue = OpCodes.Mul; bool notInstruction2 = notInstruction; bool andInstruction2 = andInstruction; bool orInstruction2 = orInstruction; FindCodeInstruction(ref index, ref codes, findValue, addCode, skip, requireInstance, notInstruction2, andInstruction2, orInstruction2, errorMessage); } private static bool CheckCodeInstruction(CodeInstruction code, int localIndex, bool store = false) { if (!store) { return localIndex switch { 0 => code.opcode == OpCodes.Ldloc_0, 1 => code.opcode == OpCodes.Ldloc_1, 2 => code.opcode == OpCodes.Ldloc_2, 3 => code.opcode == OpCodes.Ldloc_3, _ => code.opcode == OpCodes.Ldloc && (int)code.operand == localIndex, }; } return localIndex switch { 0 => code.opcode == OpCodes.Stloc_0, 1 => code.opcode == OpCodes.Stloc_1, 2 => code.opcode == OpCodes.Stloc_2, 3 => code.opcode == OpCodes.Stloc_3, _ => code.opcode == OpCodes.Stloc && (int)code.operand == localIndex, }; } private static bool CheckCodeInstruction(CodeInstruction code, object findValue) { if (findValue is sbyte) { return CheckIntegerCodeInstruction(code, findValue); } if (findValue is float) { return code.opcode == OpCodes.Ldc_R4 && code.operand.Equals(findValue); } if (findValue is string) { return code.opcode == OpCodes.Ldstr && code.operand.Equals(findValue); } if (findValue is MethodInfo) { return (code.opcode == OpCodes.Call || code.opcode == OpCodes.Callvirt) && code.operand == findValue; } if (findValue is FieldInfo) { return (code.opcode == OpCodes.Ldfld || code.opcode == OpCodes.Stfld) && code.operand == findValue; } if (findValue is OpCode) { return code.opcode == (OpCode)findValue; } return false; } private static bool CheckIntegerCodeInstruction(CodeInstruction code, object findValue) { return (sbyte)findValue switch { 0 => code.opcode == OpCodes.Ldc_I4_0, 1 => code.opcode == OpCodes.Ldc_I4_1, 2 => code.opcode == OpCodes.Ldc_I4_2, 3 => code.opcode == OpCodes.Ldc_I4_3, 4 => code.opcode == OpCodes.Ldc_I4_4, 5 => code.opcode == OpCodes.Ldc_I4_5, 6 => code.opcode == OpCodes.Ldc_I4_6, 7 => code.opcode == OpCodes.Ldc_I4_7, 8 => code.opcode == OpCodes.Ldc_I4_8, _ => code.opcode == OpCodes.Ldc_I4_S && code.operand.Equals(findValue), }; } } } namespace CadaverBloomDamagePatch.Patches { [HarmonyPatch(typeof(CadaverBloomAI))] internal static class CadaverBloomAIPatcher { public static int tempForce; [HarmonyPatch("HitEnemy")] [HarmonyTranspiler] private static IEnumerable HitEnemyTranspiler(IEnumerable instructions) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown FieldInfo field = typeof(CadaverBloomAIPatcher).GetField("tempForce"); MethodInfo method = typeof(CadaverBloomAI).GetMethod("TakeDamage"); List codes = new List(instructions); int index = 0; Tools.FindMethod(ref index, ref codes, method, null, skip: true); codes.Insert(index - 1, new CodeInstruction(OpCodes.Stsfld, (object)field)); codes.Insert(index - 1, new CodeInstruction(OpCodes.Ldarg_1, (object)null)); return codes; } [HarmonyPatch("TakeDamage")] [HarmonyTranspiler] private static IEnumerable TakeDamageTranspiler(IEnumerable instructions) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown FieldInfo field = typeof(CadaverBloomAIPatcher).GetField("tempForce"); List codes = new List(instructions); int index = 0; Tools.FindInteger(ref index, ref codes, 1, null, skip: true); codes[index - 1] = new CodeInstruction(OpCodes.Ldsfld, (object)field); codes.Insert(index + 1, new CodeInstruction(OpCodes.Stsfld, (object)field)); codes.Insert(index + 1, new CodeInstruction(OpCodes.Ldc_I4_0, (object)null)); return codes; } } } namespace CadaverBloomDamagePatch.Misc { internal static class Metadata { public const string GUID = "com.github.WhiteSpike.CadaverBloomDamagePatch"; public const string NAME = "Cadaver Bloom Damage Patch"; public const string VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace CadaverBloomDamagePatch.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }