mirror of
https://github.com/sp-tarkov/modules.git
synced 2025-02-13 07:10:44 -05:00
Fix the BTR turretview bot being visible (!92)
Rewrite the BTRTurretView attach patch, so we no longer need the BotInit patch Co-authored-by: DrakiaXYZ <565558+TheDgtl@users.noreply.github.com> Reviewed-on: SPT-AKI/Modules#92 Co-authored-by: DrakiaXYZ <drakiaxyz@noreply.dev.sp-tarkov.com> Co-committed-by: DrakiaXYZ <drakiaxyz@noreply.dev.sp-tarkov.com>
This commit is contained in:
parent
f1a7a0cb99
commit
059334d0cd
@ -12,13 +12,14 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="AnimationSystem.Types" HintPath="..\Shared\Managed\AnimationSystem.Types.dll" />
|
||||||
<Reference Include="Assembly-CSharp" HintPath="..\Shared\Hollowed\hollowed.dll" Private="False" />
|
<Reference Include="Assembly-CSharp" HintPath="..\Shared\Hollowed\hollowed.dll" Private="False" />
|
||||||
<Reference Include="Comfort" HintPath="..\Shared\Managed\Comfort.dll" Private="False" />
|
<Reference Include="Comfort" HintPath="..\Shared\Managed\Comfort.dll" Private="False" />
|
||||||
<Reference Include="DissonanceVoip" HintPath="..\Shared\Managed\DissonanceVoip.dll" Private="False" />
|
<Reference Include="DissonanceVoip" HintPath="..\Shared\Managed\DissonanceVoip.dll" Private="False" />
|
||||||
<Reference Include="Sirenix.Serialization" HintPath="..\Shared\Managed\Sirenix.Serialization.dll" Private="False" />
|
<Reference Include="Sirenix.Serialization" HintPath="..\Shared\Managed\Sirenix.Serialization.dll" Private="False" />
|
||||||
<Reference Include="UnityEngine" HintPath="..\Shared\Managed\UnityEngine.dll" Private="False" />
|
<Reference Include="UnityEngine" HintPath="..\Shared\Managed\UnityEngine.dll" Private="False" />
|
||||||
<Reference Include="UnityEngine.AIModule" HintPath="..\Shared\Managed\UnityEngine.AIModule.dll" Private="False" />
|
<Reference Include="UnityEngine.AIModule" HintPath="..\Shared\Managed\UnityEngine.AIModule.dll" Private="False" />
|
||||||
<Reference Include="UnityEngine.AnimationModule" HintPath="..\Shared\Managed\UnityEngine.AnimationModule.dll" Private="False" />
|
<Reference Include="UnityEngine.AnimationModule" HintPath="..\Shared\Managed\UnityEngine.AnimationModule.dll" Private="False" />
|
||||||
<Reference Include="UnityEngine.AssetBundleModule" HintPath="..\Shared\Managed\UnityEngine.AssetBundleModule.dll" Private="False" />
|
<Reference Include="UnityEngine.AssetBundleModule" HintPath="..\Shared\Managed\UnityEngine.AssetBundleModule.dll" Private="False" />
|
||||||
<Reference Include="UnityEngine.AudioModule" HintPath="..\Shared\Managed\UnityEngine.AudioModule.dll" Private="False" />
|
<Reference Include="UnityEngine.AudioModule" HintPath="..\Shared\Managed\UnityEngine.AudioModule.dll" Private="False" />
|
||||||
<Reference Include="UnityEngine.CoreModule" HintPath="..\Shared\Managed\UnityEngine.CoreModule.dll" Private="False" />
|
<Reference Include="UnityEngine.CoreModule" HintPath="..\Shared\Managed\UnityEngine.CoreModule.dll" Private="False" />
|
||||||
|
@ -58,7 +58,6 @@ namespace Aki.Custom
|
|||||||
new BTRActivateTraderDialogPatch().Enable();
|
new BTRActivateTraderDialogPatch().Enable();
|
||||||
new BTRInteractionPatch().Enable();
|
new BTRInteractionPatch().Enable();
|
||||||
new BTRExtractPassengersPatch().Enable();
|
new BTRExtractPassengersPatch().Enable();
|
||||||
new BTRBotInitPatch().Enable();
|
|
||||||
new BTRBotAttachPatch().Enable();
|
new BTRBotAttachPatch().Enable();
|
||||||
new BTRReceiveDamageInfoPatch().Enable();
|
new BTRReceiveDamageInfoPatch().Enable();
|
||||||
new BTRTurretCanShootPatch().Enable();
|
new BTRTurretCanShootPatch().Enable();
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
using Aki.Reflection.Patching;
|
using Aki.Reflection.Patching;
|
||||||
using Comfort.Common;
|
using Comfort.Common;
|
||||||
using EFT;
|
using EFT;
|
||||||
|
using EFT.AssetsManager;
|
||||||
using EFT.NextObservedPlayer;
|
using EFT.NextObservedPlayer;
|
||||||
using EFT.UI;
|
|
||||||
using EFT.Vehicle;
|
using EFT.Vehicle;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Aki.Custom.BTR.Patches
|
namespace Aki.Custom.BTR.Patches
|
||||||
{
|
{
|
||||||
@ -15,12 +18,25 @@ namespace Aki.Custom.BTR.Patches
|
|||||||
// Context:
|
// Context:
|
||||||
// ClientGameWorld in LiveEFT will register the server-side BTR Bot as type ObservedPlayerView and is stored in GameWorld's allObservedPlayersByID dictionary.
|
// 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.
|
// 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.
|
||||||
// For now, we do dirty patches to work around the lack of ObservedPlayerView, using Player instead.
|
//
|
||||||
|
// This is essentially a full reimplementation of the BTRTurretView class, but using Player instead of ObservedPlayerView.
|
||||||
|
//
|
||||||
public class BTRBotAttachPatch : ModulePatch
|
public class BTRBotAttachPatch : ModulePatch
|
||||||
{
|
{
|
||||||
|
private static FieldInfo _valueTuple0Field;
|
||||||
|
private static FieldInfo _gunModsToDisableField;
|
||||||
|
private static FieldInfo _weaponPrefab0Field;
|
||||||
|
private static readonly List<Renderer> rendererList = new List<Renderer>(256);
|
||||||
|
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
return AccessTools.Method(typeof(BTRTurretView), nameof(BTRTurretView.AttachBot));
|
var targetType = typeof(BTRTurretView);
|
||||||
|
|
||||||
|
_valueTuple0Field = AccessTools.Field(targetType, "valueTuple_0");
|
||||||
|
_gunModsToDisableField = AccessTools.Field(targetType, "_gunModsToDisable");
|
||||||
|
_weaponPrefab0Field = AccessTools.Field(typeof(Player.FirearmController), "weaponPrefab_0");
|
||||||
|
|
||||||
|
return AccessTools.Method(targetType, nameof(BTRTurretView.AttachBot));
|
||||||
}
|
}
|
||||||
|
|
||||||
[PatchPrefix]
|
[PatchPrefix]
|
||||||
@ -32,47 +48,120 @@ namespace Aki.Custom.BTR.Patches
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var btrTurretViewTupleField = (ValueTuple<ObservedPlayerView, bool>)AccessTools.Field(__instance.GetType(), "valueTuple_0").GetValue(__instance);
|
// Find the BTR turret
|
||||||
if (!btrTurretViewTupleField.Item2)
|
var alivePlayersList = gameWorld.AllAlivePlayersList;
|
||||||
|
Player turretPlayer = alivePlayersList.FirstOrDefault(x => x.Id == btrBotId);
|
||||||
|
if (turretPlayer == null)
|
||||||
{
|
{
|
||||||
__instance.method_3(btrBotId);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var btrController = gameWorld.BtrController;
|
// Init the turret view
|
||||||
if (btrController == null)
|
var valueTuple = (ValueTuple<ObservedPlayerView, bool>)_valueTuple0Field.GetValue(__instance);
|
||||||
|
if (!valueTuple.Item2 && !InitTurretView(__instance, turretPlayer))
|
||||||
{
|
{
|
||||||
Logger.LogError("[AKI-BTR] BTRBotAttachPatch - BtrController is null");
|
Logger.LogError("[AKI-BTR] BTRBotAttachPatch - BtrBot initialization failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var btrBotShooter = btrController.BotShooterBtr;
|
WeaponPrefab weaponPrefab;
|
||||||
if (btrBotShooter == null)
|
Transform transform;
|
||||||
|
if (FindTurretObjects(turretPlayer, out weaponPrefab, out transform))
|
||||||
{
|
{
|
||||||
Logger.LogError("[AKI-BTR] BTRBotAttachPatch - BtrBotShooter is null");
|
weaponPrefab.transform.SetPositionAndRotation(__instance.GunRoot.position, __instance.GunRoot.rotation);
|
||||||
|
transform.SetPositionAndRotation(__instance.GunRoot.position, __instance.GunRoot.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool InitTurretView(BTRTurretView btrTurretView, Player turretPlayer)
|
||||||
|
{
|
||||||
|
EnableTurretObjects(btrTurretView, turretPlayer, false);
|
||||||
|
|
||||||
|
// We only use this for tracking whether the turret is initialized, so we don't need to set the ObservedPlayerView
|
||||||
|
_valueTuple0Field.SetValue(btrTurretView, new ValueTuple<ObservedPlayerView, bool>(null, true));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EnableTurretObjects(BTRTurretView btrTurretView, Player player, bool enable)
|
||||||
|
{
|
||||||
|
// Find the turret weapon transform
|
||||||
|
WeaponPrefab weaponPrefab;
|
||||||
|
Transform weaponTransform;
|
||||||
|
if (!FindTurretObjects(player, out weaponPrefab, out weaponTransform))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide the turret bot
|
||||||
|
SetVisible(player, weaponPrefab, false);
|
||||||
|
|
||||||
|
// Disable the components we need to disaable
|
||||||
|
var _gunModsToDisable = (string[])_gunModsToDisableField.GetValue(btrTurretView);
|
||||||
|
foreach (Transform child in weaponTransform)
|
||||||
|
{
|
||||||
|
if (_gunModsToDisable.Contains(child.name))
|
||||||
|
{
|
||||||
|
child.gameObject.SetActive(enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool FindTurretObjects(Player player, out WeaponPrefab weaponPrefab, out Transform weapon)
|
||||||
|
{
|
||||||
|
// Find the WeaponPrefab and Transform of the turret weapon
|
||||||
|
var aiFirearmController = player.gameObject.GetComponent<Player.FirearmController>();
|
||||||
|
weaponPrefab = (WeaponPrefab)_weaponPrefab0Field.GetValue(aiFirearmController);
|
||||||
|
|
||||||
|
if (weaponPrefab == null)
|
||||||
|
{
|
||||||
|
weapon = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
weapon = weaponPrefab.Hierarchy.GetTransform(ECharacterWeaponBones.weapon);
|
||||||
|
return weapon != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A re-implementation of the ObservedPlayerController.Culling.Mode setter that works for a Player object
|
||||||
|
*/
|
||||||
|
private static void SetVisible(Player player, WeaponPrefab weaponPrefab, bool isVisible)
|
||||||
|
{
|
||||||
|
// Toggle any animators and colliders
|
||||||
|
if (player.HealthController.IsAlive)
|
||||||
{
|
{
|
||||||
var btrBot = btrBotShooter.GetPlayer;
|
IAnimator bodyAnimatorCommon = player.GetBodyAnimatorCommon();
|
||||||
var botRootTransform = __instance.BotRoot;
|
if (bodyAnimatorCommon.enabled != isVisible)
|
||||||
|
{
|
||||||
|
bool flag = !bodyAnimatorCommon.enabled;
|
||||||
|
bodyAnimatorCommon.enabled = isVisible;
|
||||||
|
FirearmsAnimator firearmsAnimator = player.HandsController.FirearmsAnimator;
|
||||||
|
if (firearmsAnimator != null && firearmsAnimator.Animator.enabled != isVisible)
|
||||||
|
{
|
||||||
|
firearmsAnimator.Animator.enabled = isVisible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
btrBot.Transform.position = botRootTransform.position;
|
PlayerPoolObject component = player.gameObject.GetComponent<PlayerPoolObject>();
|
||||||
|
foreach (Collider collider in component.Colliders)
|
||||||
var firearmController = btrBot.gameObject.GetComponent<Player.FirearmController>();
|
{
|
||||||
var currentWeaponPrefab = (WeaponPrefab)AccessTools.Field(firearmController.GetType(), "weaponPrefab_0").GetValue(firearmController);
|
if (collider.enabled != isVisible)
|
||||||
currentWeaponPrefab.transform.position = botRootTransform.position;
|
{
|
||||||
|
collider.enabled = isVisible;
|
||||||
btrBot.PlayerBones.Weapon_Root_Anim.SetPositionAndRotation(botRootTransform.position, botRootTransform.rotation);
|
}
|
||||||
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
|
// Build a list of renderers for this player object and set their rendering state
|
||||||
|
rendererList.Clear();
|
||||||
|
player.PlayerBody.GetRenderersNonAlloc(rendererList);
|
||||||
|
if (weaponPrefab != null)
|
||||||
{
|
{
|
||||||
ConsoleScreen.LogError("[AKI-BTR] Could not finish BtrBot initialization. Check logs.");
|
rendererList.AddRange(weaponPrefab.Renderers);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
rendererList.ForEach(renderer => renderer.forceRenderingOff = !isVisible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
using Aki.Reflection.Patching;
|
|
||||||
using Comfort.Common;
|
|
||||||
using EFT;
|
|
||||||
using EFT.NextObservedPlayer;
|
|
||||||
using EFT.UI;
|
|
||||||
using EFT.Vehicle;
|
|
||||||
using HarmonyLib;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Aki.Custom.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.
|
|
||||||
// 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), nameof(BTRTurretView.method_3));
|
|
||||||
}
|
|
||||||
|
|
||||||
[PatchPrefix]
|
|
||||||
private static bool PatchPrefix(ref ValueTuple<ObservedPlayerView, bool> ___valueTuple_0, int btrBotId, ref bool __result)
|
|
||||||
{
|
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
|
||||||
if (gameWorld == null)
|
|
||||||
{
|
|
||||||
Logger.LogError("[AKI-BTR] BTRBotInitPatch - GameWorld is null");
|
|
||||||
__result = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var alivePlayersList = gameWorld.AllAlivePlayersList;
|
|
||||||
bool doesBtrBotExist = alivePlayersList.Exists(x => x.Id == btrBotId);
|
|
||||||
if (!doesBtrBotExist)
|
|
||||||
{
|
|
||||||
__result = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Player player = alivePlayersList.First(x => x.Id == btrBotId);
|
|
||||||
|
|
||||||
Renderer[] array = player.GetComponentsInChildren<Renderer>();
|
|
||||||
for (int i = 0; i < array.Length; i++)
|
|
||||||
{
|
|
||||||
array[i].enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var aiFirearmController = player.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);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
___valueTuple_0 = new ValueTuple<ObservedPlayerView, bool>(new ObservedPlayerView(), true);
|
|
||||||
|
|
||||||
__result = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
ConsoleScreen.LogError("[AKI-BTR] BtrBot initialization failed, BtrBot will be visible ingame. Check logs.");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user