From ccad89df05d067788fbe21013e0348aa7f3df836 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 12 Jul 2024 15:59:37 +0100 Subject: [PATCH] renamed and reenabled some required patches --- ....cs => DisablePMCExtractsForScavsPatch.cs} | 2 +- .../Patches/ScavMode/ScavExfilPatch.cs | 2 +- .../Patches/ScavMode/ScavProfileLoadPatch.cs | 80 +++++++++++++++---- .../SPT.SinglePlayer/SPTSingleplayerPlugin.cs | 6 +- 4 files changed, 69 insertions(+), 21 deletions(-) rename project/SPT.SinglePlayer/Patches/ScavMode/{ExfilPointManagerPatch.cs => DisablePMCExtractsForScavsPatch.cs} (97%) diff --git a/project/SPT.SinglePlayer/Patches/ScavMode/ExfilPointManagerPatch.cs b/project/SPT.SinglePlayer/Patches/ScavMode/DisablePMCExtractsForScavsPatch.cs similarity index 97% rename from project/SPT.SinglePlayer/Patches/ScavMode/ExfilPointManagerPatch.cs rename to project/SPT.SinglePlayer/Patches/ScavMode/DisablePMCExtractsForScavsPatch.cs index 1f85c4f..96332c4 100644 --- a/project/SPT.SinglePlayer/Patches/ScavMode/ExfilPointManagerPatch.cs +++ b/project/SPT.SinglePlayer/Patches/ScavMode/DisablePMCExtractsForScavsPatch.cs @@ -11,7 +11,7 @@ namespace SPT.SinglePlayer.Patches.ScavMode /// /// Disable PMC exfil points when playing as pscav /// - public class ExfilPointManagerPatch : ModulePatch + public class DisablePMCExtractsForScavsPatch : ModulePatch { protected override MethodBase GetTargetMethod() { diff --git a/project/SPT.SinglePlayer/Patches/ScavMode/ScavExfilPatch.cs b/project/SPT.SinglePlayer/Patches/ScavMode/ScavExfilPatch.cs index b284f11..6576759 100644 --- a/project/SPT.SinglePlayer/Patches/ScavMode/ScavExfilPatch.cs +++ b/project/SPT.SinglePlayer/Patches/ScavMode/ScavExfilPatch.cs @@ -34,7 +34,7 @@ namespace SPT.SinglePlayer.Patches.ScavMode // Get the required mask value and retrieve a list of exfil points, setting it as the result var mask = __instance.GetScavExfiltrationMask(profile.Id); - __result = __instance.ScavExfiltrationClaim(mask, profile.Id); + __result = __instance.ScavExfiltrationClaim(mask, profile.Id); return false; // Don't run the original method anymore, as that will overwrite our new exfil points with ones meant for a PMC } diff --git a/project/SPT.SinglePlayer/Patches/ScavMode/ScavProfileLoadPatch.cs b/project/SPT.SinglePlayer/Patches/ScavMode/ScavProfileLoadPatch.cs index ae310ee..97560f7 100644 --- a/project/SPT.SinglePlayer/Patches/ScavMode/ScavProfileLoadPatch.cs +++ b/project/SPT.SinglePlayer/Patches/ScavMode/ScavProfileLoadPatch.cs @@ -13,30 +13,78 @@ namespace SPT.SinglePlayer.Patches.ScavMode { public class ScavProfileLoadPatch : ModulePatch { - /// - /// This was changed from an IL Patch, - /// aim is just to replace loaded profile with the Scav profile when creating a game - /// - /// protected override MethodBase GetTargetMethod() { - return AccessTools.Method(typeof(LocalGame), nameof(LocalGame.smethod_6)); + // Struct331 - 20575 + var desiredType = typeof(TarkovApplication) + .GetNestedTypes(PatchConstants.PublicDeclaredFlags) + .SingleCustom(x => x.GetField("timeAndWeather") != null + && x.GetField("timeHasComeScreenController") != null + && x.Name.Contains("Struct")); + + var desiredMethod = desiredType.GetMethods(PatchConstants.PublicDeclaredFlags) + .FirstOrDefault(x => x.Name == "MoveNext"); + + Logger.LogDebug($"{this.GetType().Name} Type: {desiredType?.Name}"); + Logger.LogDebug($"{this.GetType().Name} Method: {desiredMethod?.Name}"); + + return desiredMethod; } - [PatchPrefix] - public static void PatchPrefix(ref Profile profile, LocalRaidSettings raidSettings) + [PatchTranspiler] + private static IEnumerable PatchTranspile(ILGenerator generator, IEnumerable instructions) { - // check raidsettings to see if its a pmc raid - if (raidSettings.playerSide == ESideType.Pmc) + var codes = new List(instructions); + + // Search for code where backend.Session.getProfile() is called. + var searchCode = new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(PatchConstants.BackendProfileInterfaceType, "get_Profile")); + var searchIndex = -1; + + for (var i = 0; i < codes.Count; i++) { - Logger.LogInfo("Side was PMC, returning"); - return; + if (codes[i].opcode == searchCode.opcode && codes[i].operand == searchCode.operand) + { + searchIndex = i; + break; + } } - // if not get scav profile - // load that into the profile param - Logger.LogInfo("Side was Scav, setting profile"); - profile = PatchConstants.BackEndSession.ProfileOfPet; + // Patch failed. + if (searchIndex == -1) + { + Logger.LogError($"Patch {MethodBase.GetCurrentMethod()} failed: Could not find reference code."); + return instructions; + } + + // Move back by 2. This is the start of this method call. + searchIndex -= 2; + + var brFalseLabel = generator.DefineLabel(); + var brLabel = generator.DefineLabel(); + var newCodes = CodeGenerator.GenerateInstructions(new List() + { + new Code(OpCodes.Ldloc_1), + new Code(OpCodes.Call, typeof(ClientApplication), "get_Session"), + new Code(OpCodes.Ldloc_1), + new Code(OpCodes.Ldfld, typeof(TarkovApplication), "_raidSettings"), + new Code(OpCodes.Callvirt, typeof(RaidSettings), "get_IsPmc"), + new Code(OpCodes.Brfalse, brFalseLabel), + new Code(OpCodes.Callvirt, PatchConstants.BackendProfileInterfaceType, "get_Profile"), + new Code(OpCodes.Br, brLabel), + new CodeWithLabel(OpCodes.Callvirt, brFalseLabel, PatchConstants.BackendProfileInterfaceType, "get_ProfileOfPet"), + new CodeWithLabel(OpCodes.Stfld, brLabel, typeof(TarkovApplication).GetNestedTypes(BindingFlags.Public).SingleCustom(IsTargetNestedType), "profile") + }); + + codes.RemoveRange(searchIndex, 4); + codes.InsertRange(searchIndex, newCodes); + + return codes.AsEnumerable(); + } + + private static bool IsTargetNestedType(System.Type nestedType) + { + return nestedType.GetMethods(PatchConstants.PublicDeclaredFlags) + .Count(x => x.GetParameters().Length == 1 && x.GetParameters()[0].ParameterType == typeof(IResult)) > 0 && nestedType.GetField("savageProfile") != null; } } } diff --git a/project/SPT.SinglePlayer/SPTSingleplayerPlugin.cs b/project/SPT.SinglePlayer/SPTSingleplayerPlugin.cs index 981da5f..671113e 100644 --- a/project/SPT.SinglePlayer/SPTSingleplayerPlugin.cs +++ b/project/SPT.SinglePlayer/SPTSingleplayerPlugin.cs @@ -24,18 +24,18 @@ namespace SPT.SinglePlayer new EmptyInfilFixPatch().Enable(); new MaxBotPatch().Enable(); new PostRaidHealingPricePatch().Enable(); - new ExfilPointManagerPatch().Enable(); new HideoutQuestIgnorePatch().Enable(); new SpawnProcessNegativeValuePatch().Enable(); new SpawnPmcPatch().Enable(); - // new ScavExperienceGainPatch().Enable(); - // new ScavExfilPatch().Enable(); // new ScavRepAdjustmentPatch().Enable(); // new ScavSellAllPriceStorePatch().Enable(); // new ScavSellAllRequestPatch().Enable(); // Still need + new ScavExperienceGainPatch().Enable(); + new DisablePMCExtractsForScavsPatch().Enable(); + new ScavExfilPatch().Enable(); new ScavProfileLoadPatch().Enable(); new ScavPrefabLoadPatch().Enable(); new DisableReadyLocationReadyPatch().Enable();