2024-05-21 19:10:17 +01:00
|
|
|
using SPT.Reflection.CodeWrapper;
|
|
|
|
using SPT.Reflection.Patching;
|
|
|
|
using SPT.Reflection.Utils;
|
2023-03-03 18:52:31 +00:00
|
|
|
using EFT;
|
|
|
|
using HarmonyLib;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Reflection;
|
|
|
|
using System.Reflection.Emit;
|
|
|
|
|
2024-05-21 19:10:17 +01:00
|
|
|
namespace SPT.SinglePlayer.Patches.ScavMode
|
2023-03-03 18:52:31 +00:00
|
|
|
{
|
|
|
|
public class ScavPrefabLoadPatch : ModulePatch
|
|
|
|
{
|
2024-07-12 14:56:10 +01:00
|
|
|
/// <summary>
|
|
|
|
/// Aim of this patch is to check what Side we are loading into the raid as.
|
|
|
|
/// then if we are Scav, the game will load the bundles for that
|
|
|
|
/// else it will load the bundles for PMC
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
2023-03-03 18:52:31 +00:00
|
|
|
protected override MethodBase GetTargetMethod()
|
|
|
|
{
|
2024-07-12 14:49:25 +01:00
|
|
|
// Struct324 - 3.10.0
|
2023-03-03 18:52:31 +00:00
|
|
|
var desiredType = typeof(TarkovApplication)
|
2024-01-13 22:08:29 +00:00
|
|
|
.GetNestedTypes(PatchConstants.PublicDeclaredFlags)
|
|
|
|
.SingleCustom(x => x.GetField("timeAndWeather") != null
|
|
|
|
&& x.GetField("tarkovApplication_0") != null
|
2024-10-31 21:27:32 +00:00
|
|
|
&& x.GetField("inTransition") != null
|
2024-01-13 22:08:29 +00:00
|
|
|
&& x.Name.Contains("Struct"));
|
2023-03-03 18:52:31 +00:00
|
|
|
|
2024-01-13 22:08:29 +00:00
|
|
|
var desiredMethod = desiredType.GetMethods(PatchConstants.PublicDeclaredFlags)
|
2023-03-03 18:52:31 +00:00
|
|
|
.FirstOrDefault(x => x.Name == "MoveNext");
|
|
|
|
|
|
|
|
Logger.LogDebug($"{this.GetType().Name} Type: {desiredType?.Name}");
|
|
|
|
Logger.LogDebug($"{this.GetType().Name} Method: {desiredMethod?.Name}");
|
|
|
|
|
|
|
|
return desiredMethod;
|
|
|
|
}
|
|
|
|
|
|
|
|
[PatchTranspiler]
|
2024-08-02 16:57:59 +01:00
|
|
|
public static IEnumerable<CodeInstruction> PatchTranspile(ILGenerator generator, IEnumerable<CodeInstruction> instructions)
|
2023-03-03 18:52:31 +00:00
|
|
|
{
|
|
|
|
var codes = new List<CodeInstruction>(instructions);
|
|
|
|
|
|
|
|
// Search for code where backend.Session.getProfile() is called.
|
2024-02-12 13:15:22 +00:00
|
|
|
var searchCode = new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(PatchConstants.BackendProfileInterfaceType, "get_Profile"));
|
2023-03-03 18:52:31 +00:00
|
|
|
var searchIndex = -1;
|
|
|
|
|
|
|
|
for (var i = 0; i < codes.Count; i++)
|
|
|
|
{
|
|
|
|
if (codes[i].opcode == searchCode.opcode && codes[i].operand == searchCode.operand)
|
|
|
|
{
|
|
|
|
searchIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 IL chain that we're interested in.
|
|
|
|
searchIndex -= 2;
|
|
|
|
|
|
|
|
var brFalseLabel = generator.DefineLabel();
|
|
|
|
var brLabel = generator.DefineLabel();
|
|
|
|
|
|
|
|
var newCodes = CodeGenerator.GenerateInstructions(new List<Code>()
|
|
|
|
{
|
|
|
|
new Code(OpCodes.Ldloc_1),
|
|
|
|
new Code(OpCodes.Call, typeof(ClientApplication<ISession>), "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),
|
2024-02-12 13:15:22 +00:00
|
|
|
new Code(OpCodes.Callvirt, PatchConstants.BackendProfileInterfaceType, "get_Profile"),
|
2023-03-03 18:52:31 +00:00
|
|
|
new Code(OpCodes.Br, brLabel),
|
2024-02-12 13:15:22 +00:00
|
|
|
new CodeWithLabel(OpCodes.Callvirt, brFalseLabel, PatchConstants.BackendProfileInterfaceType, "get_ProfileOfPet"),
|
2023-03-03 18:52:31 +00:00
|
|
|
new CodeWithLabel(OpCodes.Ldc_I4_1, brLabel)
|
|
|
|
});
|
|
|
|
|
|
|
|
codes.RemoveRange(searchIndex, 4);
|
|
|
|
codes.InsertRange(searchIndex, newCodes);
|
|
|
|
|
|
|
|
return codes.AsEnumerable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|