0
0
mirror of https://github.com/sp-tarkov/modules.git synced 2025-02-13 06:10:45 -05:00

3.9.0-DEV (!128)

Reviewed-on: SPT-AKI/Modules#128
This commit is contained in:
chomp 2024-05-21 17:53:20 +00:00
commit 9b7154bded
62 changed files with 484 additions and 494 deletions

View File

@ -22,7 +22,7 @@ git config --local user.email "USERNAME@SOMETHING.com"
``` ```
## Requirements ## Requirements
- Escape From Tarkov 29197 - Escape From Tarkov 29862
- Visual Studio Code -OR- Visual Studio 2022 - Visual Studio Code -OR- Visual Studio 2022
- .NET 6 SDK - .NET 6 SDK
- [PowerShell v7](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows) - [PowerShell v7](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows)

View File

@ -6,8 +6,8 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Company>SPT Aki</Company> <Company>SPT</Company>
<Copyright>Copyright @ SPT Aki 2024</Copyright> <Copyright>Copyright @ SPT 2024</Copyright>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,12 +3,13 @@
<PropertyGroup> <PropertyGroup>
<Version>1.0.0.0</Version> <Version>1.0.0.0</Version>
<TargetFramework>net471</TargetFramework> <TargetFramework>net471</TargetFramework>
<AssemblyName>spt-common</AssemblyName>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Company>Aki</Company> <Company>SPT</Company>
<Copyright>Copyright @ Aki 2024</Copyright> <Copyright>Copyright @ SPT 2024</Copyright>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,85 +0,0 @@
#region DEPRECATED, REMOVE IN 3.8.1
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Aki.Common.Utils;
namespace Aki.Common.Http
{
[Obsolete("Request is deprecated, please use Aki.Common.Http.Client instead.")]
public class Request
{
[Obsolete("Request.Send() is deprecated, please use Aki.Common.Http.Client instead.")]
public byte[] Send(string url, string method, byte[] data = null, bool compress = true, string mime = null, Dictionary<string, string> headers = null)
{
if (!WebConstants.IsValidMethod(method))
{
throw new ArgumentException("request method is invalid");
}
Uri uri = new Uri(url);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
if (uri.Scheme == "https")
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
request.ServerCertificateValidationCallback = delegate { return true; };
}
request.Timeout = 15000;
request.Method = method;
request.Headers.Add("Accept-Encoding", "deflate");
if (headers != null)
{
foreach (KeyValuePair<string, string> item in headers)
{
request.Headers.Add(item.Key, item.Value);
}
}
if (method != WebConstants.Get && method != WebConstants.Head && data != null)
{
byte[] body = (compress) ? Zlib.Compress(data, ZlibCompression.Maximum) : data;
request.ContentType = WebConstants.IsValidMime(mime) ? mime : "application/octet-stream";
request.ContentLength = body.Length;
if (compress)
{
request.Headers.Add("Content-Encoding", "deflate");
}
using (Stream stream = request.GetRequestStream())
{
stream.Write(body, 0, body.Length);
}
}
using (WebResponse response = request.GetResponse())
{
using (MemoryStream ms = new MemoryStream())
{
response.GetResponseStream().CopyTo(ms);
byte[] body = ms.ToArray();
if (body.Length == 0)
{
return null;
}
if (Zlib.IsCompressed(body))
{
return Zlib.Decompress(body);
}
return body;
}
}
}
}
}
#endregion

View File

@ -129,89 +129,5 @@ namespace Aki.Common.Http
{ {
return Task.Run(() => PutJsonAsync(path, json)).Result; return Task.Run(() => PutJsonAsync(path, json)).Result;
} }
#region DEPRECATED, REMOVE IN 3.8.1
[Obsolete("GetData(path, isHost) is deprecated, please use GetData(path) instead.")]
public static byte[] GetData(string path, bool hasHost)
{
var url = (hasHost) ? path : Host + path;
_logger.LogInfo($"Request GET data: {SessionId}:{url}");
var headers = new Dictionary<string, string>()
{
{ "Cookie", $"PHPSESSID={SessionId}" },
{ "SessionId", SessionId }
};
var request = new Request();
var data = request.Send(url, "GET", null, headers: headers);
ValidateData(url, data);
return data;
}
[Obsolete("GetJson(path, isHost) is deprecated, please use GetJson(path) instead.")]
public static string GetJson(string path, bool hasHost)
{
var url = (hasHost) ? path : Host + path;
_logger.LogInfo($"Request GET json: {SessionId}:{url}");
var headers = new Dictionary<string, string>()
{
{ "Cookie", $"PHPSESSID={SessionId}" },
{ "SessionId", SessionId }
};
var request = new Request();
var data = request.Send(url, "GET", headers: headers);
var body = Encoding.UTF8.GetString(data);
ValidateJson(url, body);
return body;
}
[Obsolete("PostJson(path, json, isHost) is deprecated, please use PostJson(path, json) instead.")]
public static string PostJson(string path, string json, bool hasHost)
{
var url = (hasHost) ? path : Host + path;
_logger.LogInfo($"Request POST json: {SessionId}:{url}");
var payload = Encoding.UTF8.GetBytes(json);
var mime = WebConstants.Mime[".json"];
var headers = new Dictionary<string, string>()
{
{ "Cookie", $"PHPSESSID={SessionId}" },
{ "SessionId", SessionId }
};
var request = new Request();
var data = request.Send(url, "POST", payload, true, mime, headers);
var body = Encoding.UTF8.GetString(data);
ValidateJson(url, body);
return body;
}
[Obsolete("PutJson(path, json, isHost) is deprecated, please use PutJson(path, json) instead.")]
public static void PutJson(string path, string json, bool hasHost)
{
var url = (hasHost) ? path : Host + path;
_logger.LogInfo($"Request PUT json: {SessionId}:{url}");
var payload = Encoding.UTF8.GetBytes(json);
var mime = WebConstants.Mime[".json"];
var headers = new Dictionary<string, string>()
{
{ "Cookie", $"PHPSESSID={SessionId}" },
{ "SessionId", SessionId }
};
var request = new Request();
request.Send(url, "PUT", payload, true, mime, headers);
}
#endregion
} }
} }

View File

@ -1,78 +0,0 @@
#region DEPRECATED, REMOVE IN 3.8.1
using System;
using System.Collections.Generic;
using System.Linq;
namespace Aki.Common.Http
{
[Obsolete("WebConstants is deprecated, please use System.Net.Http functionality instead.")]
public static class WebConstants
{
[Obsolete("Get is deprecated, please use HttpMethod.Get instead.")]
public const string Get = "GET";
[Obsolete("Head is deprecated, please use HttpMethod.Head instead.")]
public const string Head = "HEAD";
[Obsolete("Post is deprecated, please use HttpMethod.Post instead.")]
public const string Post = "POST";
[Obsolete("Put is deprecated, please use HttpMethod.Put instead.")]
public const string Put = "PUT";
[Obsolete("Delete is deprecated, please use HttpMethod.Delete instead.")]
public const string Delete = "DELETE";
[Obsolete("Connect is deprecated, please use HttpMethod.Connect instead.")]
public const string Connect = "CONNECT";
[Obsolete("Options is deprecated, please use HttpMethod.Options instead.")]
public const string Options = "OPTIONS";
[Obsolete("Trace is deprecated, please use HttpMethod.Trace instead.")]
public const string Trace = "TRACE";
[Obsolete("Mime is deprecated, there is sadly no replacement.")]
public static Dictionary<string, string> Mime { get; private set; }
static WebConstants()
{
Mime = new Dictionary<string, string>()
{
{ ".bin", "application/octet-stream" },
{ ".txt", "text/plain" },
{ ".htm", "text/html" },
{ ".html", "text/html" },
{ ".css", "text/css" },
{ ".js", "text/javascript" },
{ ".jpeg", "image/jpeg" },
{ ".jpg", "image/jpeg" },
{ ".png", "image/png" },
{ ".ico", "image/vnd.microsoft.icon" },
{ ".json", "application/json" }
};
}
[Obsolete("IsValidMethod is deprecated, please check against HttpMethod entries instead.")]
public static bool IsValidMethod(string method)
{
return method == Get
|| method == Head
|| method == Post
|| method == Put
|| method == Delete
|| method == Connect
|| method == Options
|| method == Trace;
}
[Obsolete("isValidMime is deprecated, there is sadly no replacement available.")]
public static bool IsValidMime(string mime)
{
return Mime.Any(x => x.Value == mime);
}
}
}
#endregion

View File

@ -2,13 +2,13 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net471</TargetFramework> <TargetFramework>net471</TargetFramework>
<AssemblyName>aki-core</AssemblyName> <AssemblyName>spt-core</AssemblyName>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Company>Aki</Company> <Company>SPT</Company>
<Copyright>Copyright @ Aki 2024</Copyright> <Copyright>Copyright @ SPT 2024</Copyright>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -15,7 +15,7 @@ namespace Aki.Core
{ {
_logger = Logger; _logger = Logger;
Logger.LogInfo("Loading: Aki.Core"); Logger.LogInfo("Loading: SPT.Core");
try try
{ {
@ -36,7 +36,7 @@ namespace Aki.Core
throw; throw;
} }
Logger.LogInfo("Completed: Aki.Core"); Logger.LogInfo("Completed: SPT.Core");
} }
} }
} }

