using HarmonyLib; using KFCommonUtilityLib.Scripts.StaticManagers; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; using UnityEngine; using CameraShake; using System; [HarmonyPatch] class RecoilPatch { [HarmonyPatch(typeof(EntityPlayerLocal), "Awake")] [HarmonyPostfix] private static void Postfix_Awake_EntityPlayerLocal(EntityPlayerLocal __instance) { RecoilManager.InitPlayer(__instance); } [HarmonyPatch(typeof(vp_FPCamera), nameof(vp_FPCamera.LateUpdate))] [HarmonyTranspiler] private static IEnumerable Transpiler_LateUpdate_vp_FPCamera(IEnumerable instructions) { var codes = instructions.ToList(); var mtd_update = AccessTools.Method(typeof(vp_FPCamera), nameof(vp_FPCamera.Update3rdPerson)); var prop_trans = AccessTools.PropertyGetter(typeof(vp_Component), nameof(vp_Component.transform)); for (int i = 0; i < codes.Count; i++) { if (codes[i].Calls(mtd_update)) { codes.InsertRange(i - 1, new[] { new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Call, prop_trans), CodeInstruction.Call(typeof(KFExtensions), nameof(KFExtensions.AddMissingComponent), new Type[]{ typeof(Transform) }, new Type[]{ typeof(CameraShaker) }), CodeInstruction.Call(typeof(CameraShaker), nameof(CameraShaker.UpdateShake)) }); break; } } return codes; } [HarmonyPatch(typeof(GameManager), nameof(GameManager.SaveAndCleanupWorld))] [HarmonyPostfix] private static void Postfix_SaveAndCleanupWorld_GameManager() { RecoilManager.Cleanup(); } [HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.OnFired))] [HarmonyTranspiler] private static IEnumerable Transpiler_OnFired_EntityPlayerLocal(IEnumerable instructions) { var codes = instructions.ToList(); FieldInfo fld_isfpv = AccessTools.Field(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.bFirstPersonView)); ConstructorInfo mtd_ctor = AccessTools.Constructor(typeof(Vector2), new[] { typeof(float), typeof(float) }); for (int i = 0; i < codes.Count - 1; i++) { if (codes[i].Is(OpCodes.Call, mtd_ctor) && codes[i + 1].opcode == OpCodes.Ldloc_0) { for (int j = i + 1; j < codes.Count - 1; j++) { if (codes[j].opcode == OpCodes.Pop && codes[j + 1].opcode == OpCodes.Ldarg_0) { codes.RemoveRange(i + 1, j - i); break; } } codes.InsertRange(i + 1, new[] { new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldloca_S, 0), new CodeInstruction(OpCodes.Ldloca_S, 1), CodeInstruction.Call(typeof(RecoilPatch), nameof(RecoilPatch.ModifyRecoil)) }); i += 4; } else if (codes[i].LoadsField(fld_isfpv)) { codes.RemoveRange(i + 2, codes.Count - i - 3); codes.InsertRange(i + 2, new[] { new CodeInstruction(OpCodes.Ldloc_0), new CodeInstruction(OpCodes.Ldloc_1), CodeInstruction.Call(typeof(RecoilManager), nameof(RecoilManager.AddRecoil)) }); break; } } return codes; } private static void ModifyRecoil(EntityPlayerLocal player, ref Vector2 kickHor, ref Vector2 kickVer) { float multiplierHor = Mathf.Max(1 - EffectManager.GetValue(CustomEnums.KickDegreeHorizontalModifier, player.inventory.holdingItemItemValue, 0f, player), 0); float multiplierVer = Mathf.Max(1 - EffectManager.GetValue(CustomEnums.KickDegreeVerticalModifier, player.inventory.holdingItemItemValue, 0f, player), 0); kickHor *= multiplierHor; kickVer *= multiplierVer; } [HarmonyPatch(typeof(PlayerMoveController), nameof(PlayerMoveController.Update))] [HarmonyTranspiler] private static IEnumerable Transpiler_Update_PlayerMoveController(IEnumerable instructions) { var codes = instructions.ToList(); FieldInfo fld_rotation = AccessTools.Field(typeof(MovementInput), nameof(MovementInput.rotation)); FieldInfo fld_rx = AccessTools.Field(typeof(Vector3), nameof(Vector3.x)); FieldInfo fld_ry = AccessTools.Field(typeof(Vector3), nameof(Vector3.y)); for (int i = 0; i < codes.Count; i++) { if (codes[i].LoadsField(fld_rotation, true)) { if (codes[i + 1].LoadsField(fld_rx, true)) { for (; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Stind_R4) { codes.Insert(i, CodeInstruction.Call(typeof(RecoilManager), nameof(RecoilManager.CompensateX))); break; } } } else if (codes[i + 1].LoadsField(fld_ry, true)) { for (; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Stind_R4) { codes.Insert(i, CodeInstruction.Call(typeof(RecoilManager), nameof(RecoilManager.CompensateY))); break; } } } } } return codes; } [HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.MoveByInput))] [HarmonyPrefix] private static bool Prefix_MoveByInput_EntityPlayerLocal() { RecoilManager.ApplyRecoil(); return true; } }