ClientMods/ItemContextMenuExt/ItemContextMenuExt.cs

185 lines
7.0 KiB
C#

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 = GInterface252;
using LightsState = GStruct154;
using ResourceCache = GClass2076;
namespace IcyClawz.ItemContextMenuExt
{
internal static class PlayerExtensions
{
private static readonly FieldInfo InventoryControllerField =
typeof(Player).GetField("_inventoryController", BindingFlags.NonPublic | BindingFlags.Instance);
public static InventoryControllerClass GetInventoryController(this Player player) =>
InventoryControllerField.GetValue(player) as InventoryControllerClass;
}
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;
public IEnumerable<CustomInteraction> GetCustomInteractions(ItemUiContext uiContext, EItemViewType viewType, Item item)
{
if (viewType != EItemViewType.Inventory)
{
yield break;
}
{
var component = item.GetItemComponent<FireModeComponent>();
if (component != null)
{
// Firing mode
yield return new CustomInteraction()
{
Caption = () => "Firing mode",
Icon = () => StaticIcons.GetAttributeIcon(EItemAttributeId.Weapon),
SubMenu = () => new FireModeSubMenu(uiContext, component),
Enabled = () => component.AvailableEFireModes.Length > 1,
Error = () => "This weapon is incapable of selective fire"
};
yield break;
}
}
{
var component = item.GetItemComponent<LightComponent>();
if (component != null)
{
// Turn on/off
yield return new CustomInteraction()
{
Caption = () => (component.IsActive ? "TurnOff" : "TurnOn").Localized(),
Icon = () => ResourceCache.Pop<Sprite>(IconsPrefix + (component.IsActive ? "TurnOff" : "TurnOn")),
Action = () =>
{
Singleton<GUISounds>.Instance.PlayUISound(EUISoundType.MenuContextMenu);
ComponentUtils.SetLightState(component, !component.IsActive, component.SelectedMode);
uiContext.RedrawContextMenus(new[] { item.TemplateId });
}
};
// Switch mode
yield return new CustomInteraction()
{
Caption = () => "Switch mode",
Icon = () => StaticIcons.GetAttributeIcon(EItemAttributeId.EncodeState),
SubMenu = () => new LightModeSubMenu(uiContext, component),
Enabled = () => component.GetModesCount() > 1,
Error = () => "This device has no alternative modes"
};
yield break;
}
}
}
}
internal class FireModeSubMenu : CustomSubInteractions
{
public FireModeSubMenu(ItemUiContext uiContext, FireModeComponent component)
: base(uiContext)
{
foreach (var fireMode in component.AvailableEFireModes)
{
Add(new CustomInteraction()
{
Caption = () => fireMode.ToString().Localized(),
Action = () =>
{
Singleton<GUISounds>.Instance.PlayUISound(EUISoundType.MenuContextMenu);
ComponentUtils.SetFireMode(component, fireMode);
},
Enabled = () => fireMode != component.FireMode
});
}
}
}
internal class LightModeSubMenu : CustomSubInteractions
{
public LightModeSubMenu(ItemUiContext uiContext, LightComponent component)
: base(uiContext)
{
foreach (var lightMode in Enumerable.Range(0, component.GetModesCount()))
{
Add(new CustomInteraction()
{
Caption = () => $"Mode {lightMode + 1}",
Action = () =>
{
Singleton<GUISounds>.Instance.PlayUISound(EUISoundType.MenuContextMenu);
ComponentUtils.SetLightState(component, component.IsActive, lightMode);
},
Enabled = () => lightMode != component.SelectedMode
});
}
}
}
internal static class ComponentUtils
{
public static void SetFireMode(FireModeComponent component, Weapon.EFireMode fireMode)
{
var player = GamePlayerOwner.MyPlayer;
if (player != null && player.HandsController is Player.FirearmController fc && component.Item == fc.Item)
{
if (fc.Item.MalfState.State == Weapon.EMalfunctionState.None)
{
fc.ChangeFireMode(fireMode);
}
else
{
fc.FirearmsAnimator.MisfireSlideUnknown(false);
player.GetInventoryController().ExamineMalfunction(fc.Item, false);
}
return;
}
component.SetFireMode(fireMode);
}
public static void SetLightState(LightComponent component, bool isActive, int lightMode)
{
var player = GamePlayerOwner.MyPlayer;
if (player != null && player.HandsController is Player.FirearmController fc && component.Item.IsChildOf(fc.Item))
{
var state = new LightsState
{
Id = component.Item.Id,
IsActive = isActive,
LightMode = lightMode
};
fc.SetLightsState(new[] { state });
return;
}
component.IsActive = isActive;
component.SelectedMode = lightMode;
if (player != null)
{
foreach (var tcvc in player.GetComponentsInChildren<TacticalComboVisualController>())
{
if (ReferenceEquals(tcvc.LightMod, component))
{
tcvc.UpdateBeams();
break;
}
}
}
}
}
}