View File

@ -8,7 +8,7 @@ namespace Aki.Core.Patches
{ {
public class GameValidationPatch : ModulePatch public class GameValidationPatch : ModulePatch
{ {
private const string PluginName = "Aki.Core"; private const string PluginName = "SPT.Core";
private const string ErrorMessage = "Validation failed"; private const string ErrorMessage = "Validation failed";
private static BepInEx.Logging.ManualLogSource _logger = null; private static BepInEx.Logging.ManualLogSource _logger = null;
private static bool _hasRun = false; private static bool _hasRun = false;

View File

@ -27,9 +27,9 @@ namespace Aki.Core.Utils
new FileInfo(Path.Combine(v2, "UnityCrashHandler64.exe")) new FileInfo(Path.Combine(v2, "UnityCrashHandler64.exe"))
}; };
ServerLog.Debug("Aki.Core", Gfs(v2, "UnityCrashHandler64.exe")?.Length.ToString() ?? "0"); ServerLog.Debug("SPT.Core", Gfs(v2, "UnityCrashHandler64.exe")?.Length.ToString() ?? "0");
ServerLog.Debug("Aki.Core", Gfs(v2, "Uninstall.exe")?.Length.ToString() ?? "0"); ServerLog.Debug("SPT.Core", Gfs(v2, "Uninstall.exe")?.Length.ToString() ?? "0");
ServerLog.Debug("Aki.Core", Gfs(v2, "Register.bat")?.Length.ToString() ?? "0"); ServerLog.Debug("SPT.Core", Gfs(v2, "Register.bat")?.Length.ToString() ?? "0");
v0 = v4.Length - 1; v0 = v4.Length - 1;

View File

@ -35,7 +35,7 @@ namespace Aki.Custom.Airdrops
} }
catch catch
{ {
Debug.LogError("[AKI-AIRDROPS]: Unable to get config from server, airdrop won't occur"); Debug.LogError("[SPT-AIRDROPS]: Unable to get config from server, airdrop won't occur");
Destroy(this); Destroy(this);
throw; throw;
} }
@ -52,7 +52,7 @@ namespace Aki.Custom.Airdrops
} }
catch catch
{ {
Debug.LogError("[AKI-AIRDROPS]: Unable to create plane or crate, airdrop won't occur"); Debug.LogError("[SPT-AIRDROPS]: Unable to create plane or crate, airdrop won't occur");
Destroy(this); Destroy(this);
throw; throw;
} }
@ -98,7 +98,7 @@ namespace Aki.Custom.Airdrops
} }
catch catch
{ {
Debug.LogError("[AKI-AIRDROPS]: An error occurred during the airdrop FixedUpdate process"); Debug.LogError("[SPT-AIRDROPS]: An error occurred during the airdrop FixedUpdate process");
Destroy(airdropBox.gameObject); Destroy(airdropBox.gameObject);
Destroy(airdropPlane.gameObject); Destroy(airdropPlane.gameObject);
Destroy(this); Destroy(this);

View File

@ -69,7 +69,7 @@ namespace Aki.Custom.Airdrops.Utils
break; break;
} }
default: default:
Debug.LogError($"[AKI-AIRDROPS]: Map with name {playerLocation} not handled, defaulting spawn chance to 25%"); Debug.LogError($"[SPT-AIRDROPS]: Map with name {playerLocation} not handled, defaulting spawn chance to 25%");
result = 25; result = 25;
break; break;
} }
@ -104,7 +104,7 @@ namespace Aki.Custom.Airdrops.Utils
if (flareAirdropPoints.Count == 0 && isFlare) if (flareAirdropPoints.Count == 0 && isFlare)
{ {
Debug.LogError($"[AKI-AIRDROPS]: Airdrop called in by flare, Unable to find an airdropPoint within {flareSpawnRadiusDistance}m, defaulting to normal drop"); Debug.LogError($"[SPT-AIRDROPS]: Airdrop called in by flare, Unable to find an airdropPoint within {flareSpawnRadiusDistance}m, defaulting to normal drop");
flareAirdropPoints.Add(allAirdropPoints.OrderBy(_ => Guid.NewGuid()).FirstOrDefault()); flareAirdropPoints.Add(allAirdropPoints.OrderBy(_ => Guid.NewGuid()).FirstOrDefault());
} }

View File

@ -31,7 +31,7 @@ namespace Aki.Custom.Airdrops.Utils
} }
else else
{ {
Debug.LogError($"[AKI-AIRDROPS]: unable to find template: {containerId}"); Debug.LogError($"[SPT-AIRDROPS]: unable to find template: {containerId}");
} }
} }

View File

