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:
parent
95edd14226
commit
9e8cdc6469
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user