using System; using System.Linq; using System.Collections.Generic; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using HarmonyLib.Tools; using System.Reflection.Emit; namespace BanquetForCyka { [BepInPlugin(PluginGuid, PluginName, PluginVersion)] public class Main : BaseUnityPlugin { private const string PluginGuid = "BanquetForCyka"; private const string PluginName = "BanquetForCyka"; private const string PluginVersion = "1.0.0"; public static ConfigEntry debug; public static ConfigEntry debugXp; public static ConfigEntry debugDodgeWindow; public static ConfigEntry debugStatEntry; public static ConfigEntry debugSkillEntry; public static ConfigEntry debugLevelUpEntry; public static ExpressionConfigEntry xpMultiplier; public static ExpressionConfigEntry dodgeWindowTotal; public static ExpressionConfigEntry dodgeWindowPerfect; public static ExpressionConfigEntry levelUpStatEntry; public static ExpressionConfigEntry levelUpSkillEntry; public void Awake() { debug = Config.Bind("Debug", "Global Debug", false); debugXp = Config.Bind("Debug", "XP Debug", false); debugDodgeWindow = Config.Bind("Debug", "Dodge Window Debug", false); debugStatEntry = Config.Bind("Debug", "Stat Entry Debug", false); debugSkillEntry = Config.Bind("Debug", "Skill Entry Debug", false); debugLevelUpEntry = Config.Bind("Debug", "Level Up Entry Debug", false); xpMultiplier = new ExpressionConfigEntry( Config, "General", "XP Multiplier", "v*1", "XP Multiplier expression. Use 'v' to represent the original value.", debugXp); dodgeWindowTotal = new ExpressionConfigEntry( Config, "General", "Dodge Window Total", "v*1", "Total dodge window duration expression. Use 'v' to represent the original value (20).", debugDodgeWindow); dodgeWindowPerfect = new ExpressionConfigEntry( Config, "General", "Dodge Window Perfect", "v*1", "Perfect dodge window percentage expression. Use 'v' to represent the original value (0.25).", debugDodgeWindow); levelUpStatEntry = new ExpressionConfigEntry( Config, "General", "Level Up Stat Entry", "v*1", "Stat Entry expression. Use 'v' to represent the original value.", debugStatEntry); levelUpSkillEntry = new ExpressionConfigEntry( Config, "General", "Level Up Skill Entry", "v*1", "Skill Entry expression. Use 'v' to represent the original value.", debugSkillEntry); Logger.LogInfo("BanquetForCyka loaded"); HarmonyFileLog.Enabled = true; Harmony harmony = new Harmony(PluginGuid); harmony.PatchAll(); var originalMethods = harmony.GetPatchedMethods(); Logger.LogInfo("Patched " + originalMethods.Count() + " methods"); } public static void LogDebug(string message, ConfigEntry debugFlag = null) { if (debug.Value || (debugFlag != null && debugFlag.Value)) Console.WriteLine(message); } } [HarmonyPatch(typeof(Stats), "AddXP")] public class Stats_AddXP { public static void Prefix(ref int amt) { Main.LogDebug("Original XP amount: " + amt, Main.debugXp); float result = Main.xpMultiplier.Evaluate(amt); amt = (int)result; Main.LogDebug("Modified XP amount: " + amt, Main.debugXp); } } [HarmonyPatch(typeof(Actions), "DodgeCalculation")] public class Actions_DodgeCalculation_Transpiler { public static IEnumerable Transpiler(IEnumerable instructions) { var codes = new List(instructions); // Find the ldc.r4 20 instruction for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldc_R4 && (float)codes[i].operand == 20f) { // Replace with our expression evaluation codes[i] = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(Main), "dodgeWindowTotal")); codes.Insert(i + 1, new CodeInstruction(OpCodes.Ldc_R4, 20f)); codes.Insert(i + 2, new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(ExpressionConfigEntry), "Evaluate"))); break; } } // Find the ldc.r4 0.25 instruction for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldc_R4 && (float)codes[i].operand == 0.25f) { // Replace with our expression evaluation codes[i] = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(Main), "dodgeWindowPerfect")); codes.Insert(i + 1, new CodeInstruction(OpCodes.Ldc_R4, 0.25f)); codes.Insert(i + 2, new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(ExpressionConfigEntry), "Evaluate"))); break; } } return codes; } } [HarmonyPatch(typeof(LevelUp), "ClickedStat")] public class Actions_ClickedStat { public static IEnumerable Transpiler(IEnumerable instructions) { var codes = new List(instructions); // Find the ldc.r4 1 instruction for (int i = codes.Count - 1; i >= 0; i--) { if (codes[i].opcode == OpCodes.Ldc_R4 && (float)codes[i].operand == 1f) { // Replace with our expression evaluation codes[i] = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(Main), "levelUpStatEntry")); codes.Insert(i + 1, new CodeInstruction(OpCodes.Ldc_R4, 1f)); codes.Insert(i + 2, new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(ExpressionConfigEntry), "Evaluate"))); break; } } return codes; } } [HarmonyPatch(typeof(LevelUp), "IncreaseAmt")] public class Actions_IncreaseAmount { public static void Postfix(ref int __result) { Main.LogDebug("Original amount: " + __result, Main.debugLevelUpEntry); float result = Main.levelUpSkillEntry.Evaluate(__result); __result = (int)result; Main.LogDebug("Modified amount: " + __result, Main.debugLevelUpEntry); } } }