ClientMods/ItemContextMenuExt/ItemContextMenuExt.cs

168 lines
6.0 KiB
C#
Raw Normal View History

using Comfort.Common;
using EFT;
using EFT.InventoryLogic;
using EFT.UI;
using IcyClawz.CustomInteractions;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using ILightTemplate = GInterface310;
using GlobalEvents = GClass3040;
2024-03-05 22:48:21 +02:00
namespace IcyClawz.ItemContextMenuExt;
internal static class PlayerExtensions
{
2024-03-05 22:48:21 +02:00
private static readonly FieldInfo InventoryControllerField =
typeof(Player).GetField("_inventoryController", BindingFlags.NonPublic | BindingFlags.Instance);
2024-03-05 22:48:21 +02:00
public static InventoryControllerClass GetInventoryController(this Player player) =>
InventoryControllerField.GetValue(player) as InventoryControllerClass;
}
2024-03-05 22:48:21 +02:00
internal static class LightComponentExtensions
{
public static int GetModesCount(this LightComponent component) =>
((ILightTemplate)component.Item.Template).ModesCount;
}
internal sealed class CustomInteractionsProvider : IItemCustomInteractionsProvider
{
internal const string IconsPrefix = "Characteristics/Icons/";
internal static StaticIcons StaticIcons => EFTHardSettings.Instance.StaticIcons;
2024-03-05 22:48:21 +02:00
public IEnumerable<CustomInteraction> GetCustomInteractions(ItemUiContext uiContext, EItemViewType viewType, Item item)
{
2024-03-05 22:48:21 +02:00
if (viewType is not EItemViewType.Inventory)
yield break;
2024-03-05 22:48:21 +02:00
FireModeComponent fireModeComponent = item.GetItemComponent<FireModeComponent>();
if (fireModeComponent is not null)
{
2024-03-05 22:48:21 +02:00
// Firing mode
yield return new()
{
2024-03-05 22:48:21 +02:00
Caption = () => "Firing mode",
Icon = () => StaticIcons.GetAttributeIcon(EItemAttributeId.Weapon),
SubMenu = () => new FireModeSubMenu(uiContext, fireModeComponent),
Enabled = () => fireModeComponent.AvailableEFireModes.Length > 1,
Error = () => "This weapon is incapable of selective fire"
};
yield break;
}
LightComponent lightComponent = item.GetItemComponent<LightComponent>();
if (lightComponent is not null)
{
// Turn on/off
yield return new()
{
2024-03-05 22:48:21 +02:00
Caption = () => (lightComponent.IsActive ? "TurnOff" : "TurnOn").Localized(),
Icon = () => CacheResourcesPopAbstractClass.Pop<Sprite>(IconsPrefix + (lightComponent.IsActive ? "TurnOff" : "TurnOn")),
2024-03-05 22:48:21 +02:00
Action = () =>
{
2024-03-05 22:48:21 +02:00
Singleton<GUISounds>.Instance.PlayUISound(EUISoundType.MenuContextMenu);
ComponentUtils.SetLightState(lightComponent, !lightComponent.IsActive, lightComponent.SelectedMode);
GlobalEvents.RequestGlobalRedraw();
}
2024-03-05 22:48:21 +02:00
};
// Switch mode
yield return new()
{
2024-03-05 22:48:21 +02:00
Caption = () => "Switch mode",
Icon = () => StaticIcons.GetAttributeIcon(EItemAttributeId.EncodeState),
SubMenu = () => new LightModeSubMenu(uiContext, lightComponent),
Enabled = () => lightComponent.GetModesCount() > 1,
Error = () => "This device has no alternative modes"
};
yield break;
}
}
2024-03-05 22:48:21 +02:00
}
2024-03-05 22:48:21 +02:00
internal class FireModeSubMenu : CustomSubInteractions
{
public FireModeSubMenu(ItemUiContext uiContext, FireModeComponent component)
: base(uiContext)
{
2024-03-05 22:48:21 +02:00
AddRange(component.AvailableEFireModes.Select(fireMode => new CustomInteraction()
{
2024-03-05 22:48:21 +02:00
Caption = () => fireMode.ToString().Localized(),
Action = () =>
{
2024-03-05 22:48:21 +02:00
Singleton<GUISounds>.Instance.PlayUISound(EUISoundType.MenuContextMenu);
ComponentUtils.SetFireMode(component, fireMode);
},
Enabled = () => fireMode != component.FireMode
}));
}
2024-03-05 22:48:21 +02:00
}
2024-03-05 22:48:21 +02:00
internal class LightModeSubMenu : CustomSubInteractions
{
public LightModeSubMenu(ItemUiContext uiContext, LightComponent component)
: base(uiContext)
{
2024-03-05 22:48:21 +02:00
AddRange(Enumerable.Range(0, component.GetModesCount()).Select(lightMode => new CustomInteraction()
{
2024-03-05 22:48:21 +02:00
Caption = () => $"Mode {lightMode + 1}",
Action = () =>
{
2024-03-05 22:48:21 +02:00
Singleton<GUISounds>.Instance.PlayUISound(EUISoundType.MenuContextMenu);
ComponentUtils.SetLightState(component, component.IsActive, lightMode);
},
Enabled = () => lightMode != component.SelectedMode
}));
}
2024-03-05 22:48:21 +02:00
}
2024-03-05 22:48:21 +02:00
internal static class ComponentUtils
{
public static void SetFireMode(FireModeComponent component, Weapon.EFireMode fireMode)
{
2024-03-05 22:48:21 +02:00
Player player = GamePlayerOwner.MyPlayer;
if (player is not null && player.HandsController is Player.FirearmController fc && component.Item == fc.Item)
{
2024-03-05 22:48:21 +02:00
if (fc.Item.MalfState.State is not Weapon.EMalfunctionState.None)
{
2024-03-05 22:48:21 +02:00
fc.FirearmsAnimator.MisfireSlideUnknown(false);
player.GetInventoryController().ExamineMalfunction(fc.Item, false);
return;
}
2024-03-05 22:48:21 +02:00
fc.ChangeFireMode(fireMode);
return;
}
2024-03-05 22:48:21 +02:00
component.SetFireMode(fireMode);
}
public static void SetLightState(LightComponent component, bool isActive, int lightMode)
{
Player player = GamePlayerOwner.MyPlayer;
if (player is not null && player.HandsController is Player.FirearmController fc && component.Item.IsChildOf(fc.Item))
{
2024-03-05 22:48:21 +02:00
fc.SetLightsState([new() { Id = component.Item.Id, IsActive = isActive, LightMode = lightMode }]);
return;
}
2024-03-05 22:48:21 +02:00
component.IsActive = isActive;
component.SelectedMode = lightMode;
2024-03-05 22:48:21 +02:00
if (player is not null)
{
foreach (TacticalComboVisualController tcvc in player.GetComponentsInChildren<TacticalComboVisualController>())
{
2024-03-05 22:48:21 +02:00
if (ReferenceEquals(tcvc.LightMod, component))
{
2024-03-05 22:48:21 +02:00
tcvc.UpdateBeams();
break;
}
}
}
}
}