mirror of
https://github.com/sp-tarkov/modules.git
synced 2025-02-13 03:30:44 -05:00
BTR Progress Update (!50)
Current progress: * BTR spawns in, clientside BTR is synced with serverside BTR * BTR Bot spawns in, is assigned to BTRController (GClass2911) correctly * BTR Bot is initialized properly (invisible, makes no sound, doesn't shoot at player) Todo: BTR is currently missing functionality * It needs to allow player to enter and exit * Player should be able to interact with BTR driver/open BTR stash UI/pay money to get taxi'd to a chosen location/pay money for it to provide covering fire * Turret should rotate to shoot player if they attack it * It should be able to drive on its own from raid start, going from location to location, on a set path Co-authored-by: Nympfonic <arys.steam@gmail.com> Reviewed-on: SPT-AKI/Modules#50 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
a31f19755f
commit
e4f91a58e4
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Aki.Common;
|
using Aki.Common;
|
||||||
|
using Aki.Debugging.BTR.Patches;
|
||||||
using Aki.Debugging.Patches;
|
using Aki.Debugging.Patches;
|
||||||
using BepInEx;
|
using BepInEx;
|
||||||
|
|
||||||
@ -16,8 +17,10 @@ namespace Aki.Debugging
|
|||||||
{
|
{
|
||||||
new EndRaidDebug().Enable();
|
new EndRaidDebug().Enable();
|
||||||
// new CoordinatesPatch().Enable();
|
// new CoordinatesPatch().Enable();
|
||||||
// new StaticLootDumper().Enable();
|
// new StaticLootDumper().Enable();
|
||||||
new BtrTestPatch().Enable();
|
new BTRBotAttachPatch().Enable();
|
||||||
|
new BTRBotInitPatch().Enable();
|
||||||
|
new BTRPatch().Enable();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
128
project/Aki.Debugging/BTR/BTRManager.cs
Normal file
128
project/Aki.Debugging/BTR/BTRManager.cs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
using Comfort.Common;
|
||||||
|
using EFT;
|
||||||
|
using EFT.Vehicle;
|
||||||
|
using HarmonyLib;
|
||||||
|
using UnityEngine;
|
||||||
|
using BTRController = GClass2911;
|
||||||
|
using BTRDataPacket = GStruct378;
|
||||||
|
|
||||||
|
namespace Aki.Debugging.BTR
|
||||||
|
{
|
||||||
|
public class BTRManager : MonoBehaviour
|
||||||
|
{
|
||||||
|
private BTRController btrController;
|
||||||
|
private BTRVehicle serverSideBtr;
|
||||||
|
private BTRView clientSideBtr;
|
||||||
|
private BTRDataPacket btrDataPacket = default;
|
||||||
|
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
|
|
||||||
|
if (gameWorld == null)
|
||||||
|
{
|
||||||
|
Destroy(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameWorld.BtrController == null)
|
||||||
|
{
|
||||||
|
if (!Singleton<BTRController>.Instantiated)
|
||||||
|
{
|
||||||
|
Singleton<BTRController>.Create(new BTRController());
|
||||||
|
}
|
||||||
|
|
||||||
|
gameWorld.BtrController = btrController = Singleton<BTRController>.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
var btrControllerType = btrController.GetType();
|
||||||
|
AccessTools.Method(btrControllerType, "method_3").Invoke(btrController, null); // spawns server-side BTR game object
|
||||||
|
Singleton<IBotGame>.Instance.BotsController.BotSpawner.SpawnBotBTR(); // spawns the scav bot which controls the BTR's turret
|
||||||
|
|
||||||
|
serverSideBtr = btrController.BtrVehicle;
|
||||||
|
serverSideBtr.moveSpeed = 20f;
|
||||||
|
var btrMapConfig = btrController.MapPathsConfiguration;
|
||||||
|
serverSideBtr.CurrentPathConfig = btrMapConfig.PathsConfiguration.pathsConfigurations.RandomElement();
|
||||||
|
serverSideBtr.Initialization(btrMapConfig);
|
||||||
|
AccessTools.Method(btrControllerType, "method_14").Invoke(btrController, null); // creates and assigns the BTR a fake stash
|
||||||
|
|
||||||
|
clientSideBtr = btrController.BtrView;
|
||||||
|
|
||||||
|
UpdateDataPacket();
|
||||||
|
clientSideBtr.transform.position = btrDataPacket.position;
|
||||||
|
clientSideBtr.transform.rotation = btrDataPacket.rotation;
|
||||||
|
|
||||||
|
DisableServerSideRenderers();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Debug.LogError("[AKI-BTR]: Unable to spawn BTR");
|
||||||
|
DestroyGameObjects();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
btrController.SyncBTRVehicleFromServer(UpdateDataPacket());
|
||||||
|
}
|
||||||
|
|
||||||
|
private BTRDataPacket UpdateDataPacket()
|
||||||
|
{
|
||||||
|
btrDataPacket.position = serverSideBtr.transform.position;
|
||||||
|
btrDataPacket.rotation = serverSideBtr.transform.rotation;
|
||||||
|
if (serverSideBtr.BTRTurret?.gunsBlockRoot != null)
|
||||||
|
{
|
||||||
|
btrDataPacket.turretRotation = serverSideBtr.BTRTurret.transform.rotation;
|
||||||
|
btrDataPacket.gunsBlockRotation = serverSideBtr.BTRTurret.gunsBlockRoot.rotation;
|
||||||
|
}
|
||||||
|
btrDataPacket.State = (byte)serverSideBtr.BtrState;
|
||||||
|
btrDataPacket.RouteState = (byte)serverSideBtr.VehicleRouteState;
|
||||||
|
btrDataPacket.LeftSideState = serverSideBtr.LeftSideState;
|
||||||
|
btrDataPacket.LeftSlot0State = serverSideBtr.LeftSlot0State;
|
||||||
|
btrDataPacket.LeftSlot1State = serverSideBtr.LeftSlot1State;
|
||||||
|
btrDataPacket.RightSideState = serverSideBtr.RightSideState;
|
||||||
|
btrDataPacket.RightSlot0State = serverSideBtr.RightSlot0State;
|
||||||
|
btrDataPacket.RightSlot1State = serverSideBtr.RightSlot1State;
|
||||||
|
btrDataPacket.currentSpeed = serverSideBtr.currentSpeed;
|
||||||
|
btrDataPacket.timeToEndPause = serverSideBtr.timeToEndPause;
|
||||||
|
btrDataPacket.moveDirection = (byte)serverSideBtr.VehicleMoveDirection;
|
||||||
|
btrDataPacket.MoveSpeed = serverSideBtr.moveSpeed;
|
||||||
|
if (btrController.BotShooterBtr != null)
|
||||||
|
{
|
||||||
|
btrDataPacket.BtrBotId = btrController.BotShooterBtr.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return btrDataPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisableServerSideRenderers()
|
||||||
|
{
|
||||||
|
var meshRenderers = serverSideBtr.transform.GetComponentsInChildren<MeshRenderer>();
|
||||||
|
foreach (var renderer in meshRenderers)
|
||||||
|
{
|
||||||
|
renderer.enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DestroyGameObjects()
|
||||||
|
{
|
||||||
|
if (btrController != null)
|
||||||
|
{
|
||||||
|
if (serverSideBtr != null)
|
||||||
|
{
|
||||||
|
Destroy(serverSideBtr.gameObject);
|
||||||
|
}
|
||||||
|
if (clientSideBtr != null)
|
||||||
|
{
|
||||||
|
Destroy(clientSideBtr.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
btrController.Dispose();
|
||||||
|
}
|
||||||
|
Destroy(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
project/Aki.Debugging/BTR/Patches/BTRBotAttachPatch.cs
Normal file
71
project/Aki.Debugging/BTR/Patches/BTRBotAttachPatch.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using Aki.Reflection.Patching;
|
||||||
|
using Comfort.Common;
|
||||||
|
using EFT;
|
||||||
|
using EFT.NextObservedPlayer;
|
||||||
|
using EFT.UI;
|
||||||
|
using EFT.Vehicle;
|
||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Aki.Debugging.BTR.Patches
|
||||||
|
{
|
||||||
|
// Fixes the BTR Bot initialization in AttachBot() of BTRTurretView
|
||||||
|
//
|
||||||
|
// Context:
|
||||||
|
// ClientGameWorld in LiveEFT will register the server-side BTR Bot as type ObservedPlayerView and is stored in GameWorld's allObservedPlayersByID dictionary.
|
||||||
|
// In SPT, GameWorld.allObservedPlayersByID is empty which results in the game never finishing the initialization of the BTR Bot which includes disabling its gun, voice and mesh renderers.
|
||||||
|
// Perhaps some research should be done into getting the dictionary populated as ObservedPlayerView seems to be utilised by several aspects of the BTR's functionality.
|
||||||
|
// For now, we do dirty patches to work around the lack of ObservedPlayerView, using Player instead.
|
||||||
|
public class BTRBotAttachPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(BTRTurretView), nameof(BTRTurretView.AttachBot));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPrefix]
|
||||||
|
public static bool PatchPrefix(object __instance, int btrBotId)
|
||||||
|
{
|
||||||
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
|
var btrTurretView = (BTRTurretView)__instance;
|
||||||
|
|
||||||
|
var btrTurretViewTupleField = (ValueTuple<ObservedPlayerView, bool>)AccessTools.Field(btrTurretView.GetType(), "valueTuple_0")
|
||||||
|
.GetValue(btrTurretView);
|
||||||
|
|
||||||
|
if (!btrTurretViewTupleField.Item2)
|
||||||
|
{
|
||||||
|
var btrTurretViewMethod = AccessTools.Method(btrTurretView.GetType(), "method_1");
|
||||||
|
btrTurretViewMethod.Invoke(btrTurretView, new object[]{btrBotId});
|
||||||
|
}
|
||||||
|
if (!btrTurretViewTupleField.Item2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var btrBot = gameWorld.BtrController.BotShooterBtr?.GetPlayer;
|
||||||
|
if (btrBot == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var botRootTransform = btrTurretView.BotRoot;
|
||||||
|
|
||||||
|
btrBot.Transform.position = botRootTransform.position;
|
||||||
|
|
||||||
|
var aiFirearmController = btrBot.gameObject.GetComponent<Player.FirearmController>();
|
||||||
|
var currentWeaponPrefab = (WeaponPrefab)AccessTools.Field(aiFirearmController.GetType(), "weaponPrefab_0").GetValue(aiFirearmController);
|
||||||
|
currentWeaponPrefab.transform.position = botRootTransform.position;
|
||||||
|
|
||||||
|
btrBot.PlayerBones.Weapon_Root_Anim.SetPositionAndRotation(botRootTransform.position, botRootTransform.rotation);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ConsoleScreen.LogError("[AKI-BTR] Could not finish BtrBot initialization. Check logs.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
87
project/Aki.Debugging/BTR/Patches/BTRBotInitPatch.cs
Normal file
87
project/Aki.Debugging/BTR/Patches/BTRBotInitPatch.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
using Aki.Reflection.Patching;
|
||||||
|
using EFT.UI;
|
||||||
|
using EFT.Vehicle;
|
||||||
|
using EFT;
|
||||||
|
using HarmonyLib;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using Comfort.Common;
|
||||||
|
using System;
|
||||||
|
using EFT.NextObservedPlayer;
|
||||||
|
|
||||||
|
namespace Aki.Debugging.BTR.Patches
|
||||||
|
{
|
||||||
|
// Fixes the BTR Bot initialization in method_1() of BTRTurretView
|
||||||
|
//
|
||||||
|
// Context:
|
||||||
|
// ClientGameWorld in LiveEFT will register the server-side BTR Bot as type ObservedPlayerView and is stored in GameWorld's allObservedPlayersByID dictionary.
|
||||||
|
// In SPT, allObservedPlayersByID is empty which results in the game never finishing the initialization of the BTR Bot which includes disabling its gun, voice and mesh renderers.
|
||||||
|
// Perhaps some research should be done into getting the dictionary populated as ObservedPlayerView seems to be utilised by several aspects of the BTR's functionality.
|
||||||
|
// For now, we do dirty patches to work around the lack of ObservedPlayerView, using Player instead.
|
||||||
|
public class BTRBotInitPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(BTRTurretView), "method_1");
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
public static void PatchPostfix(object __instance, int btrBotId, ref bool __result)
|
||||||
|
{
|
||||||
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
|
var btrTurretView = (BTRTurretView)__instance;
|
||||||
|
|
||||||
|
foreach (var playerKeyValue in gameWorld.allAlivePlayersByID)
|
||||||
|
{
|
||||||
|
if (playerKeyValue.Value.Id == btrBotId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Renderer[] array = playerKeyValue.Value.GetComponentsInChildren<Renderer>();
|
||||||
|
for (int i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
array[i].enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var aiFirearmController = playerKeyValue.Value.gameObject.GetComponent<Player.FirearmController>();
|
||||||
|
var currentWeaponPrefab = (WeaponPrefab)AccessTools.Field(aiFirearmController.GetType(), "weaponPrefab_0").GetValue(aiFirearmController);
|
||||||
|
if (currentWeaponPrefab.RemoveChildrenOf != null)
|
||||||
|
{
|
||||||
|
foreach (var text in currentWeaponPrefab.RemoveChildrenOf)
|
||||||
|
{
|
||||||
|
var transform = currentWeaponPrefab.transform.FindTransform(text);
|
||||||
|
if (transform != null)
|
||||||
|
{
|
||||||
|
transform.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var renderer in currentWeaponPrefab.GetComponentsInChildren<Renderer>())
|
||||||
|
{
|
||||||
|
if (renderer.name == "MuzzleJetCombinedMesh")
|
||||||
|
{
|
||||||
|
renderer.transform.localPosition = new Vector3(0.18f, 0f, -0.095f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
renderer.enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tuple = new ValueTuple<ObservedPlayerView, bool>(new ObservedPlayerView(), true);
|
||||||
|
var btrTurretViewTupleField = AccessTools.Field(btrTurretView.GetType(), "valueTuple_0");
|
||||||
|
btrTurretViewTupleField.SetValue(btrTurretView, tuple);
|
||||||
|
|
||||||
|
__result = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ConsoleScreen.LogError("[AKI-BTR] BtrBot initialization failed, BtrBot will be visible ingame. Check logs.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
project/Aki.Debugging/BTR/Patches/BTRPatch.cs
Normal file
44
project/Aki.Debugging/BTR/Patches/BTRPatch.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using Aki.Reflection.Patching;
|
||||||
|
using Comfort.Common;
|
||||||
|
using EFT;
|
||||||
|
using EFT.UI;
|
||||||
|
|
||||||
|
namespace Aki.Debugging.BTR.Patches
|
||||||
|
{
|
||||||
|
// Adds a BTRManager component to the GameWorld game object when raid starts.
|
||||||
|
public class BTRPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return typeof(GameWorld).GetMethod(nameof(GameWorld.OnGameStarted));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
public static void PatchPostfix()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
|
if (gameWorld.MainPlayer.Location.ToLower() != "tarkovstreets")
|
||||||
|
{
|
||||||
|
// only run patch on streets
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameWorld.LocationId.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
// GameWorld's LocationId needs to be set otherwise BTR doesn't get spawned in automatically
|
||||||
|
gameWorld.LocationId = gameWorld.MainPlayer.Location;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameWorld.gameObject.AddComponent<BTRManager>();
|
||||||
|
}
|
||||||
|
catch (System.Exception)
|
||||||
|
{
|
||||||
|
ConsoleScreen.LogError("[AKI-BTR] Exception thrown, check logs.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,69 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using Aki.Reflection.Patching;
|
|
||||||
using Comfort.Common;
|
|
||||||
using EFT;
|
|
||||||
using EFT.UI;
|
|
||||||
|
|
||||||
namespace Aki.Debugging.Patches
|
|
||||||
{
|
|
||||||
public class BtrTestPatch : ModulePatch
|
|
||||||
{
|
|
||||||
protected override MethodBase GetTargetMethod()
|
|
||||||
{
|
|
||||||
return typeof(GameWorld).GetMethod(nameof(GameWorld.OnGameStarted));
|
|
||||||
}
|
|
||||||
|
|
||||||
[PatchPostfix]
|
|
||||||
public static void PatchPostfix()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
|
||||||
if (gameWorld.MainPlayer.Location.ToLower() != "tarkovstreets")
|
|
||||||
{
|
|
||||||
// only run patch on streets
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var botGame = Singleton<IBotGame>.Instance;
|
|
||||||
|
|
||||||
if (gameWorld.BtrController == null)
|
|
||||||
{
|
|
||||||
if (!Singleton<GClass2911>.Instantiated)
|
|
||||||
{
|
|
||||||
Singleton<GClass2911>.Create(new GClass2911());
|
|
||||||
}
|
|
||||||
|
|
||||||
gameWorld.BtrController = Singleton<GClass2911>.Instance;
|
|
||||||
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] BtrController instance is null: {gameWorld.BtrController == null}");
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] Singleton GClass2911 is null: {Singleton<GClass2911>.Instance == null}");
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] BtrController.BotShooterBtr instance is null: {gameWorld.BtrController?.BotShooterBtr == null}");
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] BtrController.BtrVehicle instance is null: {gameWorld.BtrController?.BtrVehicle == null}");
|
|
||||||
}
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] botspawner is enabled: {botGame.BotsController.IsEnable}");
|
|
||||||
|
|
||||||
ConsoleScreen.LogWarning("[AKI-BTR] Post patch, spawning btr");
|
|
||||||
botGame.BotsController.BotSpawner.SpawnBotBTR();
|
|
||||||
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] btr vehicle is null: {gameWorld.BtrController?.BtrVehicle == null}");
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] btr vehicle gameobject is null: {gameWorld.BtrController?.BtrVehicle?.gameObject == null}");
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] BtrController.BotShooterBtr instance is null: {gameWorld.BtrController?.BotShooterBtr == null}");
|
|
||||||
|
|
||||||
var btrTransform = gameWorld.BtrController?.BtrVehicle?.gameObject?.transform;
|
|
||||||
if (btrTransform != null)
|
|
||||||
{
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] Btr Location {btrTransform}");
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
ConsoleScreen.LogWarning($"[AKI-BTR] wasnt able to get BTR location");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception)
|
|
||||||
{
|
|
||||||
ConsoleScreen.LogError("[AKI-BTR] Exception thrown, check logs");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user