@ -2,13 +2,13 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net471</TargetFramework> <TargetFramework>net471</TargetFramework>
<AssemblyName>aki-custom</AssemblyName> <AssemblyName>spt-custom</AssemblyName>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Company>Aki</Company> <Company>SPT</Company>
<Copyright>Copyright @ Aki 2024</Copyright> <Copyright>Copyright @ SPT 2024</Copyright>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -16,7 +16,7 @@ namespace Aki.Custom
{ {
public void Awake() public void Awake()
{ {
Logger.LogInfo("Loading: Aki.Custom"); Logger.LogInfo("Loading: SPT.Custom");
try try
{ {
@ -56,6 +56,7 @@ namespace Aki.Custom
new RagfairFeePatch().Enable(); new RagfairFeePatch().Enable();
new ScavQuestPatch().Enable(); new ScavQuestPatch().Enable();
new FixBrokenSpawnOnSandboxPatch().Enable(); new FixBrokenSpawnOnSandboxPatch().Enable();
new BTRControllerInitPatch().Enable();
new BTRPathLoadPatch().Enable(); new BTRPathLoadPatch().Enable();
new BTRActivateTraderDialogPatch().Enable(); new BTRActivateTraderDialogPatch().Enable();
new BTRInteractionPatch().Enable(); new BTRInteractionPatch().Enable();
@ -70,11 +71,13 @@ namespace Aki.Custom
new BTREndRaidItemDeliveryPatch().Enable(); new BTREndRaidItemDeliveryPatch().Enable();
new BTRDestroyAtRaidEndPatch().Enable(); new BTRDestroyAtRaidEndPatch().Enable();
new BTRVehicleMovementSpeedPatch().Enable(); new BTRVehicleMovementSpeedPatch().Enable();
new BTRPathConfigMapPrefixPatch().Enable();
new ScavItemCheckmarkPatch().Enable(); new ScavItemCheckmarkPatch().Enable();
new ResetTraderServicesPatch().Enable(); new ResetTraderServicesPatch().Enable();
new CultistAmuletRemovalPatch().Enable(); new CultistAmuletRemovalPatch().Enable();
new HalloweenExtractPatch().Enable(); new HalloweenExtractPatch().Enable();
new ClampRagdollPatch().Enable(); new ClampRagdollPatch().Enable();
new DisablePvEPatch().Enable();
HookObject.AddOrGetComponent<MenuNotificationManager>(); HookObject.AddOrGetComponent<MenuNotificationManager>();
} }

View File

@ -6,11 +6,10 @@ using EFT.InventoryLogic;
using EFT.UI; using EFT.UI;
using EFT.Vehicle; using EFT.Vehicle;
using HarmonyLib; using HarmonyLib;
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Threading.Tasks;
using UnityEngine; using UnityEngine;
using Random = UnityEngine.Random; using Random = UnityEngine.Random;
@ -27,6 +26,7 @@ namespace Aki.Custom.BTR
private BTRView btrClientSide; private BTRView btrClientSide;
private BotOwner btrBotShooter; private BotOwner btrBotShooter;
private BTRDataPacket btrDataPacket = default; private BTRDataPacket btrDataPacket = default;
private bool btrInitialized = false;
private bool btrBotShooterInitialized = false; private bool btrBotShooterInitialized = false;
private float coverFireTime = 90f; private float coverFireTime = 90f;
@ -48,17 +48,9 @@ namespace Aki.Custom.BTR
private Player.FirearmController firearmController; private Player.FirearmController firearmController;
private WeaponSoundPlayer weaponSoundPlayer; private WeaponSoundPlayer weaponSoundPlayer;
private MethodInfo _updateTaxiPriceMethod;
private float originalDamageCoeff; private float originalDamageCoeff;
BTRManager() private async void Awake()
{
Type btrControllerType = typeof(BTRControllerClass);
_updateTaxiPriceMethod = AccessTools.GetDeclaredMethods(btrControllerType).Single(IsUpdateTaxiPriceMethod);
}
private void Awake()
{ {
try try
{ {
@ -76,11 +68,11 @@ namespace Aki.Custom.BTR
btrController = gameWorld.BtrController; btrController = gameWorld.BtrController;
InitBtr(); await InitBtr();
} }
catch catch
{ {
ConsoleScreen.LogError("[AKI-BTR] Unable to spawn BTR. Check logs."); ConsoleScreen.LogError("[SPT-BTR] Unable to spawn BTR. Check logs.");
Destroy(this); Destroy(this);
throw; throw;
} }
@ -133,14 +125,10 @@ namespace Aki.Custom.BTR
} }
} }
// Find `BTRControllerClass.method_9(PathDestination currentDestinationPoint, bool lastRoutePoint)`
private bool IsUpdateTaxiPriceMethod(MethodInfo method)
{
return (method.GetParameters().Length == 2 && method.GetParameters()[0].ParameterType == typeof(PathDestination));
}
private void Update() private void Update()
{ {
if (!btrInitialized) return;
btrController.SyncBTRVehicleFromServer(UpdateDataPacket()); btrController.SyncBTRVehicleFromServer(UpdateDataPacket());
if (btrController.BotShooterBtr == null) return; if (btrController.BotShooterBtr == null) return;
@ -169,9 +157,11 @@ namespace Aki.Custom.BTR
} }
} }
private void InitBtr() private async Task InitBtr()
{ {
// Initial setup // Initial setup
await btrController.InitBtrController();
botEventHandler = Singleton<BotEventHandler>.Instance; botEventHandler = Singleton<BotEventHandler>.Instance;
var botsController = Singleton<IBotGame>.Instance.BotsController; var botsController = Singleton<IBotGame>.Instance.BotsController;
btrBotService = botsController.BotTradersServices.BTRServices; btrBotService = botsController.BotTradersServices.BTRServices;
@ -187,6 +177,11 @@ namespace Aki.Custom.BTR
ConfigureSettingsFromServer(); ConfigureSettingsFromServer();
var btrMapConfig = btrController.MapPathsConfiguration; var btrMapConfig = btrController.MapPathsConfiguration;
if (btrMapConfig == null)
{
ConsoleScreen.LogError($"{nameof(btrController.MapPathsConfiguration)}");
return;
}
btrServerSide.CurrentPathConfig = btrMapConfig.PathsConfiguration.pathsConfigurations.RandomElement(); btrServerSide.CurrentPathConfig = btrMapConfig.PathsConfiguration.pathsConfigurations.RandomElement();
btrServerSide.Initialization(btrMapConfig); btrServerSide.Initialization(btrMapConfig);
btrController.method_14(); // creates and assigns the BTR a fake stash btrController.method_14(); // creates and assigns the BTR a fake stash
@ -213,6 +208,8 @@ namespace Aki.Custom.BTR
// Pull services data for the BTR from the server // Pull services data for the BTR from the server
TraderServicesManager.Instance.GetTraderServicesDataFromServer(BTRUtil.BTRTraderId); TraderServicesManager.Instance.GetTraderServicesDataFromServer(BTRUtil.BTRTraderId);
btrInitialized = true;
} }
private void ConfigureSettingsFromServer() private void ConfigureSettingsFromServer()
@ -249,7 +246,7 @@ namespace Aki.Custom.BTR
TraderServicesManager.Instance.RemovePurchasedService(ETraderServiceType.PlayerTaxi, BTRUtil.BTRTraderId); TraderServicesManager.Instance.RemovePurchasedService(ETraderServiceType.PlayerTaxi, BTRUtil.BTRTraderId);
// Update the prices for the taxi service // Update the prices for the taxi service
_updateTaxiPriceMethod.Invoke(btrController, new object[] { destinationPoint, isFinal }); btrController.UpdateTaxiPrice(destinationPoint, isFinal);
// Update the UI // Update the UI
TraderServicesManager.Instance.GetTraderServicesDataFromServer(BTRUtil.BTRTraderId); TraderServicesManager.Instance.GetTraderServicesDataFromServer(BTRUtil.BTRTraderId);
@ -257,14 +254,9 @@ namespace Aki.Custom.BTR
private bool IsBtrService(ETraderServiceType serviceType) private bool IsBtrService(ETraderServiceType serviceType)
{ {
if (serviceType == ETraderServiceType.BtrItemsDelivery return serviceType == ETraderServiceType.BtrItemsDelivery
|| serviceType == ETraderServiceType.PlayerTaxi || serviceType == ETraderServiceType.PlayerTaxi
|| serviceType == ETraderServiceType.BtrBotCover) || serviceType == ETraderServiceType.BtrBotCover;
{
return true;
}
return false;
} }
private void BtrTraderServicePurchased(ETraderServiceType serviceType, string subserviceId) private void BtrTraderServicePurchased(ETraderServiceType serviceType, string subserviceId)
@ -338,7 +330,7 @@ namespace Aki.Custom.BTR
} }
catch catch
{ {
ConsoleScreen.LogError("[AKI-BTR] lastInteractedBtrSide is null when it shouldn't be. Check logs."); ConsoleScreen.LogError($"[SPT-BTR] {nameof(lastInteractedBtrSide)} is null when it shouldn't be. Check logs.");
throw; throw;
} }
} }
@ -349,8 +341,8 @@ namespace Aki.Custom.BTR
btrDataPacket.rotation = btrServerSide.transform.rotation; btrDataPacket.rotation = btrServerSide.transform.rotation;
if (btrTurretServer != null && btrTurretServer.gunsBlockRoot != null) if (btrTurretServer != null && btrTurretServer.gunsBlockRoot != null)
{ {
btrDataPacket.turretRotation = btrTurretServer.transform.rotation; btrDataPacket.turretRotation = btrTurretServer.transform.localEulerAngles.y;
btrDataPacket.gunsBlockRotation = btrTurretServer.gunsBlockRoot.rotation; btrDataPacket.gunsBlockRotation = btrTurretServer.gunsBlockRoot.localEulerAngles.x;
} }
btrDataPacket.State = (byte)btrServerSide.BtrState; btrDataPacket.State = (byte)btrServerSide.BtrState;
btrDataPacket.RouteState = (byte)btrServerSide.VehicleRouteState; btrDataPacket.RouteState = (byte)btrServerSide.VehicleRouteState;
@ -390,12 +382,7 @@ namespace Aki.Custom.BTR
private bool HasTarget() private bool HasTarget()
{ {
if (currentTarget != null) return currentTarget != null;
{
return true;
}
return false;
} }
private void SetAim() private void SetAim()
@ -428,12 +415,7 @@ namespace Aki.Custom.BTR
private bool CanShoot() private bool CanShoot()
{ {
if (currentTarget.IsVisible && btrBotShooter.BotBtrData.CanShoot()) return currentTarget.IsVisible && btrBotShooter.BotBtrData.CanShoot();
{
return true;
}
return false;
} }
private void StartShooting() private void StartShooting()
@ -469,9 +451,11 @@ namespace Aki.Custom.BTR
{ {
targetHeadPos = currentTarget.Person.PlayerBones.Head.position; targetHeadPos = currentTarget.Person.PlayerBones.Head.position;
} }
Vector3 aimDirection = Vector3.Normalize(targetHeadPos - machineGunMuzzle.position); Vector3 aimDirection = Vector3.Normalize(targetHeadPos - machineGunMuzzle.position);
ballisticCalculator.Shoot(btrMachineGunAmmo, machineGunMuzzle.position, aimDirection, btrBotShooter.ProfileId, btrMachineGunWeapon, 1f, 0); ballisticCalculator.Shoot(btrMachineGunAmmo, machineGunMuzzle.position, aimDirection, btrBotShooter.ProfileId, btrMachineGunWeapon, 1f, 0);
firearmController.method_54(weaponSoundPlayer, btrMachineGunAmmo, machineGunMuzzle.position, aimDirection, false); firearmController.PlayWeaponSound(weaponSoundPlayer, btrMachineGunAmmo, machineGunMuzzle.position, aimDirection, false);
burstCount--; burstCount--;
yield return new WaitForSecondsRealtime(0.092308f); // 650 RPM yield return new WaitForSecondsRealtime(0.092308f); // 650 RPM
} }
@ -504,13 +488,13 @@ namespace Aki.Custom.BTR
if (btrClientSide != null) if (btrClientSide != null)
{ {
Debug.LogWarning("[AKI-BTR] BTRManager - Destroying btrClientSide"); Debug.LogWarning($"[SPT-BTR] {nameof(BTRManager)} - Destroying btrClientSide");
Destroy(btrClientSide.gameObject); Destroy(btrClientSide.gameObject);
} }
if (btrServerSide != null) if (btrServerSide != null)
{ {
Debug.LogWarning("[AKI-BTR] BTRManager - Destroying btrServerSide"); Debug.LogWarning($"[SPT-BTR] {nameof(BTRManager)} - Destroying btrServerSide");
Destroy(btrServerSide.gameObject); Destroy(btrServerSide.gameObject);
} }
} }

View File

@ -8,7 +8,7 @@ namespace Aki.Custom.BTR
{ {
public override bool IsStatic => false; public override bool IsStatic => false;
public override void AddPenalty(GInterface94 player) public override void AddPenalty(GInterface106 player)
{ {
} }
@ -16,7 +16,7 @@ namespace Aki.Custom.BTR
{ {
} }
public override void ProceedDamage(GInterface94 player, BodyPartCollider bodyPart) public override void ProceedDamage(GInterface106 player, BodyPartCollider bodyPart)
{ {
bodyPart.ApplyInstantKill(new DamageInfo() bodyPart.ApplyInstantKill(new DamageInfo()
{ {
@ -31,7 +31,7 @@ namespace Aki.Custom.BTR
}); });
} }
public override void RemovePenalty(GInterface94 player) public override void RemovePenalty(GInterface106 player)
{ {
} }
} }

View File

