mirror of
https://github.com/sp-tarkov/modules.git
synced 2025-02-13 02:10:45 -05:00
Player can now talk to BTR driver (!52)
Todo: * BTR trader services requires implementation server-side * Send items to player stash (2x4) * Provide covering fire * Taxi to a specific location on Streets * Fix turret aiming at player from raid start * Make turret shoot at enemies (including player) Co-authored-by: Nympfonic <arys.steam@gmail.com> Reviewed-on: SPT-AKI/Modules#52 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
5fcc904a89
commit
37432541c3
@ -19,11 +19,13 @@ namespace Aki.Debugging
|
||||
// new CoordinatesPatch().Enable();
|
||||
// new StaticLootDumper().Enable();
|
||||
new BTRPathLoadPatch().Enable();
|
||||
new BTRActivateTraderDialogPatch().Enable();
|
||||
new BTRInteractionPatch().Enable();
|
||||
new BTRExtractPassengersPatch().Enable();
|
||||
new BTRBotAttachPatch().Enable();
|
||||
new BTRBotInitPatch().Enable();
|
||||
new BTRIsDoorsClosedPath().Enable();
|
||||
new BTRPatch().Enable();
|
||||
new BTRPatch().Enable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1,7 +1,10 @@
|
||||
using Comfort.Common;
|
||||
using Aki.Reflection.Utils;
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.Vehicle;
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using BTRController = GClass2911;
|
||||
using BTRDataPacket = GStruct378;
|
||||
@ -12,12 +15,18 @@ namespace Aki.Debugging.BTR
|
||||
public class BTRManager : MonoBehaviour
|
||||
{
|
||||
private GameWorld gameWorld;
|
||||
private BotsController botsController;
|
||||
|
||||
private BotBTRService btrBotService;
|
||||
private BTRController btrController;
|
||||
private BTRVehicle serverSideBtr;
|
||||
private BTRView clientSideBtr;
|
||||
private BTRVehicle btrServerSide;
|
||||
private BTRView btrClientSide;
|
||||
private BTRDataPacket btrDataPacket = default;
|
||||
private bool btrBotShooterInitialized = false;
|
||||
|
||||
private EPlayerBtrState previousPlayerBtrState;
|
||||
private BTRSide previousInteractedBtrSide;
|
||||
private BTRSide lastInteractedBtrSide;
|
||||
public BTRSide LastInteractedBtrSide => lastInteractedBtrSide;
|
||||
|
||||
|
||||
private void Start()
|
||||
@ -41,27 +50,10 @@ namespace Aki.Debugging.BTR
|
||||
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
|
||||
botsController = Singleton<IBotGame>.Instance.BotsController;
|
||||
btrBotService = botsController.BotTradersServices.BTRServices;
|
||||
|
||||
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();
|
||||
|
||||
previousPlayerBtrState = gameWorld.MainPlayer.BtrState;
|
||||
gameWorld.MainPlayer.OnBtrStateChanged += HandleBtrDoorState;
|
||||
InitBTR();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -74,6 +66,15 @@ namespace Aki.Debugging.BTR
|
||||
private void Update()
|
||||
{
|
||||
btrController.SyncBTRVehicleFromServer(UpdateDataPacket());
|
||||
|
||||
// BotShooterBtr doesn't get assigned to BtrController immediately so we nullcheck this in Update
|
||||
if (btrController.BotShooterBtr != null && !btrBotShooterInitialized)
|
||||
{
|
||||
btrBotService.Reset(); // Player will be added to Neutrals list and removed from Enemies list
|
||||
btrBotShooterInitialized = true;
|
||||
}
|
||||
|
||||
AimAtEnemy();
|
||||
}
|
||||
|
||||
public void HandleBtrDoorState(EPlayerBtrState playerBtrState)
|
||||
@ -104,30 +105,55 @@ namespace Aki.Debugging.BTR
|
||||
{
|
||||
if (interactPacket.SlotId == 0)
|
||||
{
|
||||
if (playerGoIn) serverSideBtr.LeftSlot0State = 1;
|
||||
else if (playerGoOut) serverSideBtr.LeftSlot0State = 0;
|
||||
if (playerGoIn) btrServerSide.LeftSlot0State = 1;
|
||||
else if (playerGoOut) btrServerSide.LeftSlot0State = 0;
|
||||
}
|
||||
else if (interactPacket.SlotId == 1)
|
||||
{
|
||||
if (playerGoIn) serverSideBtr.LeftSlot1State = 1;
|
||||
else if (playerGoOut) serverSideBtr.LeftSlot1State = 0;
|
||||
if (playerGoIn) btrServerSide.LeftSlot1State = 1;
|
||||
else if (playerGoOut) btrServerSide.LeftSlot1State = 0;
|
||||
}
|
||||
}
|
||||
else if (interactPacket.SideId == 1)
|
||||
{
|
||||
if (interactPacket.SlotId == 0)
|
||||
{
|
||||
if (playerGoIn) serverSideBtr.RightSlot0State = 1;
|
||||
else if (playerGoOut) serverSideBtr.RightSlot0State = 0;
|
||||
if (playerGoIn) btrServerSide.RightSlot0State = 1;
|
||||
else if (playerGoOut) btrServerSide.RightSlot0State = 0;
|
||||
}
|
||||
else if (interactPacket.SlotId == 1)
|
||||
{
|
||||
if (playerGoIn) serverSideBtr.RightSlot1State = 1;
|
||||
else if (playerGoOut) serverSideBtr.RightSlot1State = 0;
|
||||
if (playerGoIn) btrServerSide.RightSlot1State = 1;
|
||||
else if (playerGoOut) btrServerSide.RightSlot1State = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitBTR()
|
||||
{
|
||||
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
|
||||
|
||||
btrServerSide = btrController.BtrVehicle;
|
||||
btrServerSide.moveSpeed = 20f;
|
||||
var btrMapConfig = btrController.MapPathsConfiguration;
|
||||
btrServerSide.CurrentPathConfig = btrMapConfig.PathsConfiguration.pathsConfigurations.RandomElement();
|
||||
btrServerSide.Initialization(btrMapConfig);
|
||||
AccessTools.Method(btrControllerType, "method_14").Invoke(btrController, null); // creates and assigns the BTR a fake stash
|
||||
|
||||
DisableServerSideRenderers();
|
||||
|
||||
gameWorld.MainPlayer.OnBtrStateChanged += HandleBtrDoorState;
|
||||
|
||||
btrServerSide.MoveEnable();
|
||||
|
||||
UpdateDataPacket();
|
||||
btrClientSide = btrController.BtrView;
|
||||
btrClientSide.transform.position = btrDataPacket.position;
|
||||
btrClientSide.transform.rotation = btrDataPacket.rotation;
|
||||
}
|
||||
|
||||
private void UpdateBTRSideDoorState(byte state)
|
||||
{
|
||||
var player = gameWorld.MainPlayer;
|
||||
@ -136,15 +162,14 @@ namespace Aki.Debugging.BTR
|
||||
for (int i = 0; i < btrSides.Length; i++)
|
||||
{
|
||||
if (player.BtrInteractionSide != null && btrSides[i] == player.BtrInteractionSide
|
||||
|| previousInteractedBtrSide != null && btrSides[i] == previousInteractedBtrSide)
|
||||
|| lastInteractedBtrSide != null && btrSides[i] == lastInteractedBtrSide)
|
||||
{
|
||||
if (i == 0) serverSideBtr.LeftSideState = state;
|
||||
else if (i == 1) serverSideBtr.RightSideState = state;
|
||||
if (i == 0) btrServerSide.LeftSideState = state;
|
||||
else if (i == 1) btrServerSide.RightSideState = state;
|
||||
|
||||
if ((previousInteractedBtrSide != player.BtrInteractionSide && player.BtrInteractionSide != null)
|
||||
|| previousInteractedBtrSide == null)
|
||||
if (lastInteractedBtrSide != player.BtrInteractionSide)
|
||||
{
|
||||
previousInteractedBtrSide = player.BtrInteractionSide;
|
||||
lastInteractedBtrSide = player.BtrInteractionSide;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,25 +177,25 @@ namespace Aki.Debugging.BTR
|
||||
|
||||
private BTRDataPacket UpdateDataPacket()
|
||||
{
|
||||
btrDataPacket.position = serverSideBtr.transform.position;
|
||||
btrDataPacket.rotation = serverSideBtr.transform.rotation;
|
||||
if (serverSideBtr.BTRTurret?.gunsBlockRoot != null)
|
||||
btrDataPacket.position = btrServerSide.transform.position;
|
||||
btrDataPacket.rotation = btrServerSide.transform.rotation;
|
||||
if (btrServerSide.BTRTurret?.gunsBlockRoot != null)
|
||||
{
|
||||
btrDataPacket.turretRotation = serverSideBtr.BTRTurret.transform.rotation;
|
||||
btrDataPacket.gunsBlockRotation = serverSideBtr.BTRTurret.gunsBlockRoot.rotation;
|
||||
btrDataPacket.turretRotation = btrServerSide.BTRTurret.transform.rotation;
|
||||
btrDataPacket.gunsBlockRotation = btrServerSide.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;
|
||||
btrDataPacket.State = (byte)btrServerSide.BtrState;
|
||||
btrDataPacket.RouteState = (byte)btrServerSide.VehicleRouteState;
|
||||
btrDataPacket.LeftSideState = btrServerSide.LeftSideState;
|
||||
btrDataPacket.LeftSlot0State = btrServerSide.LeftSlot0State;
|
||||
btrDataPacket.LeftSlot1State = btrServerSide.LeftSlot1State;
|
||||
btrDataPacket.RightSideState = btrServerSide.RightSideState;
|
||||
btrDataPacket.RightSlot0State = btrServerSide.RightSlot0State;
|
||||
btrDataPacket.RightSlot1State = btrServerSide.RightSlot1State;
|
||||
btrDataPacket.currentSpeed = btrServerSide.currentSpeed;
|
||||
btrDataPacket.timeToEndPause = btrServerSide.timeToEndPause;
|
||||
btrDataPacket.moveDirection = (byte)btrServerSide.VehicleMoveDirection;
|
||||
btrDataPacket.MoveSpeed = btrServerSide.moveSpeed;
|
||||
if (btrController.BotShooterBtr != null)
|
||||
{
|
||||
btrDataPacket.BtrBotId = btrController.BotShooterBtr.Id;
|
||||
@ -181,30 +206,49 @@ namespace Aki.Debugging.BTR
|
||||
|
||||
private void DisableServerSideRenderers()
|
||||
{
|
||||
var meshRenderers = serverSideBtr.transform.GetComponentsInChildren<MeshRenderer>();
|
||||
var meshRenderers = btrServerSide.transform.GetComponentsInChildren<MeshRenderer>();
|
||||
foreach (var renderer in meshRenderers)
|
||||
{
|
||||
renderer.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void AimAtEnemy()
|
||||
{
|
||||
if (btrController.BotShooterBtr == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var btrTurret = btrServerSide.BTRTurret;
|
||||
var enemies = btrController.BotShooterBtr.BotsGroup.Enemies;
|
||||
if (enemies.Any())
|
||||
{
|
||||
btrTurret.EnableAimingObject(enemies.First().Key.Transform.Original);
|
||||
}
|
||||
else
|
||||
{
|
||||
btrTurret.DisableAiming();
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyGameObjects()
|
||||
{
|
||||
if (btrController != null)
|
||||
{
|
||||
if (serverSideBtr != null)
|
||||
if (btrServerSide != null)
|
||||
{
|
||||
Destroy(serverSideBtr.gameObject);
|
||||
Destroy(btrServerSide.gameObject);
|
||||
}
|
||||
if (clientSideBtr != null)
|
||||
if (btrClientSide != null)
|
||||
{
|
||||
Destroy(clientSideBtr.gameObject);
|
||||
Destroy(btrClientSide.gameObject);
|
||||
}
|
||||
|
||||
btrController.Dispose();
|
||||
}
|
||||
|
||||
if (gameWorld != null)
|
||||
if (gameWorld?.MainPlayer != null)
|
||||
{
|
||||
gameWorld.MainPlayer.OnBtrStateChanged -= HandleBtrDoorState;
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
using Aki.Reflection.Patching;
|
||||
using Aki.Reflection.Utils;
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.UI.Screens;
|
||||
using HarmonyLib;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using static EFT.UI.TraderDialogScreen;
|
||||
|
||||
namespace Aki.Debugging.BTR.Patches
|
||||
{
|
||||
public class BTRActivateTraderDialogPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
var targetType = typeof(GClass1854).GetNestedTypes(PatchConstants.PrivateFlags).Where(x => x.Name == "Class1469").First();
|
||||
return AccessTools.Method(targetType, "method_2");
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static bool PatchPrefix()
|
||||
{
|
||||
var gameWorld = Singleton<GameWorld>.Instance;
|
||||
var player = gameWorld.MainPlayer;
|
||||
|
||||
var questController = (GClass3201)AccessTools.Field(player.GetType(), "_questController").GetValue(player);
|
||||
var inventoryController = (InventoryControllerClass)AccessTools.Field(player.GetType(), "_inventoryController").GetValue(player);
|
||||
|
||||
GClass3130 btrDialog = new GClass3130(player.Profile, Profile.TraderInfo.BTR_TRADER_ID, questController, inventoryController, null);
|
||||
btrDialog.OnClose += player.UpdateInteractionCast;
|
||||
btrDialog.ShowScreen(EScreenState.Queued);
|
||||
//GClass1952.ShowDialogScreen(Profile.ETraderServiceSource.Btr, true);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
using Aki.Reflection.Patching;
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.Vehicle;
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Aki.Debugging.BTR.Patches
|
||||
{
|
||||
public class BTRExtractPassengersPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(VehicleBase), "ExtractPassengers");
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static void PatchPrefix()
|
||||
{
|
||||
var gameWorld = Singleton<GameWorld>.Instance;
|
||||
var player = gameWorld.MainPlayer;
|
||||
var btrManager = gameWorld.GetComponent<BTRManager>();
|
||||
|
||||
try
|
||||
{
|
||||
var btrSide = btrManager.LastInteractedBtrSide;
|
||||
if (btrSide == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (btrSide.TryGetCachedPlace(out byte b))
|
||||
{
|
||||
var interactionBtrPacket = btrSide.GetInteractWithBtrPacket(b, EInteractionType.GoOut);
|
||||
if (interactionBtrPacket.HasInteraction)
|
||||
{
|
||||
BTRView btrView = gameWorld.BtrController.BtrView;
|
||||
if (btrView == null)
|
||||
{
|
||||
throw new NullReferenceException("BtrView not found");
|
||||
}
|
||||
|
||||
btrManager.OnPlayerInteractDoor(interactionBtrPacket);
|
||||
btrView.Interaction(player, interactionBtrPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex19)
|
||||
{
|
||||
UnityEngine.Debug.LogException(ex19);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ namespace Aki.Debugging.BTR.Patches
|
||||
{
|
||||
var gameWorld = Singleton<GameWorld>.Instance;
|
||||
var player = (Player)__instance;
|
||||
var btrManager = gameWorld.GetComponent<BTRManager>();
|
||||
|
||||
try
|
||||
{
|
||||
@ -34,9 +35,7 @@ namespace Aki.Debugging.BTR.Patches
|
||||
throw new NullReferenceException("BtrView not found");
|
||||
}
|
||||
|
||||
var btrManager = gameWorld.GetComponent<BTRManager>();
|
||||
btrManager.OnPlayerInteractDoor(interactionBtrPacket);
|
||||
|
||||
btrView.Interaction(player, interactionBtrPacket);
|
||||
}
|
||||
}
|
||||
|
@ -17,22 +17,13 @@ namespace Aki.Debugging.BTR.Patches
|
||||
[PatchPrefix]
|
||||
public static bool PatchPrefix(ref bool __result)
|
||||
{
|
||||
var btrView = Singleton<GameWorld>.Instance?.BtrController?.BtrView;
|
||||
if (btrView == null)
|
||||
var serverSideBTR = Singleton<GameWorld>.Instance?.BtrController.BtrVehicle;
|
||||
if (serverSideBTR == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var btrSides = (BTRSide[])AccessTools.Field(typeof(BTRView), "_btrSides").GetValue(btrView);
|
||||
int doorsClosed = 0;
|
||||
foreach (var side in btrSides)
|
||||
{
|
||||
if (side.State == BTRSide.EState.Free)
|
||||
{
|
||||
doorsClosed++;
|
||||
}
|
||||
}
|
||||
if (doorsClosed == btrSides.Length)
|
||||
if (serverSideBTR.LeftSideState == 0 && serverSideBTR.RightSideState == 0)
|
||||
{
|
||||
__result = true;
|
||||
return false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user