0
0
mirror of https://github.com/sp-tarkov/modules.git synced 2025-02-13 09:50:43 -05:00

Fixed BTR NRE at raid start, more NREs to solve (!105)

Todo:

- Fix NREs that randomly occur while the BTR is moving, relating to `ToDestinationEvent`
- Fix NRE spam upon exfiltration from raid with BTR, relating to `BTREndRaidItemDeliveryPatch`
- Enter BTR and test trader functionality

Errors were observed on Woods, not yet tested on Streets

Reviewed-on: SPT-AKI/Modules#105
Co-authored-by: Arys <arys@noreply.dev.sp-tarkov.com>
Co-committed-by: Arys <arys@noreply.dev.sp-tarkov.com>
This commit is contained in:
Arys 2024-04-05 08:10:37 +00:00 committed by chomp
parent 95edd14226
commit 9e8cdc6469
5 changed files with 106 additions and 60 deletions

View File

@ -57,6 +57,7 @@ namespace Aki.Custom
new RagfairFeePatch().Enable(); new RagfairFeePatch().Enable();
new ScavQuestPatch().Enable(); new ScavQuestPatch().Enable();
new FixBrokenSpawnOnSandboxPatch().Enable(); new FixBrokenSpawnOnSandboxPatch().Enable();
new BTRControllerConstructorPatch().Enable();
new BTRPathLoadPatch().Enable(); new BTRPathLoadPatch().Enable();
new BTRActivateTraderDialogPatch().Enable(); new BTRActivateTraderDialogPatch().Enable();
new BTRInteractionPatch().Enable(); new BTRInteractionPatch().Enable();

View File

@ -11,6 +11,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using UnityEngine; using UnityEngine;
using Random = UnityEngine.Random; using Random = UnityEngine.Random;
@ -27,6 +28,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;
@ -49,16 +51,20 @@ namespace Aki.Custom.BTR
private WeaponSoundPlayer weaponSoundPlayer; private WeaponSoundPlayer weaponSoundPlayer;
private MethodInfo _updateTaxiPriceMethod; private MethodInfo _updateTaxiPriceMethod;
private MethodInfo _playWeaponSoundMethod;
private float originalDamageCoeff; private float originalDamageCoeff;
BTRManager() BTRManager()
{ {
Type btrControllerType = typeof(BTRControllerClass); Type btrControllerType = typeof(BTRControllerClass);
_updateTaxiPriceMethod = AccessTools.GetDeclaredMethods(btrControllerType).Single(IsUpdateTaxiPriceMethod); _updateTaxiPriceMethod = AccessTools.GetDeclaredMethods(btrControllerType).Single(IsUpdateTaxiPriceMethod);
Type firearmControllerType = typeof(Player.FirearmController);
_playWeaponSoundMethod = AccessTools.GetDeclaredMethods(firearmControllerType).Single(IsPlayWeaponSoundMethod);
} }
private void Awake() private async void Awake()
{ {
try try
{ {
@ -76,7 +82,7 @@ namespace Aki.Custom.BTR
btrController = gameWorld.BtrController; btrController = gameWorld.BtrController;
InitBtr(); await InitBtr();
} }
catch catch
{ {
@ -108,7 +114,7 @@ namespace Aki.Custom.BTR
} }
else if (interactPacket.SideId == 1 && playerGoIn) else if (interactPacket.SideId == 1 && playerGoIn)
{ {
if (interactPacket.SlotId == 0) if (interactPacket.SlotId == 0)
{ {
btrServerSide.RightSlot0State = 1; btrServerSide.RightSlot0State = 1;
} }
@ -118,29 +124,45 @@ namespace Aki.Custom.BTR
} }
} }
// If the player is going into the BTR, store their damage coefficient // If the player is going into the BTR, store their damage coefficient
// and set it to 0, so they don't die while inside the BTR // and set it to 0, so they don't die while inside the BTR
if (interactPacket.InteractionType == EInteractionType.GoIn) if (interactPacket.InteractionType == EInteractionType.GoIn)
{ {
originalDamageCoeff = gameWorld.MainPlayer.ActiveHealthController.DamageCoeff; originalDamageCoeff = gameWorld.MainPlayer.ActiveHealthController.DamageCoeff;
gameWorld.MainPlayer.ActiveHealthController.SetDamageCoeff(0f); gameWorld.MainPlayer.ActiveHealthController.SetDamageCoeff(0f);
} }
// Otherwise restore the damage coefficient // Otherwise restore the damage coefficient
else if (interactPacket.InteractionType == EInteractionType.GoOut) else if (interactPacket.InteractionType == EInteractionType.GoOut)
{ {
gameWorld.MainPlayer.ActiveHealthController.SetDamageCoeff(originalDamageCoeff); gameWorld.MainPlayer.ActiveHealthController.SetDamageCoeff(originalDamageCoeff);
} }
} }
// Find `BTRControllerClass.method_9(PathDestination currentDestinationPoint, bool lastRoutePoint)` // Find `BTRControllerClass.method_9(PathDestination currentDestinationPoint, bool lastRoutePoint)`
private bool IsUpdateTaxiPriceMethod(MethodInfo method) private bool IsUpdateTaxiPriceMethod(MethodInfo method)
{ {
return (method.GetParameters().Length == 2 && method.GetParameters()[0].ParameterType == typeof(PathDestination)); ParameterInfo[] parameters = method.GetParameters();
return parameters.Length == 2 && parameters[0].ParameterType == typeof(PathDestination);
}
private 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);
} }
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 +191,11 @@ namespace Aki.Custom.BTR
} }
} }
private void InitBtr() private async Task InitBtr()
{ {
// Initial setup // Initial setup
await btrController.method_1();
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 +211,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 +242,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()
@ -257,14 +288,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 +364,7 @@ namespace Aki.Custom.BTR
} }
catch catch
{ {
ConsoleScreen.LogError("[AKI-BTR] lastInteractedBtrSide is null when it shouldn't be. Check logs."); ConsoleScreen.LogError($"[AKI-BTR] {nameof(lastInteractedBtrSide)} is null when it shouldn't be. Check logs.");
throw; throw;
} }
} }
@ -390,12 +416,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 +449,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 +485,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); _playWeaponSoundMethod.Invoke(firearmController, new object[] { 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 +522,13 @@ namespace Aki.Custom.BTR
if (btrClientSide != null) if (btrClientSide != null)
{ {
Debug.LogWarning("[AKI-BTR] BTRManager - Destroying btrClientSide"); Debug.LogWarning($"[AKI-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($"[AKI-BTR] {nameof(BTRManager)} - Destroying btrServerSide");
Destroy(btrServerSide.gameObject); Destroy(btrServerSide.gameObject);
} }
} }

View File

@ -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

@ -0,0 +1,20 @@
using Aki.Reflection.Patching;
using HarmonyLib;
using System.Reflection;
namespace Aki.Custom.BTR.Patches
{
public class BTRControllerConstructorPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.GetDeclaredConstructors(typeof(BTRControllerClass))[0];
}
[PatchPrefix]
private static bool PatchPrefix()
{
return false; // We don't want the original constructor to run
}
}
}

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($"[AKI-BTR] {nameof(BTRReceiveDamageInfoPatch)} - BotEventHandler is null");
return; return;
} }
var shotBy = (Player)damageInfo.Player.iPlayer; var shotBy = (Player)damageInfo.Player;
botEventHandler.InterruptTraderServiceBtrSupportByBetrayer(shotBy); if (shotBy != null)
{
botEventHandler.InterruptTraderServiceBtrSupportByBetrayer(shotBy);
}
} }
} }
} }