@ -6,7 +6,7 @@ using EFT.Vehicle;
using HarmonyLib; using HarmonyLib;
using System; using System;
using System.Reflection; using System.Reflection;
using BTRDialog = EFT.UI.TraderDialogScreen.GClass3132; using BTRDialog = EFT.UI.TraderDialogScreen.GClass3153;
namespace Aki.Custom.BTR.Patches namespace Aki.Custom.BTR.Patches
{ {
@ -28,12 +28,7 @@ namespace Aki.Custom.BTR.Patches
{ {
FieldInfo btrField = type.GetField("btr"); FieldInfo btrField = type.GetField("btr");
if (btrField != null && btrField.FieldType == typeof(BTRSide)) return btrField != null && btrField.FieldType == typeof(BTRSide);
{
return true;
}
return false;
} }
[PatchPrefix] [PatchPrefix]

View File

@ -60,7 +60,7 @@ namespace Aki.Custom.BTR.Patches
var valueTuple = (ValueTuple<ObservedPlayerView, bool>)_valueTuple0Field.GetValue(__instance); var valueTuple = (ValueTuple<ObservedPlayerView, bool>)_valueTuple0Field.GetValue(__instance);
if (!valueTuple.Item2 && !InitTurretView(__instance, turretPlayer)) if (!valueTuple.Item2 && !InitTurretView(__instance, turretPlayer))
{ {
Logger.LogError("[AKI-BTR] BTRBotAttachPatch - BtrBot initialization failed"); Logger.LogError("[SPT-BTR] BTRBotAttachPatch - BtrBot initialization failed");
return false; return false;
} }

View File

@ -0,0 +1,34 @@
using Aki.Reflection.Patching;
using HarmonyLib;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Aki.Custom.BTR.Patches
{
public class BTRControllerInitPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.FirstMethod(typeof(BTRControllerClass), IsTargetMethod);
}
private bool IsTargetMethod(MethodInfo method)
{
ParameterInfo[] parameters = method.GetParameters();
return method.ReturnType == typeof(Task)
&& parameters.Length == 1
&& parameters[0].ParameterType == typeof(CancellationToken);
}
[PatchPrefix]
private static bool PatchPrefix(ref Task __result)
{
// The BTRControllerClass constructor expects the original method to return a Task,
// as it calls another method on said Task.
__result = Task.CompletedTask;
return false;
}
}
}

View File

@ -11,7 +11,7 @@ namespace Aki.Custom.BTR.Patches
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(BaseLocalGame<GamePlayerOwner>), nameof(BaseLocalGame<GamePlayerOwner>.Stop)); return AccessTools.Method(typeof(BaseLocalGame<EftGamePlayerOwner>), nameof(BaseLocalGame<EftGamePlayerOwner>.Stop));
} }
[PatchPrefix] [PatchPrefix]
@ -26,7 +26,7 @@ namespace Aki.Custom.BTR.Patches
var btrManager = gameWorld.GetComponent<BTRManager>(); var btrManager = gameWorld.GetComponent<BTRManager>();
if (btrManager != null) if (btrManager != null)
{ {
Logger.LogWarning("[AKI-BTR] BTRDestroyAtRaidEndPatch - Raid Ended: Destroying BTRManager"); Logger.LogWarning("[SPT-BTR] BTRDestroyAtRaidEndPatch - Raid Ended: Destroying BTRManager");
Object.Destroy(btrManager); Object.Destroy(btrManager);
} }
} }

View File

@ -32,13 +32,13 @@ namespace Aki.Custom.BTR.Patches
GameWorld gameWorld = Singleton<GameWorld>.Instance; GameWorld gameWorld = Singleton<GameWorld>.Instance;
if (gameWorld == null) if (gameWorld == null)
{ {
Logger.LogError("[AKI-BTR] BTREndRaidItemDeliveryPatch - GameWorld is null"); Logger.LogError("[SPT-BTR] BTREndRaidItemDeliveryPatch - GameWorld is null");
return; return;
} }
var player = gameWorld.MainPlayer; var player = gameWorld.MainPlayer;
if (player == null) if (player == null)
{ {
Logger.LogError("[AKI-BTR] BTREndRaidItemDeliveryPatch - Player is null"); Logger.LogError("[SPT-BTR] BTREndRaidItemDeliveryPatch - Player is null");
return; return;
} }
@ -50,7 +50,7 @@ namespace Aki.Custom.BTR.Patches
if (!gameWorld.BtrController.HasNonEmptyTransferContainer(player.Profile.Id)) if (!gameWorld.BtrController.HasNonEmptyTransferContainer(player.Profile.Id))
{ {
Logger.LogDebug("[AKI-BTR] BTREndRaidItemDeliveryPatch - No items in transfer container"); Logger.LogDebug("[SPT-BTR] BTREndRaidItemDeliveryPatch - No items in transfer container");
return; return;
} }

View File

@ -35,7 +35,7 @@ namespace Aki.Custom.BTR.Patches
BTRView btrView = gameWorld.BtrController.BtrView; BTRView btrView = gameWorld.BtrController.BtrView;
if (btrView == null) if (btrView == null)
{ {
Logger.LogError($"[AKI-BTR] BTRExtractPassengersPatch - btrView is null"); Logger.LogError($"[SPT-BTR] BTRExtractPassengersPatch - btrView is null");
return; return;
} }

View File

@ -46,7 +46,7 @@ namespace Aki.Custom.BTR.Patches
BTRView btrView = gameWorld.BtrController.BtrView; BTRView btrView = gameWorld.BtrController.BtrView;
if (btrView == null) if (btrView == null)
{ {
Logger.LogError("[AKI-BTR] BTRInteractionPatch - btrView is null"); Logger.LogError("[SPT-BTR] BTRInteractionPatch - btrView is null");
return; return;
} }

View File

@ -19,14 +19,14 @@ namespace Aki.Custom.BTR.Patches
var gameWorld = Singleton<GameWorld>.Instance; var gameWorld = Singleton<GameWorld>.Instance;
if (gameWorld == null) if (gameWorld == null)
{ {
Logger.LogError("[AKI-BTR] BTRIsDoorsClosedPatch - GameWorld is null"); Logger.LogError("[SPT-BTR] BTRIsDoorsClosedPatch - GameWorld is null");
return true; return true;
} }
var serverSideBTR = gameWorld.BtrController.BtrVehicle; var serverSideBTR = gameWorld.BtrController.BtrVehicle;
if (serverSideBTR == null) if (serverSideBTR == null)
{ {
Logger.LogError("[AKI-BTR] BTRIsDoorsClosedPatch - serverSideBTR is null"); Logger.LogError("[SPT-BTR] BTRIsDoorsClosedPatch - serverSideBTR is null");
return true; return true;
} }

View File

@ -39,7 +39,7 @@ namespace Aki.Custom.BTR.Patches
} }
catch (System.Exception) catch (System.Exception)
{ {
ConsoleScreen.LogError("[AKI-BTR] Exception thrown, check logs."); ConsoleScreen.LogError("[SPT-BTR] Exception thrown, check logs.");
throw; throw;
} }
} }

View File

@ -0,0 +1,53 @@
using System;
using System.Reflection;
using Aki.Reflection.Patching;
using Comfort.Common;
using EFT;
using EFT.UI;
using HarmonyLib;
namespace Aki.Custom.BTR.Patches
{
/// <summary>
/// Fixes an issue where in a pathConfig.once type, finding destination path points was impossible because destinationID would be prefixed with "Map/", which the pathPoints do not contain.
/// </summary>
public class BTRPathConfigMapPrefixPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.FirstMethod(typeof(BTRControllerClass), IsTargetMethod);
}
private bool IsTargetMethod(MethodInfo method)
{
ParameterInfo[] parameters = method.GetParameters();
// BTRControllerClass.method_8
return method.ReturnType == typeof(int)
&& parameters.Length == 2
&& parameters[0].ParameterType == typeof(string)
&& parameters[0].Name == "destinationID"
&& parameters[1].ParameterType == typeof(int)
&& parameters[1].Name == "currentDestinationIndex";
}
[PatchPrefix]
private static void PatchPrefix(ref string destinationID)
{
try
{
var locationIdSlash = Singleton<GameWorld>.Instance.LocationId + "/";
if (destinationID.Contains(locationIdSlash))
{
// destinationID is in the form of "Map/pX", strip the "Map/" part.
destinationID = destinationID.Replace(locationIdSlash, "");
}
}
catch (Exception)
{
ConsoleScreen.LogError($"[SPT-BTR] Exception in {nameof(BTRPathConfigMapPrefixPatch)}, check logs.");
}
}
}
}

View File

@ -14,7 +14,16 @@ namespace Aki.Custom.BTR.Patches
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(BTRView), nameof(BTRView.method_1)); return AccessTools.FirstMethod(typeof(BTRView), IsTargetMethod);
}
private bool IsTargetMethod(MethodBase method)
{
var parameters = method.GetParameters();
return parameters.Length == 1
&& parameters[0].ParameterType == typeof(DamageInfo)
&& parameters[0].Name == "damageInfo";
} }
[PatchPrefix] [PatchPrefix]
@ -23,12 +32,15 @@ namespace Aki.Custom.BTR.Patches
var botEventHandler = Singleton<BotEventHandler>.Instance; var botEventHandler = Singleton<BotEventHandler>.Instance;
if (botEventHandler == null) if (botEventHandler == null)
{ {
Logger.LogError($"[AKI-BTR] BTRReceiveDamageInfoPatch - BotEventHandler is null"); Logger.LogError($"[SPT-BTR] {nameof(BTRReceiveDamageInfoPatch)} - BotEventHandler is null");
return; return;
} }
var shotBy = (Player)damageInfo.Player.iPlayer; var shotBy = (Player)damageInfo.Player.iPlayer;
if (shotBy != null)
{
botEventHandler.InterruptTraderServiceBtrSupportByBetrayer(shotBy); botEventHandler.InterruptTraderServiceBtrSupportByBetrayer(shotBy);
} }
} }
} }
}

