mirror of
https://github.com/sp-tarkov/modules.git
synced 2025-02-13 09:50:43 -05:00
Player will receive notifications when purchasing BTR service or when they are blacklisted from the BTR (!63)
Todo: * Taxi service * Improve turret aim/firing * Switch targets when current target out of line of sight * Allow certain aspects to be configured from server, for example: price multipliers, wait times at each location, etc. * Perhaps, a persisting blacklist from the BTR for several raids afterwards * Further code refactoring Co-authored-by: Nympfonic <arys.steam@gmail.com> Reviewed-on: SPT-AKI/Modules#63 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
e771501cd5
commit
879d90b71f
@ -24,6 +24,7 @@
|
|||||||
<Reference Include="UnityEngine.UI" HintPath="..\Shared\Managed\UnityEngine.UI.dll" Private="False" />
|
<Reference Include="UnityEngine.UI" HintPath="..\Shared\Managed\UnityEngine.UI.dll" Private="False" />
|
||||||
<Reference Include="UnityEngine.UIModule" HintPath="..\Shared\Managed\UnityEngine.UIModule.dll" Private="False" />
|
<Reference Include="UnityEngine.UIModule" HintPath="..\Shared\Managed\UnityEngine.UIModule.dll" Private="False" />
|
||||||
<Reference Include="Comfort.Common" HintPath="..\Shared\Managed\Comfort.dll" Private="False" />
|
<Reference Include="Comfort.Common" HintPath="..\Shared\Managed\Comfort.dll" Private="False" />
|
||||||
|
<Reference Include="DissonanceVoip" HintPath="..\Shared\Managed\DissonanceVoip.dll" Private="False" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -92,24 +92,28 @@ namespace Aki.Debugging.BTR
|
|||||||
{
|
{
|
||||||
btrController.SyncBTRVehicleFromServer(UpdateDataPacket());
|
btrController.SyncBTRVehicleFromServer(UpdateDataPacket());
|
||||||
|
|
||||||
// BotShooterBtr doesn't get assigned to BtrController immediately so we nullcheck this in Update
|
if (btrController.BotShooterBtr == null) return;
|
||||||
if (btrController.BotShooterBtr != null && !btrBotShooterInitialized)
|
|
||||||
|
// BotShooterBtr doesn't get assigned to BtrController immediately so we check this in Update
|
||||||
|
if (!btrBotShooterInitialized)
|
||||||
{
|
{
|
||||||
btrBotShooter = btrController.BotShooterBtr;
|
btrBotShooter = btrController.BotShooterBtr;
|
||||||
btrBotService.Reset(); // Player will be added to Neutrals list and removed from Enemies list
|
btrBotService.Reset(); // Player will be added to Neutrals list and removed from Enemies list
|
||||||
TraderServicesManager.Instance.OnTraderServicePurchased += TraderServicePurchased;
|
TraderServicesManager.Instance.OnTraderServicePurchased += BTRTraderServicePurchased;
|
||||||
btrBotShooterInitialized = true;
|
btrBotShooterInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btrController.BotShooterBtr == null) return;
|
|
||||||
|
|
||||||
if (HasTarget() && IsAimingAtTarget() && !isShooting)
|
if (HasTarget() && IsAimingAtTarget() && !isShooting)
|
||||||
{
|
{
|
||||||
_shootingTargetCoroutine = StaticManager.BeginCoroutine(ShootTarget());
|
_shootingTargetCoroutine = StaticManager.BeginCoroutine(ShootTarget());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_coverFireTimerCoroutine != null && ShouldCancelCoverFireSupport())
|
||||||
|
{
|
||||||
|
CancelCoverFireSupport();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Please tell me there's a better way than this xd
|
|
||||||
public void OnPlayerInteractDoor(PlayerInteractPacket interactPacket)
|
public void OnPlayerInteractDoor(PlayerInteractPacket interactPacket)
|
||||||
{
|
{
|
||||||
btrServerSide.LeftSlot0State = 0;
|
btrServerSide.LeftSlot0State = 0;
|
||||||
@ -193,15 +197,37 @@ namespace Aki.Debugging.BTR
|
|||||||
_updateTaxiPriceMethod.Invoke(btrController, new object[] { destinationPoint, isFinal });
|
_updateTaxiPriceMethod.Invoke(btrController, new object[] { destinationPoint, isFinal });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TraderServicePurchased(ETraderServiceType serviceType)
|
private bool IsBtrService(ETraderServiceType serviceType)
|
||||||
{
|
{
|
||||||
|
if (serviceType == ETraderServiceType.BtrItemsDelivery
|
||||||
|
|| serviceType == ETraderServiceType.PlayerTaxi
|
||||||
|
|| serviceType == ETraderServiceType.BtrBotCover)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BTRTraderServicePurchased(ETraderServiceType serviceType)
|
||||||
|
{
|
||||||
|
if (!IsBtrService(serviceType))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Player> passengers = gameWorld.AllAlivePlayersList.Where(x => x.BtrState == EPlayerBtrState.Inside).ToList();
|
||||||
|
List<int> playersToNotify = passengers.Select(x => x.Id).ToList();
|
||||||
|
btrController.method_6(playersToNotify, serviceType); // notify BTR passengers that a service has been purchased
|
||||||
|
|
||||||
switch (serviceType)
|
switch (serviceType)
|
||||||
{
|
{
|
||||||
case ETraderServiceType.BtrBotCover:
|
case ETraderServiceType.BtrBotCover:
|
||||||
List<Player> passengers = gameWorld.AllAlivePlayersList.Where(x => x.BtrState == EPlayerBtrState.Inside).ToList();
|
|
||||||
botEventHandler.ApplyTraderServiceBtrSupport(passengers);
|
botEventHandler.ApplyTraderServiceBtrSupport(passengers);
|
||||||
StartCoverFireTimer(90f);
|
StartCoverFireTimer(90f);
|
||||||
break;
|
break;
|
||||||
|
case ETraderServiceType.PlayerTaxi:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,6 +236,23 @@ namespace Aki.Debugging.BTR
|
|||||||
_coverFireTimerCoroutine = StaticManager.BeginCoroutine(CoverFireTimer(time));
|
_coverFireTimerCoroutine = StaticManager.BeginCoroutine(CoverFireTimer(time));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ShouldCancelCoverFireSupport()
|
||||||
|
{
|
||||||
|
var friendlyPlayersByBtrSupport = (List<Player>)AccessTools.Field(btrBotService.GetType(), "_friendlyPlayersByBtrSupport").GetValue(btrBotService);
|
||||||
|
if (!friendlyPlayersByBtrSupport.Any())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelCoverFireSupport()
|
||||||
|
{
|
||||||
|
StaticManager.KillCoroutine(ref _coverFireTimerCoroutine);
|
||||||
|
botEventHandler.StopTraderServiceBtrSupport();
|
||||||
|
}
|
||||||
|
|
||||||
private IEnumerator CoverFireTimer(float time)
|
private IEnumerator CoverFireTimer(float time)
|
||||||
{
|
{
|
||||||
yield return new WaitForSecondsRealtime(time);
|
yield return new WaitForSecondsRealtime(time);
|
||||||
@ -331,7 +374,6 @@ namespace Aki.Debugging.BTR
|
|||||||
Vector3 currentTargetPosition = currentTargetTransform.position;
|
Vector3 currentTargetPosition = currentTargetTransform.position;
|
||||||
if (btrTurretServer.CheckPositionInAimingZone(currentTargetPosition))
|
if (btrTurretServer.CheckPositionInAimingZone(currentTargetPosition))
|
||||||
{
|
{
|
||||||
// If turret machine gun aim is close enough to target and has line of sight
|
|
||||||
if (btrTurretServer.targetTransform == currentTargetTransform && btrBotShooter.BotBtrData.CanShoot())
|
if (btrTurretServer.targetTransform == currentTargetTransform && btrBotShooter.BotBtrData.CanShoot())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -389,6 +431,11 @@ namespace Aki.Debugging.BTR
|
|||||||
isShooting = false;
|
isShooting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
DestroyGameObjects();
|
||||||
|
}
|
||||||
|
|
||||||
private void DestroyGameObjects()
|
private void DestroyGameObjects()
|
||||||
{
|
{
|
||||||
if (btrController != null)
|
if (btrController != null)
|
||||||
@ -412,7 +459,7 @@ namespace Aki.Debugging.BTR
|
|||||||
|
|
||||||
if (TraderServicesManager.Instance != null)
|
if (TraderServicesManager.Instance != null)
|
||||||
{
|
{
|
||||||
TraderServicesManager.Instance.OnTraderServicePurchased -= TraderServicePurchased;
|
TraderServicesManager.Instance.OnTraderServicePurchased -= BTRTraderServicePurchased;
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticManager.KillCoroutine(ref _shootingTargetCoroutine);
|
StaticManager.KillCoroutine(ref _shootingTargetCoroutine);
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
using Aki.Debugging.BTR.Utils;
|
using Aki.Reflection.Patching;
|
||||||
using Aki.Reflection.Patching;
|
|
||||||
using Aki.Reflection.Utils;
|
|
||||||
using Comfort.Common;
|
using Comfort.Common;
|
||||||
using EFT;
|
using EFT;
|
||||||
using EFT.UI.Screens;
|
using EFT.UI.Screens;
|
||||||
using EFT.Vehicle;
|
using EFT.Vehicle;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using static EFT.UI.TraderDialogScreen;
|
using static EFT.UI.TraderDialogScreen;
|
||||||
|
|
||||||
namespace Aki.Debugging.BTR.Patches
|
namespace Aki.Debugging.BTR.Patches
|
||||||
{
|
{
|
||||||
public class BTRActivateTraderDialogPatch : ModulePatch
|
internal class BTRActivateTraderDialogPatch : ModulePatch
|
||||||
{
|
{
|
||||||
private static FieldInfo _playerInventoryControllerField;
|
private static FieldInfo _playerInventoryControllerField;
|
||||||
private static FieldInfo _playerQuestControllerField;
|
private static FieldInfo _playerQuestControllerField;
|
||||||
@ -40,7 +37,7 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPrefix]
|
[PatchPrefix]
|
||||||
public static bool PatchPrefix()
|
private static bool PatchPrefix()
|
||||||
{
|
{
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
var player = gameWorld.MainPlayer;
|
var player = gameWorld.MainPlayer;
|
||||||
|
@ -15,9 +15,8 @@ namespace Aki.Debugging.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.
|
||||||
// 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.
|
// For now, we do dirty patches to work around the lack of ObservedPlayerView, using Player instead.
|
||||||
public class BTRBotAttachPatch : ModulePatch
|
internal class BTRBotAttachPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
@ -25,20 +24,19 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPrefix]
|
[PatchPrefix]
|
||||||
public static bool PatchPrefix(object __instance, int btrBotId)
|
private static bool PatchPrefix(BTRTurretView __instance, int btrBotId)
|
||||||
{
|
{
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
var btrTurretView = (BTRTurretView)__instance;
|
|
||||||
|
|
||||||
var btrTurretViewTupleField = (ValueTuple<ObservedPlayerView, bool>)AccessTools.Field(btrTurretView.GetType(), "valueTuple_0")
|
var __instanceTupleField = (ValueTuple<ObservedPlayerView, bool>)AccessTools.Field(__instance.GetType(), "valueTuple_0")
|
||||||
.GetValue(btrTurretView);
|
.GetValue(__instance);
|
||||||
|
|
||||||
if (!btrTurretViewTupleField.Item2)
|
if (!__instanceTupleField.Item2)
|
||||||
{
|
{
|
||||||
var btrTurretViewMethod = AccessTools.Method(btrTurretView.GetType(), "method_1");
|
var __instanceMethod = AccessTools.Method(__instance.GetType(), "method_1");
|
||||||
btrTurretViewMethod.Invoke(btrTurretView, new object[] { btrBotId });
|
__instanceMethod.Invoke(__instance, new object[] { btrBotId });
|
||||||
}
|
}
|
||||||
if (!btrTurretViewTupleField.Item2)
|
if (!__instanceTupleField.Item2)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -50,12 +48,12 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var botRootTransform = btrTurretView.BotRoot;
|
var botRootTransform = __instance.BotRoot;
|
||||||
|
|
||||||
btrBot.Transform.position = botRootTransform.position;
|
btrBot.Transform.position = botRootTransform.position;
|
||||||
|
|
||||||
var aiFirearmController = btrBot.gameObject.GetComponent<Player.FirearmController>();
|
var firearmController = btrBot.gameObject.GetComponent<Player.FirearmController>();
|
||||||
var currentWeaponPrefab = (WeaponPrefab)AccessTools.Field(aiFirearmController.GetType(), "weaponPrefab_0").GetValue(aiFirearmController);
|
var currentWeaponPrefab = (WeaponPrefab)AccessTools.Field(firearmController.GetType(), "weaponPrefab_0").GetValue(firearmController);
|
||||||
currentWeaponPrefab.transform.position = botRootTransform.position;
|
currentWeaponPrefab.transform.position = botRootTransform.position;
|
||||||
|
|
||||||
btrBot.PlayerBones.Weapon_Root_Anim.SetPositionAndRotation(botRootTransform.position, botRootTransform.rotation);
|
btrBot.PlayerBones.Weapon_Root_Anim.SetPositionAndRotation(botRootTransform.position, botRootTransform.rotation);
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
using Aki.Reflection.Patching;
|
using Aki.Reflection.Patching;
|
||||||
|
using Comfort.Common;
|
||||||
|
using EFT;
|
||||||
|
using EFT.NextObservedPlayer;
|
||||||
using EFT.UI;
|
using EFT.UI;
|
||||||
using EFT.Vehicle;
|
using EFT.Vehicle;
|
||||||
using EFT;
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Comfort.Common;
|
|
||||||
using System;
|
|
||||||
using EFT.NextObservedPlayer;
|
|
||||||
|
|
||||||
namespace Aki.Debugging.BTR.Patches
|
namespace Aki.Debugging.BTR.Patches
|
||||||
{
|
{
|
||||||
@ -17,7 +18,7 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
// 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, 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, 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.
|
// For now, we do dirty patches to work around the lack of ObservedPlayerView, using Player instead.
|
||||||
public class BTRBotInitPatch : ModulePatch
|
internal class BTRBotInitPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
@ -25,56 +26,60 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPostfix]
|
[PatchPostfix]
|
||||||
public static void PatchPostfix(BTRTurretView __instance, int btrBotId, ref bool __result)
|
private static void PatchPostfix(BTRTurretView __instance, int btrBotId, ref bool __result)
|
||||||
{
|
{
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
|
if (gameWorld == null)
|
||||||
foreach (var playerKeyValue in gameWorld.allAlivePlayersByID)
|
|
||||||
{
|
{
|
||||||
if (playerKeyValue.Value.Id == btrBotId)
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var alivePlayersList = gameWorld.AllAlivePlayersList;
|
||||||
|
bool doesBtrBotExist = alivePlayersList.Exists(x => x.Id == btrBotId);
|
||||||
|
if (doesBtrBotExist)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
Player player = alivePlayersList.First(x => x.Id == btrBotId);
|
||||||
|
|
||||||
|
Renderer[] array = player.GetComponentsInChildren<Renderer>();
|
||||||
|
for (int i = 0; i < array.Length; i++)
|
||||||
{
|
{
|
||||||
Renderer[] array = playerKeyValue.Value.GetComponentsInChildren<Renderer>();
|
array[i].enabled = false;
|
||||||
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);
|
|
||||||
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(__instance.GetType(), "valueTuple_0");
|
|
||||||
btrTurretViewTupleField.SetValue(__instance, tuple);
|
|
||||||
|
|
||||||
__result = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
|
var aiFirearmController = player.gameObject.GetComponent<Player.FirearmController>();
|
||||||
|
var currentWeaponPrefab = (WeaponPrefab)AccessTools.Field(aiFirearmController.GetType(), "weaponPrefab_0").GetValue(aiFirearmController);
|
||||||
|
if (currentWeaponPrefab.RemoveChildrenOf != null)
|
||||||
{
|
{
|
||||||
ConsoleScreen.LogError("[AKI-BTR] BtrBot initialization failed, BtrBot will be visible ingame. Check logs.");
|
foreach (var text in currentWeaponPrefab.RemoveChildrenOf)
|
||||||
throw;
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tuple = new ValueTuple<ObservedPlayerView, bool>(new ObservedPlayerView(), true);
|
||||||
|
var btrTurretViewTupleField = AccessTools.Field(__instance.GetType(), "valueTuple_0");
|
||||||
|
btrTurretViewTupleField.SetValue(__instance, tuple);
|
||||||
|
|
||||||
|
__result = true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ConsoleScreen.LogError("[AKI-BTR] BtrBot initialization failed, BtrBot will be visible ingame. Check logs.");
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,11 @@ using Comfort.Common;
|
|||||||
using EFT;
|
using EFT;
|
||||||
using EFT.Vehicle;
|
using EFT.Vehicle;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Aki.Debugging.BTR.Patches
|
namespace Aki.Debugging.BTR.Patches
|
||||||
{
|
{
|
||||||
public class BTRExtractPassengersPatch : ModulePatch
|
internal class BTRExtractPassengersPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
@ -16,39 +15,32 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPrefix]
|
[PatchPrefix]
|
||||||
public static void PatchPrefix()
|
private static void PatchPrefix()
|
||||||
{
|
{
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
var player = gameWorld.MainPlayer;
|
var player = gameWorld.MainPlayer;
|
||||||
var btrManager = gameWorld.GetComponent<BTRManager>();
|
var btrManager = gameWorld.GetComponent<BTRManager>();
|
||||||
|
|
||||||
try
|
var btrSide = btrManager.LastInteractedBtrSide;
|
||||||
|
if (btrSide == null)
|
||||||
{
|
{
|
||||||
var btrSide = btrManager.LastInteractedBtrSide;
|
return;
|
||||||
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)
|
|
||||||
|
if (btrSide.TryGetCachedPlace(out byte b))
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogException(ex19);
|
var interactionBtrPacket = btrSide.GetInteractWithBtrPacket(b, EInteractionType.GoOut);
|
||||||
|
if (interactionBtrPacket.HasInteraction)
|
||||||
|
{
|
||||||
|
BTRView btrView = gameWorld.BtrController.BtrView;
|
||||||
|
if (btrView == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
btrManager.OnPlayerInteractDoor(interactionBtrPacket);
|
||||||
|
btrView.Interaction(player, interactionBtrPacket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
using Aki.Reflection.Patching;
|
using Aki.Reflection.Patching;
|
||||||
using Comfort.Common;
|
using Comfort.Common;
|
||||||
using EFT;
|
using EFT;
|
||||||
|
using EFT.GlobalEvents;
|
||||||
using EFT.Vehicle;
|
using EFT.Vehicle;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using GlobalEventHandler = GClass2909;
|
||||||
|
|
||||||
namespace Aki.Debugging.BTR.Patches
|
namespace Aki.Debugging.BTR.Patches
|
||||||
{
|
{
|
||||||
public class BTRInteractionPatch : ModulePatch
|
internal class BTRInteractionPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
@ -24,32 +25,33 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPostfix]
|
[PatchPostfix]
|
||||||
public static void PatchPostfix(object __instance, BTRSide btr, byte placeId, EInteractionType interaction)
|
private static void PatchPostfix(Player __instance, BTRSide btr, byte placeId, EInteractionType interaction)
|
||||||
{
|
{
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
var player = (Player)__instance;
|
|
||||||
var btrManager = gameWorld.GetComponent<BTRManager>();
|
var btrManager = gameWorld.GetComponent<BTRManager>();
|
||||||
|
|
||||||
try
|
var interactionBtrPacket = btr.GetInteractWithBtrPacket(placeId, interaction);
|
||||||
{
|
__instance.UpdateInteractionCast();
|
||||||
var interactionBtrPacket = btr.GetInteractWithBtrPacket(placeId, interaction);
|
|
||||||
player.UpdateInteractionCast();
|
|
||||||
|
|
||||||
if (interactionBtrPacket.HasInteraction)
|
// Prevent player from entering BTR when blacklisted
|
||||||
{
|
var btrBot = gameWorld.BtrController.BotShooterBtr;
|
||||||
BTRView btrView = gameWorld.BtrController.BtrView;
|
if (btrBot.BotsGroup.Enemies.ContainsKey(__instance))
|
||||||
if (btrView == null)
|
|
||||||
{
|
|
||||||
throw new NullReferenceException("BtrView not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
btrManager.OnPlayerInteractDoor(interactionBtrPacket);
|
|
||||||
btrView.Interaction(player, interactionBtrPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex19)
|
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogException(ex19);
|
// Notify player they are blacklisted from entering BTR
|
||||||
|
GlobalEventHandler.CreateEvent<BtrNotificationInteractionMessageEvent>().Invoke(__instance.Id, EBtrInteractionStatus.Blacklisted);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactionBtrPacket.HasInteraction)
|
||||||
|
{
|
||||||
|
BTRView btrView = gameWorld.BtrController.BtrView;
|
||||||
|
if (btrView == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
btrManager.OnPlayerInteractDoor(interactionBtrPacket);
|
||||||
|
btrView.Interaction(__instance, interactionBtrPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ using System.Reflection;
|
|||||||
|
|
||||||
namespace Aki.Debugging.BTR.Patches
|
namespace Aki.Debugging.BTR.Patches
|
||||||
{
|
{
|
||||||
public class BTRIsDoorsClosedPath : ModulePatch
|
internal class BTRIsDoorsClosedPath : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
@ -14,7 +14,7 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPrefix]
|
[PatchPrefix]
|
||||||
public static bool PatchPrefix(ref bool __result)
|
private static bool PatchPrefix(ref bool __result)
|
||||||
{
|
{
|
||||||
var serverSideBTR = Singleton<GameWorld>.Instance?.BtrController.BtrVehicle;
|
var serverSideBTR = Singleton<GameWorld>.Instance?.BtrController.BtrVehicle;
|
||||||
if (serverSideBTR == null)
|
if (serverSideBTR == null)
|
||||||
|
@ -10,7 +10,7 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a BTRManager component to the GameWorld game object when raid starts.
|
/// Adds a BTRManager component to the GameWorld game object when raid starts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BTRPatch : ModulePatch
|
internal class BTRPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
@ -18,7 +18,7 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPostfix]
|
[PatchPostfix]
|
||||||
public static void PatchPostfix()
|
private static void PatchPostfix()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
{
|
{
|
||||||
// The BTRManager MapPathsConfiguration loading depends on the game state being set to Starting
|
// The BTRManager MapPathsConfiguration loading depends on the game state being set to Starting
|
||||||
// so set it to Starting while the method is running, then reset it afterwards
|
// so set it to Starting while the method is running, then reset it afterwards
|
||||||
public class BTRPathLoadPatch : ModulePatch
|
internal class BTRPathLoadPatch : ModulePatch
|
||||||
{
|
{
|
||||||
private static PropertyInfo _statusProperty;
|
private static PropertyInfo _statusProperty;
|
||||||
private static GameStatus originalStatus;
|
private static GameStatus originalStatus;
|
||||||
@ -20,14 +20,14 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPrefix]
|
[PatchPrefix]
|
||||||
public static void PatchPrefix()
|
private static void PatchPrefix()
|
||||||
{
|
{
|
||||||
originalStatus = Singleton<AbstractGame>.Instance.Status;
|
originalStatus = Singleton<AbstractGame>.Instance.Status;
|
||||||
_statusProperty.SetValue(Singleton<AbstractGame>.Instance, GameStatus.Starting);
|
_statusProperty.SetValue(Singleton<AbstractGame>.Instance, GameStatus.Starting);
|
||||||
}
|
}
|
||||||
|
|
||||||
[PatchPostfix]
|
[PatchPostfix]
|
||||||
public static void PatchPostfix()
|
private static void PatchPostfix()
|
||||||
{
|
{
|
||||||
_statusProperty.SetValue(Singleton<AbstractGame>.Instance, originalStatus);
|
_statusProperty.SetValue(Singleton<AbstractGame>.Instance, originalStatus);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
using Aki.Debugging.BTR.Utils;
|
using Aki.Debugging.BTR.Utils;
|
||||||
using Aki.Reflection.Patching;
|
using Aki.Reflection.Patching;
|
||||||
using Aki.SinglePlayer.Utils.TraderServices;
|
using Aki.SinglePlayer.Utils.TraderServices;
|
||||||
using Comfort.Common;
|
|
||||||
using EFT;
|
|
||||||
using EFT.UI;
|
using EFT.UI;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Aki.Debugging.BTR.Patches
|
namespace Aki.Debugging.BTR.Patches
|
||||||
{
|
{
|
||||||
public class BTRTransferItemsPatch : ModulePatch
|
internal class BTRTransferItemsPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
@ -18,7 +16,7 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPostfix]
|
[PatchPostfix]
|
||||||
public static void PatchPostfix(bool ___bool_1)
|
private static void PatchPostfix(bool ___bool_1)
|
||||||
{
|
{
|
||||||
// Didn't extract items
|
// Didn't extract items
|
||||||
if (!___bool_1)
|
if (!___bool_1)
|
||||||
|
@ -6,20 +6,20 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Aki.Debugging.BTR.Patches
|
namespace Aki.Debugging.BTR.Patches
|
||||||
{
|
{
|
||||||
public class BTRTurretCanShootPatch : ModulePatch
|
internal class BTRTurretCanShootPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
return AccessTools.Method(typeof(BTRTurretServer), "method_1");
|
return AccessTools.Method(typeof(BTRTurretServer), nameof(BTRTurretServer.method_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[PatchPrefix]
|
[PatchPrefix]
|
||||||
public static bool PatchPrefix(BTRTurretServer __instance)
|
private static bool PatchPrefix(BTRTurretServer __instance)
|
||||||
{
|
{
|
||||||
Transform defaultTargetTransform = (Transform)AccessTools.Field(__instance.GetType(), "defaultTargetTransform").GetValue(__instance);
|
Transform defaultTargetTransform = (Transform)AccessTools.Field(__instance.GetType(), "defaultTargetTransform").GetValue(__instance);
|
||||||
|
|
||||||
bool flag = __instance.targetTransform != null && __instance.targetTransform != defaultTargetTransform;
|
bool flag = __instance.targetTransform != null && __instance.targetTransform != defaultTargetTransform;
|
||||||
bool flag2 = (bool)AccessTools.Method(__instance.GetType(), "method_2").Invoke(__instance, null);
|
bool flag2 = __instance.method_2();
|
||||||
bool flag3 = __instance.targetPosition != __instance.defaultAimingPosition;
|
bool flag3 = __instance.targetPosition != __instance.defaultAimingPosition;
|
||||||
|
|
||||||
var isCanShootProperty = AccessTools.DeclaredProperty(__instance.GetType(), nameof(__instance.IsCanShoot));
|
var isCanShootProperty = AccessTools.DeclaredProperty(__instance.GetType(), nameof(__instance.IsCanShoot));
|
||||||
|
@ -6,7 +6,7 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Aki.Debugging.BTR.Patches
|
namespace Aki.Debugging.BTR.Patches
|
||||||
{
|
{
|
||||||
public class BTRTurretDefaultAimingPositionPatch : ModulePatch
|
internal class BTRTurretDefaultAimingPositionPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
@ -14,7 +14,7 @@ namespace Aki.Debugging.BTR.Patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchPrefix]
|
[PatchPrefix]
|
||||||
public static bool PatchPrefix(BTRTurretServer __instance)
|
private static bool PatchPrefix(BTRTurretServer __instance)
|
||||||
{
|
{
|
||||||
__instance.defaultAimingPosition = Vector3.zero;
|
__instance.defaultAimingPosition = Vector3.zero;
|
||||||
|
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
using Aki.Common.Http;
|
using Comfort.Common;
|
||||||
using Comfort.Common;
|
|
||||||
using EFT;
|
using EFT;
|
||||||
using EFT.InventoryLogic;
|
using EFT.InventoryLogic;
|
||||||
using HarmonyLib;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
using static BackendConfigSettingsClass;
|
|
||||||
using TraderServiceClass = GClass1789;
|
|
||||||
|
|
||||||
namespace Aki.Debugging.BTR.Utils
|
namespace Aki.Debugging.BTR.Utils
|
||||||
{
|
{
|
||||||
@ -19,13 +11,6 @@ namespace Aki.Debugging.BTR.Utils
|
|||||||
public static readonly string BTRMachineGunWeaponTplId = "657857faeff4c850222dff1b"; // BTR PKTM machine gun
|
public static readonly string BTRMachineGunWeaponTplId = "657857faeff4c850222dff1b"; // BTR PKTM machine gun
|
||||||
public static readonly string BTRMachineGunAmmoTplId = "5e023d34e8a400319a28ed44"; // 7.62x54mmR BT
|
public static readonly string BTRMachineGunAmmoTplId = "5e023d34e8a400319a28ed44"; // 7.62x54mmR BT
|
||||||
|
|
||||||
static BTRUtil()
|
|
||||||
{
|
|
||||||
// Sanity checks for compile time failure in the event the GClass changes
|
|
||||||
_ = nameof(TraderServiceClass.CanAfford);
|
|
||||||
_ = nameof(TraderServiceClass.WasPurchasedInThisRaid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to create an instance of the item in-raid.
|
/// Used to create an instance of the item in-raid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
using Aki.Common.Http;
|
using Aki.Common.Http;
|
||||||
using Comfort.Common;
|
using Comfort.Common;
|
||||||
using EFT;
|
using EFT;
|
||||||
using HarmonyLib;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using static BackendConfigSettingsClass;
|
using static BackendConfigSettingsClass;
|
||||||
using TraderServiceClass = GClass1789;
|
using TraderServiceClass = GClass1789;
|
||||||
@ -14,7 +12,10 @@ namespace Aki.SinglePlayer.Utils.TraderServices
|
|||||||
{
|
{
|
||||||
public class TraderServicesManager
|
public class TraderServicesManager
|
||||||
{
|
{
|
||||||
public event Action<ETraderServiceType> OnTraderServicePurchased; // Subscribe to this event to trigger trader service logic
|
/// <summary>
|
||||||
|
/// Subscribe to this event to trigger trader service logic.
|
||||||
|
/// </summary>
|
||||||
|
public event Action<ETraderServiceType> OnTraderServicePurchased;
|
||||||
|
|
||||||
private static TraderServicesManager _instance;
|
private static TraderServicesManager _instance;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user