mirror of
https://github.com/sp-tarkov/modules.git
synced 2025-02-13 03:10:45 -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 Aki.Common;
|
||||
using Aki.Debugging.BTR.Patches;
|
||||
using Aki.Debugging.Patches;
|
||||
using BepInEx;
|
||||
|
||||
@ -16,8 +17,10 @@ namespace Aki.Debugging
|
||||
{
|
||||
new EndRaidDebug().Enable();
|
||||
// new CoordinatesPatch().Enable();
|
||||
// new StaticLootDumper().Enable();
|
||||
new BtrTestPatch().Enable();
|
||||
// new StaticLootDumper().Enable();
|
||||
new BTRBotAttachPatch().Enable();
|
||||
new BTRBotInitPatch().Enable();
|
||||
new BTRPatch().Enable();
|
||||
}
|
||||
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