View File

@ -0,0 +1,66 @@
using EFT;
using EFT.Vehicle;
using HarmonyLib;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using UnityEngine;
namespace Aki.Custom.BTR.Utils
{
public static class BTRReflectionHelper
{
private static Type _btrControllerType = typeof(BTRControllerClass);
private static Type _firearmControllerType = typeof(Player.FirearmController);
private static MethodInfo _initBtrControllerMethod = AccessTools.GetDeclaredMethods(_btrControllerType).Single(IsInitBtrControllerMethod);
private static MethodInfo _updateTaxiPriceMethod = AccessTools.GetDeclaredMethods(_btrControllerType).Single(IsUpdateTaxiPriceMethod);
private static MethodInfo _playWeaponSoundMethod = AccessTools.GetDeclaredMethods(_firearmControllerType).Single(IsPlayWeaponSoundMethod);
public static Task InitBtrController(this BTRControllerClass controller)
{
return (Task)_initBtrControllerMethod.Invoke(controller, null);
}
public static void UpdateTaxiPrice(this BTRControllerClass controller, PathDestination destinationPoint, bool isFinal)
{
_updateTaxiPriceMethod.Invoke(controller, new object[] { destinationPoint, isFinal });
}
public static void PlayWeaponSound(this Player.FirearmController controller, WeaponSoundPlayer weaponSoundPlayer, BulletClass ammo, Vector3 shotPosition, Vector3 shotDirection, bool multiShot)
{
_playWeaponSoundMethod.Invoke(controller, new object[] { weaponSoundPlayer, ammo, shotPosition, shotDirection, multiShot });
}
// Find `BTRControllerClass.method_1()`
private static bool IsInitBtrControllerMethod(MethodInfo method)
{
return method.ReturnType == typeof(Task)
&& method.GetParameters().Length == 0;
}
// Find `BTRControllerClass.method_9(PathDestination currentDestinationPoint, bool lastRoutePoint)`
private static bool IsUpdateTaxiPriceMethod(MethodInfo method)
{
ParameterInfo[] parameters = method.GetParameters();
return parameters.Length == 2
&& parameters[0].ParameterType == typeof(PathDestination);
}
// Find `Player.FirearmController.method_54(WeaponSoundPlayer weaponSoundPlayer, BulletClass ammo, Vector3 shotPosition, Vector3 shotDirection, bool multiShot)`
private static bool IsPlayWeaponSoundMethod(MethodInfo method)
{
ParameterInfo[] parameters = method.GetParameters();
return parameters.Length == 5
&& parameters[0].ParameterType == typeof(WeaponSoundPlayer)
&& parameters[1].ParameterType == typeof(BulletClass)
&& parameters[2].ParameterType == typeof(Vector3)
&& parameters[3].ParameterType == typeof(Vector3)
&& parameters[4].ParameterType == typeof(bool);
}
}
}

View File

@ -1,23 +0,0 @@
#region DEPRECATED, REMOVE IN 3.8.1
using System;
namespace Aki.Custom.Models
{
[Obsolete("BundleInfo is deprecated, please use BundleItem instead.")]
public class BundleInfo
{
public string Key { get; }
public string Path { get; set; }
public string[] DependencyKeys { get; }
public BundleInfo(string key, string path, string[] dependencyKeys)
{
Key = key;
Path = path;
DependencyKeys = dependencyKeys;
}
}
}
#endregion

View File

@ -0,0 +1,43 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Aki.Custom.Models
{
[Serializable]
public struct DifficultyInfo
{
public Dictionary<string, object> this[string key]
{
get
{
switch (key)
{
case "easy":
return easy;
case "hard":
return hard;
case "impossible":
return impossible;
case "normal":
return normal;
default:
throw new ArgumentException($"Difficulty '{key}' does not exist in DifficultyInfo.");
}
}
}
[JsonProperty("easy")]
public Dictionary<string, object> easy;
[JsonProperty("hard")]
public Dictionary<string, object> hard;
[JsonProperty("impossible")]
public Dictionary<string, object> impossible;
[JsonProperty("normal")]
public Dictionary<string, object> normal;
}
}

View File

@ -13,7 +13,7 @@ namespace Aki.SinglePlayer.Patches.MainMenu
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(TarkovApplication), nameof(TarkovApplication.method_27)); return AccessTools.Method(typeof(TarkovApplication), nameof(TarkovApplication.method_28));
} }
[PatchPrefix] [PatchPrefix]

View File

@ -1,4 +1,4 @@
using Aki.Common.Http; using Aki.Custom.Utils;
using Aki.Reflection.Patching; using Aki.Reflection.Patching;
using Aki.Reflection.Utils; using Aki.Reflection.Utils;
using EFT; using EFT;
@ -21,7 +21,7 @@ namespace Aki.Custom.Patches
[PatchPrefix] [PatchPrefix]
private static bool PatchPrefix(ref string __result, BotDifficulty botDifficulty, WildSpawnType role) private static bool PatchPrefix(ref string __result, BotDifficulty botDifficulty, WildSpawnType role)
{ {
__result = RequestHandler.GetJson($"/singleplayer/settings/bot/difficulty/{role}/{botDifficulty}"); __result = DifficultyManager.Get(botDifficulty, role);
var resultIsNullEmpty = string.IsNullOrWhiteSpace(__result); var resultIsNullEmpty = string.IsNullOrWhiteSpace(__result);
if (resultIsNullEmpty) if (resultIsNullEmpty)
{ {

View File

@ -2,6 +2,7 @@ using Aki.Reflection.Patching;
using Aki.Reflection.Utils; using Aki.Reflection.Utils;
using Aki.Common.Http; using Aki.Common.Http;
using System.Reflection; using System.Reflection;
using Aki.Custom.Utils;
namespace Aki.Custom.Patches namespace Aki.Custom.Patches
{ {
@ -19,6 +20,11 @@ namespace Aki.Custom.Patches
[PatchPrefix] [PatchPrefix]
private static bool PatchPrefix(ref string __result) private static bool PatchPrefix(ref string __result)
{ {
// fetch all bot difficulties to be used in BotDifficultyPatch
// this is called here since core difficulties are fetched before bot-specific difficulties are
DifficultyManager.Update();
// update core difficulty
__result = RequestHandler.GetJson("/singleplayer/settings/bot/difficulty/core/core"); __result = RequestHandler.GetJson("/singleplayer/settings/bot/difficulty/core/core");
return string.IsNullOrWhiteSpace(__result); return string.IsNullOrWhiteSpace(__result);
} }

View File

@ -0,0 +1,29 @@
using Aki.Common.Http;
using Aki.Reflection.Patching;
using System.Reflection;
using EFT;
using EFT.UI;
using HarmonyLib;
using UnityEngine;
using TMPro;
using System.Linq;
namespace Aki.Custom.Patches
{
public class DisablePvEPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(ChangeGameModeButton), nameof(ChangeGameModeButton.Show));
}
[PatchPrefix]
private static bool PatchPrefix(ESessionMode sessionMode, Profile profile, ref GameObject ____notAvailableState)
{
____notAvailableState.SetActive(true);
Object.FindObjectsOfType<HoverTooltipArea>().Where(o => o.name == "Locked").SingleOrDefault()?.SetMessageText("<color=#51c6db>SPT-AKI</color> is already PvE.");
return false;
}
}
}

View File

@ -12,8 +12,8 @@ using Aki.Common.Utils;
using Aki.Custom.Models; using Aki.Custom.Models;
using Aki.Custom.Utils; using Aki.Custom.Utils;
using Aki.Reflection.Patching; using Aki.Reflection.Patching;
using Aki.Reflection.Utils;
using DependencyGraph = DependencyGraph<IEasyBundle>; using DependencyGraph = DependencyGraph<IEasyBundle>;
using Aki.Reflection.Utils;
namespace Aki.Custom.Patches namespace Aki.Custom.Patches
{ {
@ -23,7 +23,7 @@ namespace Aki.Custom.Patches
static EasyAssetsPatch() static EasyAssetsPatch()
{ {
_bundlesField = typeof(EasyAssets).GetField($"{EasyBundleHelper.Type.Name.ToLowerInvariant()}_0", PatchConstants.PrivateFlags); _bundlesField = typeof(EasyAssets).GetFields(PatchConstants.PrivateFlags).FirstOrDefault(field => field.FieldType == typeof(EasyAssetHelperClass[]));
} }
public EasyAssetsPatch() public EasyAssetsPatch()

View File

@ -13,7 +13,7 @@ namespace Aki.Custom.Patches
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(BaseLocalGame<GamePlayerOwner>), nameof(BaseLocalGame<GamePlayerOwner>.Stop)); return AccessTools.Method(typeof(BaseLocalGame<EftGamePlayerOwner>), nameof(BaseLocalGame<EftGamePlayerOwner>.Stop));
} }
// Look at BaseLocalGame<TPlayerOwner> and find a method named "Stop" // Look at BaseLocalGame<TPlayerOwner> and find a method named "Stop"
@ -31,7 +31,7 @@ namespace Aki.Custom.Patches
var player = Singleton<GameWorld>.Instance.MainPlayer; var player = Singleton<GameWorld>.Instance.MainPlayer;
if (profileId == player?.Profile.Id) if (profileId == player?.Profile.Id)
{ {
GClass3107.Instance.CloseAllScreensForced(); GClass3127.Instance.CloseAllScreensForced();
} }
return true; return true;

View File

@ -12,7 +12,7 @@ namespace Aki.Custom.Patches
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
var desiredType = typeof(BaseLocalGame<GamePlayerOwner>); var desiredType = typeof(BaseLocalGame<EftGamePlayerOwner>);
var desiredMethod = desiredType.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public).SingleCustom(IsTargetMethod); // method_6 var desiredMethod = desiredType.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public).SingleCustom(IsTargetMethod); // method_6
Logger.LogDebug($"{this.GetType().Name} Type: {desiredType?.Name}"); Logger.LogDebug($"{this.GetType().Name} Type: {desiredType?.Name}");

View File

@ -17,8 +17,8 @@ namespace Aki.Custom.Patches
public RagfairFeePatch() public RagfairFeePatch()
{ {
// Remember to update prefix parameter if below lines are broken // Remember to update prefix parameter if below lines are broken
_ = nameof(GClass3069.IsAllSelectedItemSame); _ = nameof(GClass3087.IsAllSelectedItemSame);
_ = nameof(GClass3069.AutoSelectSimilar); _ = nameof(GClass3087.AutoSelectSimilar);
} }
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
@ -30,18 +30,18 @@ namespace Aki.Custom.Patches
/// Calculate tax to charge player and send to server before the offer is sent /// Calculate tax to charge player and send to server before the offer is sent
/// </summary> /// </summary>
/// <param name="___item_0">Item sold</param> /// <param name="___item_0">Item sold</param>
/// <param name="___gclass3069_0">OfferItemCount</param> /// <param name="___gclass3087_0">OfferItemCount</param>
/// <param name="___double_0">RequirementsPrice</param> /// <param name="___double_0">RequirementsPrice</param>
/// <param name="___bool_0">SellInOnePiece</param> /// <param name="___bool_0">SellInOnePiece</param>
[PatchPrefix] [PatchPrefix]
private static void PatchPrefix(ref Item ___item_0, ref GClass3069 ___gclass3069_0, ref double ___double_0, ref bool ___bool_0) private static void PatchPrefix(ref Item ___item_0, ref GClass3087 ___gclass3087_0, ref double ___double_0, ref bool ___bool_0)
{ {
RequestHandler.PutJson("/client/ragfair/offerfees", new RequestHandler.PutJson("/client/ragfair/offerfees", new
{ {
id = ___item_0.Id, id = ___item_0.Id,
tpl = ___item_0.TemplateId, tpl = ___item_0.TemplateId,
count = ___gclass3069_0.OfferItemCount, count = ___gclass3087_0.OfferItemCount,
fee = Mathf.CeilToInt((float)GClass2089.CalculateTaxPrice(___item_0, ___gclass3069_0.OfferItemCount, ___double_0, ___bool_0)) fee = Mathf.CeilToInt((float)GClass2103.CalculateTaxPrice(___item_0, ___gclass3087_0.OfferItemCount, ___double_0, ___bool_0))
}.ToJson()); }.ToJson());
} }
} }

