Bindable headlights, nvg; toggle/hold applies
This commit is contained in:
@@ -19,6 +19,7 @@ global using ItemSorter = GClass2772;
|
||||
global using ItemWithLocation = GClass2521;
|
||||
global using SearchableGrid = GClass2516;
|
||||
global using CursorManager = GClass3034;
|
||||
global using Helmet = GClass2651;
|
||||
|
||||
// State machine states
|
||||
global using FirearmReadyState = EFT.Player.FirearmController.GClass1619;
|
||||
|
@@ -74,15 +74,7 @@ public static class AimToggleHoldPatches
|
||||
[PatchPostfix]
|
||||
public static void Postfix(ToggleKeyCombination __instance, EGameKey gameKey, ECommand command, KeyCombination.KeyCombinationState[] ___keyCombinationState_1)
|
||||
{
|
||||
bool useToggleHold = gameKey switch
|
||||
{
|
||||
EGameKey.Tactical => Settings.ToggleOrHoldTactical.Value,
|
||||
EGameKey.ToggleGoggles => Settings.ToggleOrHoldGoggles.Value,
|
||||
EGameKey.ToggleHeadLight => Settings.ToggleOrHoldHeadlight.Value,
|
||||
_ => false
|
||||
};
|
||||
|
||||
if (!useToggleHold)
|
||||
if (!UseToggleHold(gameKey))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -108,23 +100,44 @@ public static class AimToggleHoldPatches
|
||||
[PatchPostfix]
|
||||
public static void Postfix(KeyCombination __instance)
|
||||
{
|
||||
bool useToggleHold = __instance.GameKey switch
|
||||
{
|
||||
EGameKey.Aim => Settings.ToggleOrHoldAim.Value,
|
||||
EGameKey.Tactical => Settings.ToggleOrHoldTactical.Value,
|
||||
EGameKey.ToggleGoggles => Settings.ToggleOrHoldGoggles.Value,
|
||||
EGameKey.ToggleHeadLight => Settings.ToggleOrHoldHeadlight.Value,
|
||||
EGameKey.Sprint => Settings.ToggleOrHoldSprint.Value,
|
||||
_ => false
|
||||
};
|
||||
|
||||
if (useToggleHold)
|
||||
if (UseToggleHold(__instance.GameKey))
|
||||
{
|
||||
__instance.method_0((KeyCombination.EKeyState)ToggleHoldState.Idle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool UseToggleHold(EGameKey gameKey)
|
||||
{
|
||||
return gameKey switch
|
||||
{
|
||||
EGameKey.Aim => Settings.ToggleOrHoldAim.Value,
|
||||
EGameKey.Tactical => Settings.ToggleOrHoldTactical.Value,
|
||||
EGameKey.ToggleGoggles => Settings.ToggleOrHoldGoggles.Value,
|
||||
EGameKey.ToggleHeadLight => Settings.ToggleOrHoldHeadlight.Value,
|
||||
EGameKey.Sprint => Settings.ToggleOrHoldSprint.Value,
|
||||
EGameKey.Slot4 => UseToggleHoldQuickBind(EGameKey.Slot4),
|
||||
EGameKey.Slot5 => UseToggleHoldQuickBind(EGameKey.Slot5),
|
||||
EGameKey.Slot6 => UseToggleHoldQuickBind(EGameKey.Slot6),
|
||||
EGameKey.Slot7 => UseToggleHoldQuickBind(EGameKey.Slot7),
|
||||
EGameKey.Slot8 => UseToggleHoldQuickBind(EGameKey.Slot8),
|
||||
EGameKey.Slot9 => UseToggleHoldQuickBind(EGameKey.Slot9),
|
||||
EGameKey.Slot0 => UseToggleHoldQuickBind(EGameKey.Slot0),
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
private static bool UseToggleHoldQuickBind(EGameKey gameKey)
|
||||
{
|
||||
return Quickbind.GetType(gameKey) switch
|
||||
{
|
||||
Quickbind.ItemType.Tactical => Settings.ToggleOrHoldTactical.Value,
|
||||
Quickbind.ItemType.Headlight => Settings.ToggleOrHoldHeadlight.Value,
|
||||
Quickbind.ItemType.NightVision => Settings.ToggleOrHoldGoggles.Value,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
private static void OnSettingChanged(object sender, EventArgs args)
|
||||
{
|
||||
// Will "save" control settings, running GClass1911.UpdateInput, which will set (or unset) toggle/hold behavior
|
||||
|
@@ -1,9 +1,13 @@
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.InputSystem;
|
||||
using EFT.InventoryLogic;
|
||||
using HarmonyLib;
|
||||
using SPT.Reflection.Patching;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UIFixes;
|
||||
@@ -15,6 +19,10 @@ public static class TacticalBindsPatches
|
||||
new BindableTacticalPatch().Enable();
|
||||
new ReachableTacticalPatch().Enable();
|
||||
new UseTacticalPatch().Enable();
|
||||
|
||||
new BindTacticalPatch().Enable();
|
||||
new UnbindTacticalPatch().Enable();
|
||||
new InitQuickBindsPatch().Enable();
|
||||
}
|
||||
|
||||
public class BindableTacticalPatch : ModulePatch
|
||||
@@ -72,20 +80,33 @@ public static class TacticalBindsPatches
|
||||
}
|
||||
|
||||
LightComponent lightComponent = boundItem.GetItemComponent<LightComponent>();
|
||||
if (lightComponent == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't return true past this point; if the default handler tries to use a tactical device, very bad things happen
|
||||
|
||||
if (__instance.HandsController is not Player.FirearmController firearmController ||
|
||||
firearmController.Item != boundItem.GetRootItem())
|
||||
if (lightComponent != null)
|
||||
{
|
||||
ToggleLight(__instance, boundItem, lightComponent);
|
||||
callback(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
NightVisionComponent nightVisionComponent = boundItem.GetItemComponent<NightVisionComponent>();
|
||||
if (nightVisionComponent != null)
|
||||
{
|
||||
Item rootItem = boundItem.GetRootItemNotEquipment();
|
||||
if (rootItem is Helmet helmet &&
|
||||
__instance.Inventory.Equipment.GetSlot(EquipmentSlot.Headwear).ContainedItem == helmet)
|
||||
{
|
||||
__instance.InventoryControllerClass.TryRunNetworkTransaction(
|
||||
nightVisionComponent.Togglable.Set(!nightVisionComponent.Togglable.On, true, false));
|
||||
}
|
||||
|
||||
callback(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ToggleLight(Player player, Item boundItem, LightComponent lightComponent)
|
||||
{
|
||||
FirearmLightStateStruct lightState = new()
|
||||
{
|
||||
Id = lightComponent.Item.Id,
|
||||
@@ -102,24 +123,96 @@ public static class TacticalBindsPatches
|
||||
lightState.IsActive = !lightState.IsActive;
|
||||
}
|
||||
|
||||
firearmController.SetLightsState([lightState], false);
|
||||
Item rootItem = boundItem.GetRootItemNotEquipment();
|
||||
if (rootItem is Weapon weapon &&
|
||||
player.HandsController is Player.FirearmController firearmController &&
|
||||
firearmController.Item == weapon)
|
||||
{
|
||||
firearmController.SetLightsState([lightState], false);
|
||||
}
|
||||
|
||||
callback(null);
|
||||
return false;
|
||||
if (rootItem is Helmet helmet &&
|
||||
player.Inventory.Equipment.GetSlot(EquipmentSlot.Headwear).ContainedItem == helmet)
|
||||
{
|
||||
lightComponent.SetLightState(lightState);
|
||||
player.SendHeadlightsPacket(false);
|
||||
player.SwitchHeadLightsAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InitQuickBindsPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(MainMenuController), nameof(MainMenuController.method_5));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static async void Postfix(MainMenuController __instance, Task __result)
|
||||
{
|
||||
await __result;
|
||||
|
||||
for (EBoundItem index = EBoundItem.Item4; index <= EBoundItem.Item10; index++)
|
||||
{
|
||||
if (__instance.InventoryController.Inventory.FastAccess.BoundItems.ContainsKey(index))
|
||||
{
|
||||
UpdateQuickbindType(__instance.InventoryController.Inventory.FastAccess.BoundItems[index], index);
|
||||
}
|
||||
}
|
||||
|
||||
// Will "save" control settings, running GClass1911.UpdateInput, which will set (or unset) toggle/hold behavior
|
||||
Singleton<SharedGameSettingsClass>.Instance.Control.Controller.method_3();
|
||||
}
|
||||
}
|
||||
|
||||
public class BindTacticalPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(GClass2818), nameof(GClass2818.Run));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void Postfix(InventoryControllerClass controller, Item item, EBoundItem index)
|
||||
{
|
||||
UpdateQuickbindType(item, index);
|
||||
|
||||
// Will "save" control settings, running GClass1911.UpdateInput, which will set (or unset) toggle/hold behavior
|
||||
Singleton<SharedGameSettingsClass>.Instance.Control.Controller.method_3();
|
||||
}
|
||||
}
|
||||
|
||||
public class UnbindTacticalPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(GClass2819), nameof(GClass2819.Run));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void Postfix(InventoryControllerClass controller, Item item, EBoundItem index)
|
||||
{
|
||||
Quickbind.SetType(index, Quickbind.ItemType.Other);
|
||||
|
||||
// Will "save" control settings, running GClass1911.UpdateInput, which will set (or unset) toggle/hold behavior
|
||||
Singleton<SharedGameSettingsClass>.Instance.Control.Controller.method_3();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsEquippedTacticalDevice(InventoryControllerClass inventoryController, Item item)
|
||||
{
|
||||
LightComponent lightComponent = item.GetItemComponent<LightComponent>();
|
||||
if (lightComponent == null)
|
||||
NightVisionComponent nightVisionComponent = item.GetItemComponent<NightVisionComponent>();
|
||||
if (lightComponent == null && nightVisionComponent == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.GetRootItem() is Weapon weapon)
|
||||
Item rootItem = item.GetRootItemNotEquipment();
|
||||
if (rootItem is Weapon || rootItem is Helmet)
|
||||
{
|
||||
return inventoryController.Inventory.Equipment.Contains(weapon);
|
||||
return inventoryController.Inventory.Equipment.Contains(rootItem);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -135,4 +228,75 @@ public static class TacticalBindsPatches
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
private static void UpdateQuickbindType(Item item, EBoundItem index)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
Quickbind.SetType(index, Quickbind.ItemType.Other);
|
||||
return;
|
||||
}
|
||||
|
||||
LightComponent lightComponent = item.GetItemComponent<LightComponent>();
|
||||
if (lightComponent != null)
|
||||
{
|
||||
Item rootItem = item.GetRootItemNotEquipment();
|
||||
if (rootItem is Weapon)
|
||||
{
|
||||
Quickbind.SetType(index, Quickbind.ItemType.Tactical);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rootItem is Helmet)
|
||||
{
|
||||
Quickbind.SetType(index, Quickbind.ItemType.Headlight);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NightVisionComponent nvComponent = item.GetItemComponent<NightVisionComponent>();
|
||||
if (nvComponent != null)
|
||||
{
|
||||
Quickbind.SetType(index, Quickbind.ItemType.NightVision);
|
||||
return;
|
||||
}
|
||||
|
||||
Quickbind.SetType(index, Quickbind.ItemType.Other);
|
||||
}
|
||||
|
||||
private static Item GetRootItemNotEquipment(this Item item)
|
||||
{
|
||||
return item.GetAllParentItemsAndSelf(true).LastOrDefault(i => i is not EquipmentClass) ?? item;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Quickbind
|
||||
{
|
||||
public enum ItemType
|
||||
{
|
||||
Other,
|
||||
Tactical,
|
||||
Headlight,
|
||||
NightVision
|
||||
}
|
||||
|
||||
private static readonly Dictionary<EBoundItem, ItemType> TacticalQuickbinds = new()
|
||||
{
|
||||
{ EBoundItem.Item4, ItemType.Other },
|
||||
{ EBoundItem.Item5, ItemType.Other },
|
||||
{ EBoundItem.Item6, ItemType.Other },
|
||||
{ EBoundItem.Item7, ItemType.Other },
|
||||
{ EBoundItem.Item8, ItemType.Other },
|
||||
{ EBoundItem.Item9, ItemType.Other },
|
||||
{ EBoundItem.Item10, ItemType.Other },
|
||||
};
|
||||
|
||||
public static ItemType GetType(EBoundItem index) => TacticalQuickbinds[index];
|
||||
public static void SetType(EBoundItem index, ItemType type) => TacticalQuickbinds[index] = type;
|
||||
|
||||
public static ItemType GetType(EGameKey gameKey)
|
||||
{
|
||||
int offset = gameKey - EGameKey.Slot4;
|
||||
return GetType(EBoundItem.Item4 + offset);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user