mirror of
https://github.com/sp-tarkov/modules.git
synced 2025-02-13 02:50:45 -05:00
Shooting the BTR will make it retaliate. Fixed BTR turret from rotating when non-hostile (!56)
Todo: * Make the UI notifications for BTR-related stuff appear, e.g. when BTR is about to depart * Prevent player from entering BTR when it is hostile to the player * Implement cover fire trader service * Finish implementation of taxi service * Finetune the turret machine gun shooting (it might need some pauses as it will shoot nonstop if it is aiming at you) Co-authored-by: Nympfonic <arys.steam@gmail.com> Reviewed-on: SPT-AKI/Modules#56 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
b82ef6dd30
commit
0cabe9dc12
@ -41,7 +41,7 @@ namespace Aki.Custom.Patches
|
||||
[PatchPrefix]
|
||||
private static bool PatchPrefix(ref bool __result, BotsGroup __instance, IPlayer requester)
|
||||
{
|
||||
if (__instance.InitialBotType == WildSpawnType.peacefullZryachiyEvent)
|
||||
if (__instance.InitialBotType == WildSpawnType.peacefullZryachiyEvent || __instance.InitialBotType == WildSpawnType.shooterBTR)
|
||||
{
|
||||
return true; // Do original code
|
||||
}
|
||||
|
@ -24,6 +24,9 @@ namespace Aki.Debugging
|
||||
new BTRExtractPassengersPatch().Enable();
|
||||
new BTRBotAttachPatch().Enable();
|
||||
new BTRBotInitPatch().Enable();
|
||||
new BTRReceiveDamageInfoPatch().Enable();
|
||||
new BTRTurretCanShootPatch().Enable();
|
||||
new BTRTurretDefaultAimingPositionPatch().Enable();
|
||||
new BTRIsDoorsClosedPath().Enable();
|
||||
new BTRPatch().Enable();
|
||||
new BTRTransferItemsPatch().Enable();
|
||||
|
@ -1,9 +1,11 @@
|
||||
using Aki.Debugging.BTR.Utils;
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.InventoryLogic;
|
||||
using EFT.Vehicle;
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@ -20,6 +22,7 @@ namespace Aki.Debugging.BTR
|
||||
private BTRControllerClass btrController;
|
||||
private BTRVehicle btrServerSide;
|
||||
private BTRView btrClientSide;
|
||||
private BotOwner btrBotShooter;
|
||||
private BTRDataPacket btrDataPacket = default;
|
||||
private bool btrBotShooterInitialized = false;
|
||||
|
||||
@ -27,6 +30,13 @@ namespace Aki.Debugging.BTR
|
||||
private BTRSide lastInteractedBtrSide;
|
||||
public BTRSide LastInteractedBtrSide => lastInteractedBtrSide;
|
||||
|
||||
private BTRTurretServer btrTurretServer;
|
||||
private Transform btrTurretDefaultTargetTransform;
|
||||
private Coroutine _shootingTargetCoroutine;
|
||||
private bool isShooting = false;
|
||||
private BulletClass btrMachineGunAmmo;
|
||||
private Item btrMachineGunWeapon;
|
||||
|
||||
private MethodInfo _updateTaxiPriceMethod;
|
||||
|
||||
private Dictionary<ETraderServiceType, Dictionary<string, bool>> ServicePurchasedDict { get; set; }
|
||||
@ -91,9 +101,6 @@ namespace Aki.Debugging.BTR
|
||||
gameWorld.BtrController = btrController = Singleton<BTRControllerClass>.Instance;
|
||||
}
|
||||
|
||||
botsController = Singleton<IBotGame>.Instance.BotsController;
|
||||
btrBotService = botsController.BotTradersServices.BTRServices;
|
||||
|
||||
InitBTR();
|
||||
}
|
||||
catch
|
||||
@ -111,11 +118,17 @@ namespace Aki.Debugging.BTR
|
||||
// BotShooterBtr doesn't get assigned to BtrController immediately so we nullcheck this in Update
|
||||
if (btrController.BotShooterBtr != null && !btrBotShooterInitialized)
|
||||
{
|
||||
btrBotShooter = btrController.BotShooterBtr;
|
||||
btrBotService.Reset(); // Player will be added to Neutrals list and removed from Enemies list
|
||||
btrBotShooterInitialized = true;
|
||||
}
|
||||
|
||||
AimAtEnemy();
|
||||
if (btrController.BotShooterBtr == null) return;
|
||||
|
||||
if (IsAimingAtTarget() && !isShooting)
|
||||
{
|
||||
_shootingTargetCoroutine = StaticManager.BeginCoroutine(ShootTarget());
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleBtrDoorState(EPlayerBtrState playerBtrState)
|
||||
@ -172,10 +185,14 @@ namespace Aki.Debugging.BTR
|
||||
|
||||
private void InitBTR()
|
||||
{
|
||||
// Initial setup
|
||||
botsController = Singleton<IBotGame>.Instance.BotsController;
|
||||
btrBotService = botsController.BotTradersServices.BTRServices;
|
||||
var btrControllerType = btrController.GetType();
|
||||
AccessTools.Method(btrControllerType, "method_3").Invoke(btrController, null); // spawns server-side BTR game object
|
||||
botsController.BotSpawner.SpawnBotBTR(); // spawns the scav bot which controls the BTR's turret
|
||||
|
||||
// Initial BTR configuration
|
||||
btrServerSide = btrController.BtrVehicle;
|
||||
btrServerSide.moveSpeed = 20f;
|
||||
var btrMapConfig = btrController.MapPathsConfiguration;
|
||||
@ -190,11 +207,18 @@ namespace Aki.Debugging.BTR
|
||||
btrServerSide.MoveEnable();
|
||||
btrServerSide.IncomingToDestinationEvent += ToDestinationEvent;
|
||||
|
||||
// Sync initial position and rotation
|
||||
UpdateDataPacket();
|
||||
btrClientSide = btrController.BtrView;
|
||||
btrClientSide.transform.position = btrDataPacket.position;
|
||||
btrClientSide.transform.rotation = btrDataPacket.rotation;
|
||||
|
||||
// Initialise turret variables
|
||||
btrTurretServer = btrServerSide.BTRTurret;
|
||||
btrTurretDefaultTargetTransform = (Transform)AccessTools.Field(btrTurretServer.GetType(), "defaultTargetTransform").GetValue(btrTurretServer);
|
||||
btrMachineGunAmmo = (BulletClass)BTRUtil.CreateItem(BTRUtil.BTRMachineGunAmmoTplId);
|
||||
btrMachineGunWeapon = BTRUtil.CreateItem(BTRUtil.BTRMachineGunWeaponTplId);
|
||||
|
||||
// Pull services data for the BTR from the server
|
||||
BTRUtil.PopulateTraderServicesData(BTRUtil.BTRTraderId);
|
||||
}
|
||||
@ -233,10 +257,10 @@ namespace Aki.Debugging.BTR
|
||||
{
|
||||
btrDataPacket.position = btrServerSide.transform.position;
|
||||
btrDataPacket.rotation = btrServerSide.transform.rotation;
|
||||
if (btrServerSide.BTRTurret?.gunsBlockRoot != null)
|
||||
if (btrTurretServer?.gunsBlockRoot != null)
|
||||
{
|
||||
btrDataPacket.turretRotation = btrServerSide.BTRTurret.transform.rotation;
|
||||
btrDataPacket.gunsBlockRotation = btrServerSide.BTRTurret.gunsBlockRoot.rotation;
|
||||
btrDataPacket.turretRotation = btrTurretServer.transform.rotation;
|
||||
btrDataPacket.gunsBlockRotation = btrTurretServer.gunsBlockRoot.rotation;
|
||||
}
|
||||
btrDataPacket.State = (byte)btrServerSide.BtrState;
|
||||
btrDataPacket.RouteState = (byte)btrServerSide.VehicleRouteState;
|
||||
@ -267,23 +291,76 @@ namespace Aki.Debugging.BTR
|
||||
}
|
||||
}
|
||||
|
||||
private void AimAtEnemy()
|
||||
private bool IsAimingAtTarget()
|
||||
{
|
||||
if (btrController.BotShooterBtr == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var turretInDefaultRotation = btrTurretServer.targetTransform == btrTurretDefaultTargetTransform
|
||||
&& btrTurretServer.targetPosition == btrTurretServer.defaultAimingPosition;
|
||||
|
||||
var btrTurret = btrServerSide.BTRTurret;
|
||||
var enemies = btrController.BotShooterBtr.BotsGroup.Enemies;
|
||||
var enemies = btrBotShooter.BotsGroup.Enemies;
|
||||
if (enemies.Any())
|
||||
{
|
||||
btrTurret.EnableAimingObject(enemies.First().Key.Transform.Original);
|
||||
IPlayer currentTarget = enemies.First().Key;
|
||||
Transform currentTargetTransform = currentTarget.Transform.Original;
|
||||
Vector3 currentTargetPosition = currentTargetTransform.position;
|
||||
var currentTargetInfo = btrBotShooter.EnemiesController.EnemyInfos[currentTarget];
|
||||
|
||||
if (!currentTarget.HealthController.IsAlive)
|
||||
{
|
||||
enemies.Remove(currentTarget);
|
||||
}
|
||||
|
||||
if (currentTargetInfo.IsVisible)
|
||||
{
|
||||
if (btrTurretServer.CheckPositionInAimingZone(currentTargetPosition))
|
||||
{
|
||||
btrTurretServer.EnableAimingObject(currentTargetTransform);
|
||||
}
|
||||
// If turret machine gun aim is close enough to target and has line of sight
|
||||
if (btrBotShooter.BotBtrData.CanShoot())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (!currentTargetInfo.IsVisible)
|
||||
{
|
||||
// Turret will hold the angle where target was last seen for 3 seconds before resetting its rotation
|
||||
if (btrTurretServer.targetPosition != currentTargetInfo.EnemyLastPosition && btrTurretServer.targetTransform != null)
|
||||
{
|
||||
btrTurretServer.EnableAimingPosition(currentTargetInfo.EnemyLastPosition);
|
||||
}
|
||||
else if (currentTargetInfo.TimeLastSeen >= 3f && !turretInDefaultRotation)
|
||||
{
|
||||
btrTurretServer.DisableAiming();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!enemies.Any() && !turretInDefaultRotation)
|
||||
{
|
||||
btrTurret.DisableAiming();
|
||||
btrTurretServer.DisableAiming();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom method to make the BTR coaxial machine gun shoot.
|
||||
/// </summary>
|
||||
private IEnumerator ShootTarget()
|
||||
{
|
||||
isShooting = true;
|
||||
|
||||
Transform machineGunMuzzle = btrTurretServer.machineGunLaunchPoint;
|
||||
Player btrBotPlayer = btrBotShooter.GetPlayer;
|
||||
|
||||
gameWorld.SharedBallisticsCalculator.Shoot(btrMachineGunAmmo, machineGunMuzzle.position, machineGunMuzzle.forward, btrBotPlayer.ProfileId, btrMachineGunWeapon, 1f, 0);
|
||||
|
||||
Player.FirearmController firearmController = btrBotShooter.GetComponent<Player.FirearmController>();
|
||||
WeaponPrefab weaponPrefab = (WeaponPrefab)AccessTools.Field(firearmController.GetType(), "weaponPrefab_0").GetValue(firearmController);
|
||||
WeaponSoundPlayer weaponSoundPlayer = weaponPrefab.GetComponent<WeaponSoundPlayer>();
|
||||
AccessTools.Method(firearmController.GetType(), "method_54").Invoke(firearmController, new object[] { weaponSoundPlayer, btrMachineGunAmmo, machineGunMuzzle.position, machineGunMuzzle.forward, false });
|
||||
|
||||
yield return new WaitForSecondsRealtime(0.092308f); // 650 RPM
|
||||
isShooting = false;
|
||||
}
|
||||
|
||||
private void DestroyGameObjects()
|
||||
@ -306,6 +383,8 @@ namespace Aki.Debugging.BTR
|
||||
{
|
||||
gameWorld.MainPlayer.OnBtrStateChanged -= HandleBtrDoorState;
|
||||
}
|
||||
|
||||
StaticManager.KillCoroutine(ref _shootingTargetCoroutine);
|
||||
Destroy(this);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
using Aki.Reflection.Patching;
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.Vehicle;
|
||||
using HarmonyLib;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Aki.Debugging.BTR.Patches
|
||||
{
|
||||
/// <summary>
|
||||
/// Patches an empty method in <see cref="BTRView"/> to handle updating the BTR bot's Neutrals and Enemies lists in response to taking damage.
|
||||
/// </summary>
|
||||
public class BTRReceiveDamageInfoPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(BTRView), "method_1");
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static void PatchPrefix(DamageInfo damageInfo)
|
||||
{
|
||||
var globalEvents = Singleton<GClass595>.Instance;
|
||||
if (globalEvents == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var shotBy = (Player)damageInfo.Player.iPlayer;
|
||||
globalEvents.InterruptTraderServiceBtrSupportByBetrayer(shotBy);
|
||||
}
|
||||
}
|
||||
}
|
31
project/Aki.Debugging/BTR/Patches/BTRTurretCanShootPatch.cs
Normal file
31
project/Aki.Debugging/BTR/Patches/BTRTurretCanShootPatch.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Aki.Reflection.Patching;
|
||||
using EFT.Vehicle;
|
||||
using HarmonyLib;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Aki.Debugging.BTR.Patches
|
||||
{
|
||||
public class BTRTurretCanShootPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(BTRTurretServer), "method_1");
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static bool PatchPrefix(BTRTurretServer __instance)
|
||||
{
|
||||
Transform defaultTargetTransform = (Transform)AccessTools.Field(__instance.GetType(), "defaultTargetTransform").GetValue(__instance);
|
||||
|
||||
bool flag = __instance.targetTransform != null && __instance.targetTransform != defaultTargetTransform;
|
||||
bool flag2 = (bool)AccessTools.Method(__instance.GetType(), "method_2").Invoke(__instance, null);
|
||||
bool flag3 = __instance.targetPosition != __instance.defaultAimingPosition;
|
||||
|
||||
var isCanShootProperty = AccessTools.DeclaredProperty(__instance.GetType(), nameof(__instance.IsCanShoot));
|
||||
isCanShootProperty.SetValue(__instance, (flag || flag3) && flag2);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
using Aki.Reflection.Patching;
|
||||
using EFT.Vehicle;
|
||||
using HarmonyLib;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Aki.Debugging.BTR.Patches
|
||||
{
|
||||
public class BTRTurretDefaultAimingPositionPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(BTRTurretServer), "Start");
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static bool PatchPrefix(BTRTurretServer __instance)
|
||||
{
|
||||
__instance.defaultAimingPosition = Vector3.zero;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,8 +2,10 @@
|
||||
using Aki.Debugging.BTR.Models;
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.InventoryLogic;
|
||||
using HarmonyLib;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
@ -15,6 +17,8 @@ namespace Aki.Debugging.BTR.Utils
|
||||
public static class BTRUtil
|
||||
{
|
||||
public static readonly string BTRTraderId = Profile.TraderInfo.BTR_TRADER_ID;
|
||||
public static readonly string BTRMachineGunWeaponTplId = "657857faeff4c850222dff1b"; // BTR PKTM machine gun
|
||||
public static readonly string BTRMachineGunAmmoTplId = "5e023d34e8a400319a28ed44"; // 7.62x54mmR BT
|
||||
|
||||
private static FieldInfo _traderAvailableServicesField = AccessTools.Field(typeof(Profile.TraderInfo), "_availableServices");
|
||||
|
||||
@ -145,5 +149,14 @@ namespace Aki.Debugging.BTR.Utils
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to create an instance of the item in-raid.
|
||||
/// </summary>
|
||||
public static Item CreateItem(string tplId)
|
||||
{
|
||||
var id = Guid.NewGuid().ToString("N").Substring(0, 24);
|
||||
return Singleton<ItemFactory>.Instance.CreateItem(id, tplId, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user