View File

@ -10,7 +10,7 @@ namespace Aki.Custom.Patches
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(BaseLocalGame<GamePlayerOwner>), nameof(BaseLocalGame<GamePlayerOwner>.Stop)); return AccessTools.Method(typeof(BaseLocalGame<EftGamePlayerOwner>), nameof(BaseLocalGame<EftGamePlayerOwner>.Stop));
} }
[PatchPrefix] [PatchPrefix]

View File

@ -14,7 +14,7 @@ namespace Aki.Custom.Patches
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(BaseLocalGame<GamePlayerOwner>), nameof(BaseLocalGame<GamePlayerOwner>.method_5)); return AccessTools.Method(typeof(BaseLocalGame<EftGamePlayerOwner>), nameof(BaseLocalGame<EftGamePlayerOwner>.method_5));
} }
[PatchPostfix] [PatchPostfix]

View File

@ -0,0 +1,34 @@
using System.Collections.Generic;
using EFT;
using Aki.Common.Http;
using Aki.Common.Utils;
using Aki.Custom.Models;
namespace Aki.Custom.Utils
{
public static class DifficultyManager
{
public static Dictionary<string, DifficultyInfo> Difficulties { get; private set; }
static DifficultyManager()
{
Difficulties = new Dictionary<string, DifficultyInfo>();
}
public static void Update()
{
// remove existing list
Difficulties.Clear();
// get new difficulties
var json = RequestHandler.GetJson("/singleplayer/settings/bot/difficulties");
Difficulties = Json.Deserialize<Dictionary<string, DifficultyInfo>>(json);
}
public static string Get(BotDifficulty botDifficulty, WildSpawnType role)
{
var difficultyMatrix = Difficulties[role.ToString().ToLower()];
return Json.Serialize(difficultyMatrix[botDifficulty.ToString().ToLower()]);
}
}
}

View File

