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 ScavQuestPatch().Enable();
new FixBrokenSpawnOnSandboxPatch().Enable();
new BTRControllerConstructorPatch().Enable();
new BTRPathLoadPatch().Enable();
new BTRActivateTraderDialogPatch().Enable();
new BTRInteractionPatch().Enable();

View File

@ -11,6 +11,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using UnityEngine;
using Random = UnityEngine.Random;
@ -27,6 +28,7 @@ namespace Aki.Custom.BTR
private BTRView btrClientSide;
private BotOwner btrBotShooter;
private BTRDataPacket btrDataPacket = default;
private bool btrInitialized = false;
private bool btrBotShooterInitialized = false;
private float coverFireTime = 90f;
@ -49,16 +51,20 @@ namespace Aki.Custom.BTR
private WeaponSoundPlayer weaponSoundPlayer;
private MethodInfo _updateTaxiPriceMethod;
private MethodInfo _playWeaponSoundMethod;
private float originalDamageCoeff;
private float originalDamageCoeff;
BTRManager()
BTRManager()
{
Type btrControllerType = typeof(BTRControllerClass);
_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
{
@ -76,7 +82,7 @@ namespace Aki.Custom.BTR
btrController = gameWorld.BtrController;
InitBtr();
await InitBtr();
}
catch
{
@ -108,7 +114,7 @@ namespace Aki.Custom.BTR
}
else if (interactPacket.SideId == 1 && playerGoIn)
{
if (interactPacket.SlotId == 0)
if (interactPacket.SlotId == 0)
{
btrServerSide.RightSlot0State = 1;
}
@ -118,29 +124,45 @@ namespace Aki.Custom.BTR
}
}
// 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
if (interactPacket.InteractionType == EInteractionType.GoIn)
{
originalDamageCoeff = gameWorld.MainPlayer.ActiveHealthController.DamageCoeff;
gameWorld.MainPlayer.ActiveHealthController.SetDamageCoeff(0f);
// 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
if (interactPacket.InteractionType == EInteractionType.GoIn)
{
originalDamageCoeff = gameWorld.MainPlayer.ActiveHealthController.DamageCoeff;
gameWorld.MainPlayer.ActiveHealthController.SetDamageCoeff(0f);
}
// Otherwise restore the damage coefficient
else if (interactPacket.InteractionType == EInteractionType.GoOut)
{
gameWorld.MainPlayer.ActiveHealthController.SetDamageCoeff(originalDamageCoeff);
}
}
}
// Otherwise restore the damage coefficient
else if (interactPacket.InteractionType == EInteractionType.GoOut)
{
gameWorld.MainPlayer.ActiveHealthController.SetDamageCoeff(originalDamageCoeff);
}
}
// Find `BTRControllerClass.method_9(PathDestination currentDestinationPoint, bool lastRoutePoint)`
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()
{
if (!btrInitialized) return;
btrController.SyncBTRVehicleFromServer(UpdateDataPacket());
if (btrController.BotShooterBtr == null) return;
@ -169,9 +191,11 @@ namespace Aki.Custom.BTR
}
}
private void InitBtr()
private async Task InitBtr()
{
// Initial setup
await btrController.method_1();
botEventHandler = Singleton<BotEventHandler>.Instance;
var botsController = Singleton<IBotGame>.Instance.BotsController;
btrBotService = botsController.BotTradersServices.BTRServices;
@ -187,6 +211,11 @@ namespace Aki.Custom.BTR
ConfigureSettingsFromServer();
var btrMapConfig = btrController.MapPathsConfiguration;
if (btrMapConfig == null)
{
ConsoleScreen.LogError($"{nameof(btrController.MapPathsConfiguration)}");
return;
}
btrServerSide.CurrentPathConfig = btrMapConfig.PathsConfiguration.pathsConfigurations.RandomElement();
btrServerSide.Initialization(btrMapConfig);
btrController.method_14(); // creates and assigns the BTR a fake stash
@ -206,13 +235,15 @@ namespace Aki.Custom.BTR
// Initialise turret variables
btrTurretServer = btrServerSide.BTRTurret;
var btrTurretDefaultTargetTransform = (Transform)AccessTools.Field(btrTurretServer.GetType(), "defaultTargetTransform").GetValue(btrTurretServer);
isTurretInDefaultRotation = btrTurretServer.targetTransform == btrTurretDefaultTargetTransform
isTurretInDefaultRotation = btrTurretServer.targetTransform == btrTurretDefaultTargetTransform
&& btrTurretServer.targetPosition == btrTurretServer.defaultAimingPosition;
btrMachineGunAmmo = (BulletClass)BTRUtil.CreateItem(BTRUtil.BTRMachineGunAmmoTplId);
btrMachineGunWeapon = BTRUtil.CreateItem(BTRUtil.BTRMachineGunWeaponTplId);
// Pull services data for the BTR from the server
TraderServicesManager.Instance.GetTraderServicesDataFromServer(BTRUtil.BTRTraderId);
btrInitialized = true;
}
private void ConfigureSettingsFromServer()
@ -257,14 +288,9 @@ namespace Aki.Custom.BTR
private bool IsBtrService(ETraderServiceType serviceType)
{
if (serviceType == ETraderServiceType.BtrItemsDelivery
|| serviceType == ETraderServiceType.PlayerTaxi
|| serviceType == ETraderServiceType.BtrBotCover)
{
return true;
}
return false;
return serviceType == ETraderServiceType.BtrItemsDelivery
|| serviceType == ETraderServiceType.PlayerTaxi
|| serviceType == ETraderServiceType.BtrBotCover;
}
private void BtrTraderServicePurchased(ETraderServiceType serviceType, string subserviceId)
@ -338,7 +364,7 @@ namespace Aki.Custom.BTR
}
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;
}
}
@ -390,16 +416,11 @@ namespace Aki.Custom.BTR
private bool HasTarget()
{
if (currentTarget != null)
{
return true;
}
return false;
return currentTarget != null;
}
private void SetAim()
{
{
if (currentTarget.IsVisible)
{
Vector3 targetPos = currentTarget.CurrPosition;
@ -412,8 +433,8 @@ namespace Aki.Custom.BTR
else
{
Vector3 targetLastPos = currentTarget.EnemyLastPositionReal;
if (btrTurretServer.CheckPositionInAimingZone(targetLastPos)
&& Time.time - currentTarget.PersonalLastSeenTime < 3f
if (btrTurretServer.CheckPositionInAimingZone(targetLastPos)
&& Time.time - currentTarget.PersonalLastSeenTime < 3f
&& btrTurretServer.targetPosition != targetLastPos)
{
btrTurretServer.EnableAimingPosition(targetLastPos);
@ -428,12 +449,7 @@ namespace Aki.Custom.BTR
private bool CanShoot()
{
if (currentTarget.IsVisible && btrBotShooter.BotBtrData.CanShoot())
{
return true;
}
return false;
return currentTarget.IsVisible && btrBotShooter.BotBtrData.CanShoot();
}
private void StartShooting()
@ -469,16 +485,18 @@ namespace Aki.Custom.BTR
{
targetHeadPos = currentTarget.Person.PlayerBones.Head.position;
}
Vector3 aimDirection = Vector3.Normalize(targetHeadPos - machineGunMuzzle.position);
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--;
yield return new WaitForSecondsRealtime(0.092308f); // 650 RPM
}
float waitTime = Random.Range(machineGunRecoveryTime.x, machineGunRecoveryTime.y);
yield return new WaitForSecondsRealtime(waitTime);
isShooting = false;
}
@ -504,13 +522,13 @@ namespace Aki.Custom.BTR
if (btrClientSide != null)
{
Debug.LogWarning("[AKI-BTR] BTRManager - Destroying btrClientSide");
Debug.LogWarning($"[AKI-BTR] {nameof(BTRManager)} - Destroying btrClientSide");
Destroy(btrClientSide.gameObject);
}
if (btrServerSide != null)
{
Debug.LogWarning("[AKI-BTR] BTRManager - Destroying btrServerSide");
Debug.LogWarning($"[AKI-BTR] {nameof(BTRManager)} - Destroying btrServerSide");
Destroy(btrServerSide.gameObject);
}
}

View File

@ -28,12 +28,7 @@ namespace Aki.Custom.BTR.Patches
{
FieldInfo btrField = type.GetField("btr");
if (btrField != null && btrField.FieldType == typeof(BTRSide))
{
return true;
}
return false;
return btrField != null && btrField.FieldType == typeof(BTRSide);
}
[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()
{
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]
@ -23,12 +32,15 @@ namespace Aki.Custom.BTR.Patches
var botEventHandler = Singleton<BotEventHandler>.Instance;
if (botEventHandler == null)
{
Logger.LogError($"[AKI-BTR] BTRReceiveDamageInfoPatch - BotEventHandler is null");
Logger.LogError($"[AKI-BTR] {nameof(BTRReceiveDamageInfoPatch)} - BotEventHandler is null");
return;
}
var shotBy = (Player)damageInfo.Player.iPlayer;
botEventHandler.InterruptTraderServiceBtrSupportByBetrayer(shotBy);
var shotBy = (Player)damageInfo.Player;
if (shotBy != null)
{
botEventHandler.InterruptTraderServiceBtrSupportByBetrayer(shotBy);
}
}
}
}