@ -2,13 +2,13 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net471</TargetFramework> <TargetFramework>net471</TargetFramework>
<AssemblyName>aki-debugging</AssemblyName> <AssemblyName>spt-debugging</AssemblyName>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Company>Aki</Company> <Company>SPT</Company>
<Copyright>Copyright @ Aki 2024</Copyright> <Copyright>Copyright @ SPT 2024</Copyright>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -14,7 +14,7 @@ namespace Aki.Debugging
public void Awake() public void Awake()
{ {
Logger.LogInfo("Loading: Aki.Debugging"); Logger.LogInfo("Loading: SPT.Debugging");
try try
{ {

View File

@ -5,7 +5,7 @@ using EFT;
using EFT.UI; using EFT.UI;
using HarmonyLib; using HarmonyLib;
using System.Reflection; using System.Reflection;
using DialogControlClass = GClass1957; using DialogControlClass = GClass1971;
namespace Aki.Debugging.Patches namespace Aki.Debugging.Patches
{ {

View File

@ -14,11 +14,11 @@ namespace Aki.Debugging.Patches
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(BaseLocalGame<GamePlayerOwner>), nameof(BaseLocalGame<GamePlayerOwner>.Update)); return AccessTools.Method(typeof(BaseLocalGame<EftGamePlayerOwner>), nameof(BaseLocalGame<EftGamePlayerOwner>.Update));
} }
[PatchPrefix] [PatchPrefix]
private static void PatchPrefix(BaseLocalGame<GamePlayerOwner> __instance) private static void PatchPrefix(BaseLocalGame<EftGamePlayerOwner> __instance)
{ {
if (!Input.GetKeyDown(KeyCode.LeftControl)) return; if (!Input.GetKeyDown(KeyCode.LeftControl)) return;

View File

@ -9,7 +9,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using ExitSettingsClass = GClass1225; using ExitSettingsClass = GClass1234;
namespace Aki.Debugging.Patches namespace Aki.Debugging.Patches
{ {

View File

@ -17,11 +17,11 @@ namespace Aki.Debugging.Patches
{ {
private readonly List<ISpawnPoint> playerSpawnPoints; private readonly List<ISpawnPoint> playerSpawnPoints;
private readonly Random _rnd = new Random(); private readonly Random _rnd = new Random();
private readonly GStruct380 _spawnSettings = new GStruct380(); private readonly GStruct381 _spawnSettings = new GStruct381();
public SptSpawnHelper() public SptSpawnHelper()
{ {
IEnumerable<ISpawnPoint> locationSpawnPoints = GClass2928.CreateFromScene(); IEnumerable<ISpawnPoint> locationSpawnPoints = GClass2946.CreateFromScene();
var playerSpawns = locationSpawnPoints.Where(x => x.Categories.HasFlag(ESpawnCategoryMask.Player)).ToList(); var playerSpawns = locationSpawnPoints.Where(x => x.Categories.HasFlag(ESpawnCategoryMask.Player)).ToList();
this.playerSpawnPoints = locationSpawnPoints.Where(x => x.Categories.HasFlag(ESpawnCategoryMask.Player)).ToList(); this.playerSpawnPoints = locationSpawnPoints.Where(x => x.Categories.HasFlag(ESpawnCategoryMask.Player)).ToList();
@ -62,7 +62,7 @@ namespace Aki.Debugging.Patches
} }
[PatchPrefix] [PatchPrefix]
public static bool PatchPrefix(GClass1472 __instance, GClass591 data) public static bool PatchPrefix(GClass1483 __instance, GClass591 data)
{ {
var firstBotRole = data.Profiles[0].Info.Settings.Role; var firstBotRole = data.Profiles[0].Info.Settings.Role;

View File

@ -38,7 +38,7 @@ namespace Aki.Debugging.Patches
{ {
tarkovapp.HideoutControllerAccess.UnloadHideout(); tarkovapp.HideoutControllerAccess.UnloadHideout();
} }
tarkovapp.method_48(); tarkovapp.method_49();
} }
} }
} }

View File

@ -3,13 +3,13 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net471</TargetFramework> <TargetFramework>net471</TargetFramework>
<AssemblyName>aki_PrePatch</AssemblyName> <AssemblyName>spt-prepatch</AssemblyName>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Company>Aki</Company> <Company>SPT</Company>
<Copyright>Copyright @ Aki 2024</Copyright> <Copyright>Copyright @ SPT 2024</Copyright>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -11,8 +11,8 @@ namespace Aki.PrePatch
{ {
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" }; public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
public static int sptUsecValue = 47; public static int sptUsecValue = 100;
public static int sptBearValue = 48; public static int sptBearValue = 101;
private static string _sptPluginFolder = "plugins/spt"; private static string _sptPluginFolder = "plugins/spt";
@ -86,14 +86,14 @@ namespace Aki.PrePatch
} }
// Validate that the folder exists, and contains our plugins // Validate that the folder exists, and contains our plugins
string[] sptPlugins = new string[] { "aki-core.dll", "aki-custom.dll", "aki-singleplayer.dll" }; string[] sptPlugins = new string[] { "spt-common.dll", "spt-reflection.dll", "spt-core.dll", "spt-custom.dll", "spt-singleplayer.dll" };
string[] foundPlugins = Directory.GetFiles(sptPluginPath).Select(x => Path.GetFileName(x)).ToArray(); string[] foundPlugins = Directory.GetFiles(sptPluginPath).Select(x => Path.GetFileName(x)).ToArray();
foreach (string plugin in sptPlugins) foreach (string pluginNameAndSuffix in sptPlugins)
{ {
if (!foundPlugins.Contains(plugin)) if (!foundPlugins.Contains(pluginNameAndSuffix))
{ {
message = $"Required SPT plugins missing from '{sptPluginPath}'{exitMessage}"; message = $"Required SPT plugin: {pluginNameAndSuffix} missing from '{sptPluginPath}' {exitMessage}";
logger.LogError(message); logger.LogError(message);
return false; return false;
} }

View File

@ -3,11 +3,12 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net471</TargetFramework> <TargetFramework>net471</TargetFramework>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<AssemblyName>spt-reflection</AssemblyName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Company>Aki</Company> <Company>SPT</Company>
<Copyright>Copyright @ Aki 2024</Copyright> <Copyright>Copyright @ SPT 2024</Copyright>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,13 +2,13 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net471</TargetFramework> <TargetFramework>net471</TargetFramework>
<AssemblyName>aki-singleplayer</AssemblyName> <AssemblyName>spt-singleplayer</AssemblyName>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Company>Aki</Company> <Company>SPT</Company>
<Copyright>Copyright @ Aki 2024</Copyright> <Copyright>Copyright @ SPT 2024</Copyright>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -16,7 +16,7 @@ namespace Aki.SinglePlayer
{ {
public void Awake() public void Awake()
{ {
Logger.LogInfo("Loading: Aki.SinglePlayer"); Logger.LogInfo("Loading: SPT.SinglePlayer");
try try
{ {

View File

@ -32,7 +32,7 @@ namespace Aki.SinglePlayer.Patches.MainMenu
// this.method_41(); // this.method_41();
//} //}
return AccessTools.Method(typeof(MainMenuController), nameof(MainMenuController.method_72)); return AccessTools.Method(typeof(MainMenuController), nameof(MainMenuController.method_73));
} }
[PatchPrefix] [PatchPrefix]

View File

@ -14,7 +14,7 @@ namespace Aki.SinglePlayer.Patches.Quests
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(BaseLocalGame<GamePlayerOwner>), nameof(BaseLocalGame<GamePlayerOwner>.Stop)); return AccessTools.Method(typeof(BaseLocalGame<EftGamePlayerOwner>), nameof(BaseLocalGame<EftGamePlayerOwner>.Stop));
} }
// Unused, but left here in case patch breaks and finding the intended method is difficult // Unused, but left here in case patch breaks and finding the intended method is difficult

View File

@ -32,7 +32,7 @@ namespace Aki.SinglePlayer.Patches.ScavMode
_ = MatchmakerPlayerControllerClass.MAX_SCAV_COUNT; // UPDATE REFS TO THIS CLASS BELOW !!! _ = MatchmakerPlayerControllerClass.MAX_SCAV_COUNT; // UPDATE REFS TO THIS CLASS BELOW !!!
// `MatchmakerInsuranceScreen` OnShowNextScreen // `MatchmakerInsuranceScreen` OnShowNextScreen
_onReadyScreenMethod = AccessTools.Method(typeof(MainMenuController), nameof(MainMenuController.method_43)); _onReadyScreenMethod = AccessTools.Method(typeof(MainMenuController), nameof(MainMenuController.method_44));
_isLocalField = AccessTools.Field(typeof(MainMenuController), "bool_0"); _isLocalField = AccessTools.Field(typeof(MainMenuController), "bool_0");
_menuControllerField = typeof(TarkovApplication).GetFields(PatchConstants.PrivateFlags).FirstOrDefault(x => x.FieldType == typeof(MainMenuController)); _menuControllerField = typeof(TarkovApplication).GetFields(PatchConstants.PrivateFlags).FirstOrDefault(x => x.FieldType == typeof(MainMenuController));
@ -46,65 +46,66 @@ namespace Aki.SinglePlayer.Patches.ScavMode
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
// `MatchMakerSelectionLocationScreen` OnShowNextScreen // `MatchMakerSelectionLocationScreen` OnShowNextScreen
return AccessTools.Method(typeof(MainMenuController), nameof(MainMenuController.method_69)); return AccessTools.Method(typeof(MainMenuController), nameof(MainMenuController.method_71));
} }
[PatchTranspiler] [PatchTranspiler]
private static IEnumerable<CodeInstruction> PatchTranspiler(ILGenerator generator, IEnumerable<CodeInstruction> instructions) private static IEnumerable<CodeInstruction> PatchTranspiler(ILGenerator generator, IEnumerable<CodeInstruction> instructions)
{ {
/* The original msil looks something like this:
* 0 0000 ldarg.0
* 1 0001 call instance void MainMenuController::method_69()
* 2 0006 ldarg.0
* 3 0007 call instance void MainMenuController::method_41()
* 4 000C ldarg.0
* 5 000D call instance bool MainMenuController::method_46()
* 6 0012 brtrue.s 8 (0015) ldarg.0
* 7 0014 ret
* 8 0015 ldarg.0
* 9 0016 ldfld class EFT.RaidSettings MainMenuController::raidSettings_0
* 10 001B callvirt instance bool EFT.RaidSettings::get_IsPmc()
* 11 0020 brfalse.s 15 (0029) ldarg.0
* 12 0022 ldarg.0
* 13 0023 call instance void MainMenuController::method_42()
* 14 0028 ret
* 15 0029 ldarg.0
* 16 002A call instance void MainMenuController::method_44()
* 17 002F ret
*
* The goal is to replace the call to method_44 with our own LoadOfflineRaidScreenForScav function.
* method_44 expects one argument which is the implicit "this" pointer.
* The ldarg.0 instruction loads "this" onto the stack and the function call will consume it.
* But because our own LoadOfflineRaidScreenForScav method is static
* it won't consume a "this" pointer from the stack, so we have to remove the ldarg.0 instruction.
* But the brfalse instruction at 0020 jumps to the ldarg.0, so we can not simply delete it.
* Instead, we first need to transfer the jump label from the ldarg.0 instruction to our new
* call instruction and only then we remove it.
*/
var codes = new List<CodeInstruction>(instructions); var codes = new List<CodeInstruction>(instructions);
var onReadyScreenMethodOperand = AccessTools.Method(typeof(MainMenuController), _onReadyScreenMethod.Name);
// The original method call that we want to replace var callCodeIndex = codes.FindLastIndex(code => code.opcode == OpCodes.Call
var onReadyScreenMethodIndex = -1; && (MethodInfo)code.operand == onReadyScreenMethodOperand);
var onReadyScreenMethodCode = new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(MainMenuController), _onReadyScreenMethod.Name));
// We additionally need to replace an instruction that jumps to a label on certain conditions, since we change the jump target instruction if (callCodeIndex == -1)
var jumpWhenFalse_Index = -1;
for (var i = 0; i < codes.Count; i++)
{
if (codes[i].opcode == onReadyScreenMethodCode.opcode && codes[i].operand == onReadyScreenMethodCode.operand)
{
onReadyScreenMethodIndex = i;
continue;
}
if (codes[i].opcode == OpCodes.Brfalse)
{
if (jumpWhenFalse_Index != -1)
{
// If this warning is ever logged, the condition for locating the exact brfalse instruction will have to be updated
Logger.LogWarning($"[{nameof(LoadOfflineRaidScreenPatch)}] Found extra instructions with the brfalse opcode! " +
"This breaks an old assumption that there is only one such instruction in the method body and is now very likely to cause bugs!");
}
jumpWhenFalse_Index = i;
}
}
if (onReadyScreenMethodIndex == -1)
{ {
throw new Exception($"{nameof(LoadOfflineRaidScreenPatch)} failed: Could not find {nameof(_onReadyScreenMethod)} reference code."); throw new Exception($"{nameof(LoadOfflineRaidScreenPatch)} failed: Could not find {nameof(_onReadyScreenMethod)} reference code.");
} }
if (jumpWhenFalse_Index == -1) var loadThisIndex = callCodeIndex - 1;
if (codes[loadThisIndex].opcode != OpCodes.Ldarg_0)
{ {
throw new Exception($"{nameof(LoadOfflineRaidScreenPatch)} failed: Could not find jump (brfalse) reference code."); throw new Exception($"{nameof(LoadOfflineRaidScreenPatch)} failed: Expected ldarg.0 before call instruction but found {codes[loadThisIndex]}");
} }
// Define the new jump label // Overwrite the call instruction with the call to LoadOfflineRaidScreenForScav, preserving the label for the 0020 brfalse jump
var brFalseLabel = generator.DefineLabel(); codes[callCodeIndex] = new CodeInstruction(OpCodes.Call,
AccessTools.Method(typeof(LoadOfflineRaidScreenPatch), nameof(LoadOfflineRaidScreenForScav))) {
labels = codes[loadThisIndex].labels
};
// We build the method call for our substituted method and replace the initial method call with our own, also adding our new label // Remove the ldarg.0 instruction which we no longer need because LoadOfflineRaidScreenForScav is static
var callCode = new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LoadOfflineRaidScreenPatch), nameof(LoadOfflineRaidScreenForScav))) { labels = { brFalseLabel } }; codes.RemoveAt(loadThisIndex);
codes[onReadyScreenMethodIndex] = callCode;
// We build a new brfalse instruction and give it our new label, then replace the original brfalse instruction
var newBrFalseCode = new CodeInstruction(OpCodes.Brfalse, brFalseLabel);
codes[jumpWhenFalse_Index] = newBrFalseCode;
// This will remove a stray ldarg.0 instruction. It's only needed if we wanted to reference something from `this` in the method body.
// This is done last to ensure that previous instruction indexes don't shift around (probably why this used to just turn it into a Nop OpCode)
codes.RemoveAt(onReadyScreenMethodIndex - 1);
return codes.AsEnumerable(); return codes.AsEnumerable();
} }
@ -123,12 +124,12 @@ namespace Aki.SinglePlayer.Patches.ScavMode
.Single(field => field.FieldType == typeof(MatchmakerPlayerControllerClass)) .Single(field => field.FieldType == typeof(MatchmakerPlayerControllerClass))
?.GetValue(menuController) as MatchmakerPlayerControllerClass; ?.GetValue(menuController) as MatchmakerPlayerControllerClass;
var gclass = new MatchmakerOfflineRaidScreen.GClass3155(profile?.Info, ref raidSettings, matchmakerPlayersController); var gclass = new MatchmakerOfflineRaidScreen.GClass3178(profile?.Info, ref raidSettings, matchmakerPlayersController, ESessionMode.Regular);
gclass.OnShowNextScreen += LoadOfflineRaidNextScreen; gclass.OnShowNextScreen += LoadOfflineRaidNextScreen;
// `MatchmakerOfflineRaidScreen` OnShowReadyScreen // `MatchmakerOfflineRaidScreen` OnShowReadyScreen
gclass.OnShowReadyScreen += (OfflineRaidAction)Delegate.CreateDelegate(typeof(OfflineRaidAction), menuController, nameof(MainMenuController.method_73)); gclass.OnShowReadyScreen += (OfflineRaidAction)Delegate.CreateDelegate(typeof(OfflineRaidAction), menuController, nameof(MainMenuController.method_75));
gclass.ShowScreen(EScreenState.Queued); gclass.ShowScreen(EScreenState.Queued);
} }

View File

@ -12,7 +12,7 @@ namespace Aki.SinglePlayer.Patches.ScavMode
// TODO: REMAP/UPDATE GCLASS REF // TODO: REMAP/UPDATE GCLASS REF
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(GClass1790), nameof(GClass1790.OnEnemyKill)); return AccessTools.Method(typeof(GClass1799), nameof(GClass1799.OnEnemyKill));
} }
[PatchPrefix] [PatchPrefix]

View File

@ -19,7 +19,7 @@ namespace Aki.SinglePlayer.Utils.TraderServices
gameWorld = Singleton<GameWorld>.Instance; gameWorld = Singleton<GameWorld>.Instance;
if (gameWorld == null || TraderServicesManager.Instance == null) if (gameWorld == null || TraderServicesManager.Instance == null)
{ {
logger.LogError("[AKI-LKS] GameWorld or TraderServices null"); logger.LogError("[SPT-LKS] GameWorld or TraderServices null");
Destroy(this); Destroy(this);
return; return;
} }
@ -27,7 +27,7 @@ namespace Aki.SinglePlayer.Utils.TraderServices
botsController = Singleton<IBotGame>.Instance.BotsController; botsController = Singleton<IBotGame>.Instance.BotsController;
if (botsController == null) if (botsController == null)
{ {
logger.LogError("[AKI-LKS] BotsController null"); logger.LogError("[SPT-LKS] BotsController null");
Destroy(this); Destroy(this);
return; return;
} }

View File

@ -10,9 +10,9 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
using static BackendConfigSettingsClass; using static BackendConfigSettingsClass;
using TraderServiceClass = GClass1794; using TraderServiceClass = GClass1805;
using QuestDictClass = GClass2133<string>; using QuestDictClass = GClass2145<string>;
using StandingListClass = GClass2135<float>; using StandingListClass = GClass2147<float>;
namespace Aki.SinglePlayer.Utils.TraderServices namespace Aki.SinglePlayer.Utils.TraderServices
{ {

Binary file not shown.

View File

@ -3,8 +3,6 @@ $bepinexFolder = "..\Build\BepInEx"
$bepinexPatchFolder = "..\Build\BepInEx\patchers" $bepinexPatchFolder = "..\Build\BepInEx\patchers"
$bepinexPluginFolder = "..\Build\BepInEx\plugins" $bepinexPluginFolder = "..\Build\BepInEx\plugins"
$bepinexSptFolder = "..\Build\BepInEx\plugins\spt" $bepinexSptFolder = "..\Build\BepInEx\plugins\spt"
$eftDataFolder = "..\Build\EscapeFromTarkov_Data"
$managedFolder = "..\Build\EscapeFromTarkov_Data\Managed"
$projReleaseFolder = ".\bin\Release\net471" $projReleaseFolder = ".\bin\Release\net471"
$licenseFile = "..\..\LICENSE.md" $licenseFile = "..\..\LICENSE.md"
@ -12,19 +10,19 @@ $licenseFile = "..\..\LICENSE.md"
if (Test-Path "$buildFolder") { Remove-Item -Path "$buildFolder" -Recurse -Force } if (Test-Path "$buildFolder") { Remove-Item -Path "$buildFolder" -Recurse -Force }
# Create build folder and subfolders if they don't exist # Create build folder and subfolders if they don't exist
$foldersToCreate = @("$buildFolder", "$bepinexFolder", "$bepinexPatchFolder", "$bepinexPluginFolder", "$bepinexSptFolder", "$eftDataFolder", "$managedFolder") $foldersToCreate = @("$buildFolder", "$bepinexFolder", "$bepinexPatchFolder", "$bepinexPluginFolder", "$bepinexSptFolder")
foreach ($folder in $foldersToCreate) { foreach ($folder in $foldersToCreate) {
if (-not (Test-Path "$folder")) { New-Item -Path "$folder" -ItemType Directory } if (-not (Test-Path "$folder")) { New-Item -Path "$folder" -ItemType Directory }
} }
# Move DLLs from project's bin-release folder to the build folder # Move DLLs from project's bin-release folder to the build folder
Copy-Item "$projReleaseFolder\Aki.Common.dll" -Destination "$managedFolder" Copy-Item "$projReleaseFolder\spt-common.dll" -Destination "$bepinexSptFolder"
Copy-Item "$projReleaseFolder\Aki.Reflection.dll" -Destination "$managedFolder" Copy-Item "$projReleaseFolder\spt-reflection.dll" -Destination "$bepinexSptFolder"
Copy-Item "$projReleaseFolder\aki_PrePatch.dll" -Destination "$bepinexPatchFolder" Copy-Item "$projReleaseFolder\spt-prepatch.dll" -Destination "$bepinexPatchFolder"
Copy-Item "$projReleaseFolder\aki-core.dll" -Destination "$bepinexSptFolder" Copy-Item "$projReleaseFolder\spt-core.dll" -Destination "$bepinexSptFolder"
Copy-Item "$projReleaseFolder\aki-custom.dll" -Destination "$bepinexSptFolder" Copy-Item "$projReleaseFolder\spt-custom.dll" -Destination "$bepinexSptFolder"
Copy-Item "$projReleaseFolder\aki-debugging.dll" -Destination "$bepinexSptFolder" Copy-Item "$projReleaseFolder\spt-debugging.dll" -Destination "$bepinexSptFolder"
Copy-Item "$projReleaseFolder\aki-singleplayer.dll" -Destination "$bepinexSptFolder" Copy-Item "$projReleaseFolder\spt-singleplayer.dll" -Destination "$bepinexSptFolder"
# If any new DLLs need to be copied, add here # If any new DLLs need to be copied, add here
# Write the contents of the license file to a txt # Write the contents of the license file to a txt