diff --git a/CustomInteractions.Prepatch/CustomInteractions.Prepatch.csproj b/CustomInteractions.Prepatch/CustomInteractions.Prepatch.csproj index ad6167f..cb33581 100644 --- a/CustomInteractions.Prepatch/CustomInteractions.Prepatch.csproj +++ b/CustomInteractions.Prepatch/CustomInteractions.Prepatch.csproj @@ -3,7 +3,7 @@ net472 IcyClawz.CustomInteractions.Prepatch - 1.5.0 + 1.6.0 IcyClawz.CustomInteractions latest diff --git a/CustomInteractions/CustomInteractions.cs b/CustomInteractions/CustomInteractions.cs index 5c3f09a..f76582f 100644 --- a/CustomInteractions/CustomInteractions.cs +++ b/CustomInteractions/CustomInteractions.cs @@ -4,21 +4,17 @@ using EFT.UI; using JetBrains.Annotations; using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Reflection; using UnityEngine; -using EmptyInteractionsAbstractClass = GClass3061; +using EmptyInteractionsAbstractClass = GClass3423; namespace IcyClawz.CustomInteractions; -[EditorBrowsable(EditorBrowsableState.Never)] -public interface ICustomInteractionsProvider { } // Do not implement this directly - -public interface IItemCustomInteractionsProvider : ICustomInteractionsProvider +public interface ICustomInteractionsProvider { - IEnumerable GetCustomInteractions(ItemUiContext uiContext, EItemViewType viewType, Item item); + IEnumerable GetCustomInteractions(ItemUiContext context, EItemViewType viewType, Item item); } public static class CustomInteractionsManager @@ -32,52 +28,35 @@ public static class CustomInteractionsManager } } -public class CustomInteraction() +public class CustomInteraction(ItemUiContext context) { - internal readonly CustomInteractionImpl Impl = new(UnityEngine.Random.Range(0, int.MaxValue).ToString("x4")); + internal readonly CustomInteractionImpl Impl = new(context, UnityEngine.Random.Range(0, int.MaxValue).ToString("x4")); public Func Caption { get => Impl.Caption; set => Impl.Caption = value; } public Func Icon { get => Impl.Icon; set => Impl.Icon = value; } public Action Action { get => Impl.Action; set => Impl.Action = value; } - public Func SubMenu { get => Impl.SubMenu; set => Impl.SubMenu = value; } + public Func> SubMenu { get => Impl.SubMenu; set => Impl.SubMenu = value; } public Func Enabled { get => Impl.Enabled; set => Impl.Enabled = value; } public Func Error { get => Impl.Error; set => Impl.Error = value; } } -internal sealed class CustomInteractionImpl(string id) : DynamicInteractionClass(id, id) +internal sealed class CustomInteractionImpl(ItemUiContext context, string id) : DynamicInteractionClass(id, id) { + internal readonly ItemUiContext Context = context; + public Func Caption { get; set; } public new Func Icon { get; set; } public Action Action { get => action_0; set => action_0 = value; } - public Func SubMenu { get; set; } + public Func> SubMenu { get; set; } public Func Enabled { get; set; } public Func Error { get; set; } public bool IsInteractive() => Enabled?.Invoke() ?? true; } -public abstract class CustomSubInteractions(ItemUiContext uiContext) -{ - internal readonly CustomSubInteractionsImpl Impl = new(uiContext); - - public bool ExaminationRequired - { - get => Impl.ExaminationRequiredInternal; - set => Impl.ExaminationRequiredInternal = value; - } - - public void Add(CustomInteraction interaction) => Impl.AddCustomInteraction(interaction); - public void AddRange(IEnumerable interactions) => interactions.ExecuteForEach(Impl.AddCustomInteraction); - public void Remove(CustomInteraction interaction) => Impl.RemoveCustomInteraction(interaction); - public void RemoveRange(IEnumerable interactions) => interactions.ExecuteForEach(Impl.RemoveCustomInteraction); -} - -internal sealed class CustomSubInteractionsImpl(ItemUiContext uiContext) : EmptyInteractionsAbstractClass(uiContext) +internal sealed class CustomInteractionsImpl(ItemUiContext context) : EmptyInteractionsAbstractClass(context) { public IEnumerable CustomInteractions => DynamicInteractions.OfType(); - - public bool ExaminationRequiredInternal { get; set; } = true; - public override bool ExaminationRequired => ExaminationRequiredInternal; public override bool HasIcons => CustomInteractions.Any(interaction => interaction.Icon is not null); } @@ -87,11 +66,8 @@ internal static class AbstractInteractionsExtensions typeof(ItemInfoInteractionsAbstractClass).GetField("dictionary_0", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(instance) as Dictionary; - public static void AddCustomInteraction(this ItemInfoInteractionsAbstractClass instance, CustomInteraction interaction) where T : struct, Enum => - instance.GetDynamicInteractions()[interaction.Impl.Key] = interaction.Impl; - - public static void RemoveCustomInteraction(this ItemInfoInteractionsAbstractClass instance, CustomInteraction interaction) where T : struct, Enum => - instance.GetDynamicInteractions().Remove(interaction.Impl.Key); + public static void AddCustomInteraction(this ItemInfoInteractionsAbstractClass instance, CustomInteractionImpl impl) where T : struct, Enum => + instance.GetDynamicInteractions()[impl.Key] = impl; } internal static class InteractionButtonsContainerExtensions @@ -140,6 +116,7 @@ internal static class InteractionButtonsContainerExtensions public static void AddCustomButton(this InteractionButtonsContainer instance, CustomInteractionImpl impl) { bool isInteractive = impl.IsInteractive(); + IEnumerable subMenu = impl.SubMenu?.Invoke(); SimpleContextMenuButton button = null; button = instance.CreateButton( impl.Key, @@ -156,14 +133,15 @@ internal static class InteractionButtonsContainerExtensions { instance.SetCurrentButton(button); instance.CloseSubMenu(); - if (isInteractive) + if (isInteractive && subMenu != null) { - CustomSubInteractions subMenu = impl.SubMenu?.Invoke(); - if (subMenu is not null) - instance.SetSubInteractions(subMenu.Impl); + CustomInteractionsImpl subInteractions = new CustomInteractionsImpl(impl.Context); + foreach (CustomInteractionImpl subImpl in subMenu.Select(item => item.Impl)) + subInteractions.AddCustomInteraction(subImpl); + instance.SetSubInteractions(subInteractions); } }, - impl.SubMenu is not null, + subMenu?.Any() ?? false, false ); button.SetButtonInteraction( diff --git a/CustomInteractions/CustomInteractions.csproj b/CustomInteractions/CustomInteractions.csproj index e9530d2..5803fb6 100644 --- a/CustomInteractions/CustomInteractions.csproj +++ b/CustomInteractions/CustomInteractions.csproj @@ -3,7 +3,7 @@ net472 IcyClawz.CustomInteractions - 1.5.0 + 1.6.0 IcyClawz.CustomInteractions latest diff --git a/CustomInteractions/Plugin.cs b/CustomInteractions/Plugin.cs index 585ac44..ef2083c 100644 --- a/CustomInteractions/Plugin.cs +++ b/CustomInteractions/Plugin.cs @@ -6,7 +6,7 @@ using System.Reflection; namespace IcyClawz.CustomInteractions; -[BepInPlugin("com.IcyClawz.CustomInteractions", "IcyClawz.CustomInteractions", "1.5.0")] +[BepInPlugin("com.IcyClawz.CustomInteractions", "IcyClawz.CustomInteractions", "1.6.0")] public class Plugin : BaseUnityPlugin { private void Awake() @@ -25,13 +25,13 @@ internal class ItemUiContextPatch : ModulePatch private static void Postfix(ref ItemInfoInteractionsAbstractClass __result, ref ItemUiContext __instance, ItemContextClass itemContext) { - foreach (var provider in CustomInteractionsManager.Providers.OfType()) + foreach (var provider in CustomInteractionsManager.Providers) { var interactions = provider.GetCustomInteractions(__instance, itemContext.ViewType, itemContext.Item); if (interactions is null) continue; - foreach (CustomInteraction interaction in interactions) - __result.AddCustomInteraction(interaction); + foreach (CustomInteractionImpl impl in interactions.Select(interaction => interaction.Impl)) + __result.AddCustomInteraction(impl); } } } diff --git a/ItemAttributeFix/ItemAttributeFix.csproj b/ItemAttributeFix/ItemAttributeFix.csproj index fe800a1..e9dc46d 100644 --- a/ItemAttributeFix/ItemAttributeFix.csproj +++ b/ItemAttributeFix/ItemAttributeFix.csproj @@ -3,7 +3,7 @@ net472 IcyClawz.ItemAttributeFix - 1.4.0 + 1.5.0 IcyClawz.ItemAttributeFix latest diff --git a/ItemAttributeFix/Plugin.cs b/ItemAttributeFix/Plugin.cs index 9535d5f..13def58 100644 --- a/ItemAttributeFix/Plugin.cs +++ b/ItemAttributeFix/Plugin.cs @@ -5,7 +5,7 @@ using System.Reflection; namespace IcyClawz.ItemAttributeFix; -[BepInPlugin("com.IcyClawz.ItemAttributeFix", "IcyClawz.ItemAttributeFix", "1.4.0")] +[BepInPlugin("com.IcyClawz.ItemAttributeFix", "IcyClawz.ItemAttributeFix", "1.5.0")] public class Plugin : BaseUnityPlugin { private void Awake() => diff --git a/ItemContextMenuExt/ItemContextMenuExt.cs b/ItemContextMenuExt/ItemContextMenuExt.cs index 7e3c695..0e8705f 100644 --- a/ItemContextMenuExt/ItemContextMenuExt.cs +++ b/ItemContextMenuExt/ItemContextMenuExt.cs @@ -5,116 +5,209 @@ using EFT.UI; using IcyClawz.CustomInteractions; using System.Collections.Generic; using System.Linq; -using System.Reflection; using UnityEngine; -using ILightTemplate = GInterface310; -using GlobalEvents = GClass3040; +using ILightTemplate = GInterface357; +using ISightTemplate = GInterface365; +using GlobalEvents = GClass3400; namespace IcyClawz.ItemContextMenuExt; -internal static class PlayerExtensions +internal static class SightComponentExtensions { - private static readonly FieldInfo InventoryControllerField = - typeof(Player).GetField("_inventoryController", BindingFlags.NonPublic | BindingFlags.Instance); + public static int[] GetScopeCalibrationDistances(this SightComponent instance, int scopeIndex) => + ((ISightTemplate)instance.Item.Template).CalibrationDistances[scopeIndex]; - public static InventoryControllerClass GetInventoryController(this Player player) => - InventoryControllerField.GetValue(player) as InventoryControllerClass; + public static float[] GetScopeZooms(this SightComponent instance, int scopeIndex) => + ((ISightTemplate)instance.Item.Template).Zooms[scopeIndex]; } internal static class LightComponentExtensions { - public static int GetModesCount(this LightComponent component) => - ((ILightTemplate)component.Item.Template).ModesCount; + public static int GetModesCount(this LightComponent instance) => + ((ILightTemplate)instance.Item.Template).ModesCount; } -internal sealed class CustomInteractionsProvider : IItemCustomInteractionsProvider +internal sealed class CustomInteractionsProvider : ICustomInteractionsProvider { - internal const string IconsPrefix = "Characteristics/Icons/"; - internal static StaticIcons StaticIcons => EFTHardSettings.Instance.StaticIcons; + private const string IconsPrefix = "Characteristics/Icons/"; + private static StaticIcons StaticIcons => EFTHardSettings.Instance.StaticIcons; - public IEnumerable GetCustomInteractions(ItemUiContext uiContext, EItemViewType viewType, Item item) + public IEnumerable GetCustomInteractions(ItemUiContext context, EItemViewType viewType, Item item) { - if (viewType is not EItemViewType.Inventory) - yield break; - - FireModeComponent fireModeComponent = item.GetItemComponent(); - if (fireModeComponent is not null) + if (viewType is EItemViewType.Inventory) { - // Firing mode - yield return new() + FireModeComponent fireModeComponent = item.GetItemComponent(); + if (fireModeComponent is not null) + return GetFireModeInteractions(context, fireModeComponent); + + SightComponent sightComponent = item.GetItemComponent(); + if (sightComponent is not null) + return GetSightInteractions(context, sightComponent); + + LightComponent lightComponent = item.GetItemComponent(); + if (lightComponent is not null) + return GetLightInteractions(context, lightComponent); + } + return []; + } + + private IEnumerable GetFireModeInteractions(ItemUiContext context, FireModeComponent component) + { + if (component.AvailableEFireModes.Length > 1) + { + yield return new(context) { 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", + SubMenu = () => GetFireModeSubInteractions(context, component), }; - yield break; } + } - LightComponent lightComponent = item.GetItemComponent(); - if (lightComponent is not null) + private IEnumerable GetFireModeSubInteractions(ItemUiContext context, FireModeComponent component) + { + foreach (Weapon.EFireMode fireMode in component.AvailableEFireModes) { - // Turn on/off - yield return new() + yield return new(context) { - Caption = () => (lightComponent.IsActive ? "TurnOff" : "TurnOn").Localized(), - Icon = () => CacheResourcesPopAbstractClass.Pop(IconsPrefix + (lightComponent.IsActive ? "TurnOff" : "TurnOn")), + Caption = () => fireMode.ToString().Localized(), Action = () => { Singleton.Instance.PlayUISound(EUISoundType.MenuContextMenu); - ComponentUtils.SetLightState(lightComponent, !lightComponent.IsActive, lightComponent.SelectedMode); - GlobalEvents.RequestGlobalRedraw(); + ComponentUtils.SetFireMode(component, fireMode); }, + Enabled = () => fireMode != component.FireMode, }; - // Switch mode - yield return new() - { - 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; } } -} -internal class FireModeSubMenu : CustomSubInteractions -{ - public FireModeSubMenu(ItemUiContext uiContext, FireModeComponent component) - : base(uiContext) + private IEnumerable GetSightInteractions(ItemUiContext context, SightComponent component) { - AddRange(component.AvailableEFireModes.Select(fireMode => new CustomInteraction() + if (component.ScopesCount > 1) { - Caption = () => fireMode.ToString().Localized(), - Action = () => + yield return new(context) { - Singleton.Instance.PlayUISound(EUISoundType.MenuContextMenu); - ComponentUtils.SetFireMode(component, fireMode); - }, - Enabled = () => fireMode != component.FireMode, - })); + Caption = () => "Active scope", + Icon = () => StaticIcons.GetAttributeIcon(EItemAttributeId.EncodeState), + SubMenu = () => GetScopeIndexSubInteractions(context, component), + }; + } + if (component.GetScopeModesCount(component.SelectedScope) > 1) + { + yield return new(context) + { + Caption = () => "Active mode", + Icon = () => StaticIcons.GetAttributeIcon(EItemAttributeId.EncodeState), + SubMenu = () => GetScopeModeSubInteractions(context, component), + }; + } + if (component.GetScopeCalibrationDistances(component.SelectedScope).Length > 1) + { + yield return new(context) + { + Caption = () => "Zero distance", + Icon = () => StaticIcons.GetAttributeIcon(EItemAttributeId.EncodeState), + SubMenu = () => GetScopeCalibSubInteractions(context, component), + }; + } } -} -internal class LightModeSubMenu : CustomSubInteractions -{ - public LightModeSubMenu(ItemUiContext uiContext, LightComponent component) - : base(uiContext) + private IEnumerable GetScopeIndexSubInteractions(ItemUiContext context, SightComponent component) { - AddRange(Enumerable.Range(0, component.GetModesCount()).Select(lightMode => new CustomInteraction() + foreach (int scopeIndex in Enumerable.Range(0, component.ScopesCount)) { - Caption = () => $"Mode {lightMode + 1}", + yield return new(context) + { + Caption = () => $"Scope {scopeIndex + 1}", + Action = () => + { + Singleton.Instance.PlayUISound(EUISoundType.MenuContextMenu); + ComponentUtils.SetScopeIndex(component, scopeIndex); + }, + Enabled = () => scopeIndex != component.SelectedScope, + }; + } + } + + private IEnumerable GetScopeModeSubInteractions(ItemUiContext context, SightComponent component) + { + int scopeIndex = component.SelectedScope; + float[] scopeZooms = component.GetScopeZooms(scopeIndex); + foreach (int scopeMode in Enumerable.Range(0, component.GetScopeModesCount(scopeIndex))) + { + float scopeZoom = scopeZooms.Length > 0 ? scopeZooms[scopeMode] : 0f; + yield return new(context) + { + Caption = () => $"Mode {scopeMode + 1} ({scopeZoom}x)", + Action = () => + { + Singleton.Instance.PlayUISound(EUISoundType.MenuContextMenu); + ComponentUtils.SetScopeMode(component, scopeMode); + }, + Enabled = () => scopeMode != component.ScopesSelectedModes[scopeIndex], + }; + } + } + + private IEnumerable GetScopeCalibSubInteractions(ItemUiContext context, SightComponent component) + { + int scopeIndex = component.SelectedScope; + int[] scopeCalibDistances = component.GetScopeCalibrationDistances(scopeIndex); + foreach (int scopeCalibIndex in Enumerable.Range(0, scopeCalibDistances.Length)) + { + yield return new(context) + { + Caption = () => $"{scopeCalibDistances[scopeCalibIndex]}", + Action = () => + { + Singleton.Instance.PlayUISound(EUISoundType.MenuContextMenu); + ComponentUtils.SetScopeCalibIndex(component, scopeCalibIndex); + }, + Enabled = () => scopeCalibIndex != component.ScopesCurrentCalibPointIndexes[scopeIndex], + }; + } + } + + private IEnumerable GetLightInteractions(ItemUiContext context, LightComponent component) + { + yield return new(context) + { + Caption = () => component.IsActive ? "Turn off" : "Turn on", + Icon = () => CacheResourcesPopAbstractClass.Pop(IconsPrefix + (component.IsActive ? "TurnOff" : "TurnOn")), Action = () => { Singleton.Instance.PlayUISound(EUISoundType.MenuContextMenu); - ComponentUtils.SetLightState(component, component.IsActive, lightMode); + ComponentUtils.SetLightActive(component, !component.IsActive); + GlobalEvents.RequestGlobalRedraw(); }, - Enabled = () => lightMode != component.SelectedMode, - })); + }; + if (component.GetModesCount() > 1) + { + yield return new(context) + { + Caption = () => "Active mode", + Icon = () => StaticIcons.GetAttributeIcon(EItemAttributeId.EncodeState), + SubMenu = () => GetLightModeSubInteractions(context, component), + }; + } + } + + private IEnumerable GetLightModeSubInteractions(ItemUiContext context, LightComponent component) + { + foreach (int lightMode in Enumerable.Range(0, component.GetModesCount())) + { + yield return new(context) + { + Caption = () => $"Mode {lightMode + 1}", + Action = () => + { + Singleton.Instance.PlayUISound(EUISoundType.MenuContextMenu); + ComponentUtils.SetLightMode(component, lightMode); + }, + Enabled = () => lightMode != component.SelectedMode, + }; + } } } @@ -126,31 +219,103 @@ internal static class ComponentUtils if (player is not null && player.HandsController is Player.FirearmController fc && component.Item == fc.Item) { - if (fc.Item.MalfState.State is Weapon.EMalfunctionState.None) - fc.ChangeFireMode(fireMode); - else + if (fc.Item.MalfState.State is not Weapon.EMalfunctionState.None) { fc.FirearmsAnimator.MisfireSlideUnknown(false); - player.GetInventoryController().ExamineMalfunction(fc.Item, false); + player.InventoryController.ExamineMalfunction(fc.Item, false); + return; } + + fc.ChangeFireMode(fireMode); return; } component.SetFireMode(fireMode); } - public static void SetLightState(LightComponent component, bool isActive, int lightMode) + public static void SetScopeIndex(SightComponent component, int scopeIndex) + { + SetScopeState(component, new() + { + Id = component.Item.Id, + ScopeIndexInsideSight = scopeIndex, + ScopeMode = component.ScopesSelectedModes[scopeIndex], + ScopeCalibrationIndex = component.ScopesCurrentCalibPointIndexes[scopeIndex], + }); + } + + public static void SetScopeMode(SightComponent component, int scopeMode) + { + int scopeIndex = component.SelectedScope; + SetScopeState(component, new() + { + Id = component.Item.Id, + ScopeIndexInsideSight = scopeIndex, + ScopeMode = scopeMode, + ScopeCalibrationIndex = component.ScopesCurrentCalibPointIndexes[scopeIndex], + }); + } + + public static void SetScopeCalibIndex(SightComponent component, int scopeCalibIndex) + { + int scopeIndex = component.SelectedScope; + SetScopeState(component, new() + { + Id = component.Item.Id, + ScopeIndexInsideSight = scopeIndex, + ScopeMode = component.ScopesSelectedModes[scopeIndex], + ScopeCalibrationIndex = scopeCalibIndex, + }); + } + + private static void SetScopeState(SightComponent component, FirearmScopeStateStruct scopeState) { Player player = GamePlayerOwner.MyPlayer; if (player is not null && player.HandsController is Player.FirearmController fc && component.Item.IsChildOf(fc.Item)) { - fc.SetLightsState([new() { Id = component.Item.Id, IsActive = isActive, LightMode = lightMode }]); + fc.SetScopeMode([scopeState]); return; } - component.IsActive = isActive; - component.SelectedMode = lightMode; + int scopeIndex = scopeState.ScopeIndexInsideSight; + component.SelectedScope = scopeIndex; + component.ScopesSelectedModes[scopeIndex] = scopeState.ScopeMode; + component.ScopesCurrentCalibPointIndexes[scopeIndex] = scopeState.ScopeCalibrationIndex; + } + + public static void SetLightActive(LightComponent component, bool isActive) + { + SetLightState(component, new() + { + Id = component.Item.Id, + IsActive = isActive, + LightMode = component.SelectedMode, + }); + } + + public static void SetLightMode(LightComponent component, int lightMode) + { + SetLightState(component, new() + { + Id = component.Item.Id, + IsActive = component.IsActive, + LightMode = lightMode, + }); + } + + private static void SetLightState(LightComponent component, FirearmLightStateStruct lightState) + { + Player player = GamePlayerOwner.MyPlayer; + + if (player is not null && player.HandsController is Player.FirearmController fc && component.Item.IsChildOf(fc.Item)) + { + fc.SetLightsState([lightState]); + return; + } + + component.IsActive = lightState.IsActive; + component.SelectedMode = lightState.LightMode; if (player is not null) { diff --git a/ItemContextMenuExt/ItemContextMenuExt.csproj b/ItemContextMenuExt/ItemContextMenuExt.csproj index 19d863c..ed0f33a 100644 --- a/ItemContextMenuExt/ItemContextMenuExt.csproj +++ b/ItemContextMenuExt/ItemContextMenuExt.csproj @@ -3,7 +3,7 @@ net472 IcyClawz.ItemContextMenuExt - 1.5.0 + 1.6.0 IcyClawz.ItemContextMenuExt latest @@ -27,6 +27,9 @@ ..\Shared\ItemTemplate.Types.dll + + ..\Shared\spt-reflection.dll + ..\Shared\UnityEngine.dll diff --git a/ItemContextMenuExt/Plugin.cs b/ItemContextMenuExt/Plugin.cs index 940b56c..8f3dfbd 100644 --- a/ItemContextMenuExt/Plugin.cs +++ b/ItemContextMenuExt/Plugin.cs @@ -1,12 +1,35 @@ using BepInEx; +using BepInEx.Configuration; +using EFT.UI; using IcyClawz.CustomInteractions; +using SPT.Reflection.Patching; +using System.Reflection; namespace IcyClawz.ItemContextMenuExt; -[BepInPlugin("com.IcyClawz.ItemContextMenuExt", "IcyClawz.ItemContextMenuExt", "1.5.0")] +[BepInPlugin("com.IcyClawz.ItemContextMenuExt", "IcyClawz.ItemContextMenuExt", "1.6.0")] [BepInDependency("com.IcyClawz.CustomInteractions")] public class Plugin : BaseUnityPlugin { - private void Awake() => + private static ConfigEntry ScaleConfig { get; set; } + + private void Awake() + { + const string SECTION = "Item Context Menu"; + ScaleConfig = Config.Bind(SECTION, "Scale", 1f); + new ItemUiContextPatch().Enable(); CustomInteractionsManager.Register(new CustomInteractionsProvider()); + } + + internal static float Scale => ScaleConfig.Value; +} + +internal class ItemUiContextPatch : ModulePatch +{ + protected override MethodBase GetTargetMethod() => + typeof(ItemUiContext).GetMethod("ShowContextMenu", BindingFlags.Public | BindingFlags.Instance); + + [PatchPostfix] + private static void Postfix(ref ItemUiContext __instance) => + __instance.ContextMenu.Transform.localScale = new(Plugin.Scale, Plugin.Scale); } diff --git a/ItemSellPrice/ItemSellPrice.cs b/ItemSellPrice/ItemSellPrice.cs index 2cfdbb0..47d6059 100644 --- a/ItemSellPrice/ItemSellPrice.cs +++ b/ItemSellPrice/ItemSellPrice.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Reflection; using UnityEngine; -using CurrencyUtil = GClass2531; +using CurrencyUtil = GClass2867; namespace IcyClawz.ItemSellPrice; @@ -91,7 +91,7 @@ internal static class ItemExtensions FullStringValue = () => { IEnumerable offers = GetAllTraderOffers(item); - return offers is not null + return offers.Any() ? string.Join(Environment.NewLine, offers.Select(offer => $"{offer.Name}: {offer.Currency} {offer.Price}")) : ""; }, @@ -111,20 +111,20 @@ internal static class ItemExtensions private static TraderOffer GetTraderOffer(Item item, TraderClass trader) { - var result = trader.GetUserItemPrice(item); - return result is null ? null : new( + var price = trader.GetUserItemPrice(item); + return price.HasValue ? new( trader.LocalizedName, - result.Value.Amount, - CurrencyUtil.GetCurrencyCharById(result.Value.CurrencyId), - trader.GetSupplyData().CurrencyCourses[result.Value.CurrencyId], + price.Value.Amount, + CurrencyUtil.GetCurrencyCharById(price.Value.CurrencyId.Value), + trader.GetSupplyData().CurrencyCourses[price.Value.CurrencyId.Value], item.StackObjectsCount - ); + ) : null; } private static IEnumerable GetAllTraderOffers(Item item) { if (!Session.Profile.Examined(item)) - return null; + return []; if (item.Owner?.OwnerType is EOwnerType.RagFair or EOwnerType.Trader && (item.StackObjectsCount > 1 || item.UnlimitedCount)) { @@ -133,11 +133,12 @@ internal static class ItemExtensions item.UnlimitedCount = false; } return Session.Traders + .Where(trader => !trader.Settings.AvailableInRaid) .Select(trader => GetTraderOffer(item, trader)) .Where(offer => offer is not null) .OrderByDescending(offer => offer.Price * offer.Course); } private static TraderOffer GetBestTraderOffer(Item item) => - GetAllTraderOffers(item)?.FirstOrDefault() ?? null; + GetAllTraderOffers(item).FirstOrDefault(); } \ No newline at end of file diff --git a/ItemSellPrice/ItemSellPrice.csproj b/ItemSellPrice/ItemSellPrice.csproj index f9a5d6e..de8b604 100644 --- a/ItemSellPrice/ItemSellPrice.csproj +++ b/ItemSellPrice/ItemSellPrice.csproj @@ -3,7 +3,7 @@ net472 IcyClawz.ItemSellPrice - 1.4.0 + 1.5.0 IcyClawz.ItemSellPrice latest diff --git a/ItemSellPrice/Plugin.cs b/ItemSellPrice/Plugin.cs index ecd1fb8..7f2d2c8 100644 --- a/ItemSellPrice/Plugin.cs +++ b/ItemSellPrice/Plugin.cs @@ -1,20 +1,20 @@ using BepInEx; +using EFT; using EFT.InventoryLogic; using SPT.Reflection.Patching; using System.Reflection; namespace IcyClawz.ItemSellPrice; -[BepInPlugin("com.IcyClawz.ItemSellPrice", "IcyClawz.ItemSellPrice", "1.4.0")] +[BepInPlugin("com.IcyClawz.ItemSellPrice", "IcyClawz.ItemSellPrice", "1.5.0")] public class Plugin : BaseUnityPlugin { private void Awake() { new TraderPatch().Enable(); new ItemPatch().Enable(); - new AmmoPatch().Enable(); - new GrenadePatch().Enable(); - new SecureContainerPatch().Enable(); + new AmmoItemPatch().Enable(); + new ThrowWeapItemPatch().Enable(); } } @@ -38,32 +38,22 @@ internal class ItemPatch : ModulePatch __instance.AddTraderOfferAttribute(); } -internal class AmmoPatch : ModulePatch +internal class AmmoItemPatch : ModulePatch { protected override MethodBase GetTargetMethod() => - typeof(BulletClass).GetConstructors()[0]; + typeof(AmmoItemClass).GetConstructors()[0]; [PatchPostfix] - private static void PatchPostfix(ref BulletClass __instance) => + private static void PatchPostfix(ref AmmoItemClass __instance) => __instance.AddTraderOfferAttribute(); } -internal class GrenadePatch : ModulePatch +internal class ThrowWeapItemPatch : ModulePatch { protected override MethodBase GetTargetMethod() => - typeof(GrenadeClass).GetConstructors()[0]; + typeof(ThrowWeapItemClass).GetConstructors()[0]; [PatchPostfix] - private static void PatchPostfix(ref GrenadeClass __instance) => - __instance.AddTraderOfferAttribute(); -} - -internal class SecureContainerPatch : ModulePatch -{ - protected override MethodBase GetTargetMethod() => - typeof(ItemContainerClass).GetConstructors()[0]; - - [PatchPostfix] - private static void PatchPostfix(ref ItemContainerClass __instance) => + private static void PatchPostfix(ref ThrowWeapItemClass __instance) => __instance.AddTraderOfferAttribute(); } diff --git a/MagazineInspector/MagazineInspector.cs b/MagazineInspector/MagazineInspector.cs index 88f77bc..5048b28 100644 --- a/MagazineInspector/MagazineInspector.cs +++ b/MagazineInspector/MagazineInspector.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; -using InGameStatus = GClass1864; +using InGameStatus = GClass2064; namespace IcyClawz.MagazineInspector; @@ -38,7 +38,7 @@ internal static class MagazineClassExtensions private static Profile ActiveProfile => InGameStatus.InRaid ? GamePlayerOwner.MyPlayer.Profile : Session.Profile; - public static void AddAmmoCountAttribute(this MagazineClass magazine) + public static void AddAmmoCountAttribute(this MagazineItemClass magazine) { ItemAttributeClass attribute = magazine.Attributes.Find(attr => attr.Id is EItemAttributeId.MaxCount); if (attribute is null) @@ -74,7 +74,7 @@ internal static class MagazineClassExtensions }; } - private static int? GetAmmoCount(MagazineClass magazine, Profile profile, out bool magChecked) + private static int? GetAmmoCount(MagazineItemClass magazine, Profile profile, out bool magChecked) { if (!InGameStatus.InRaid || magazine.Count == 0) { diff --git a/MagazineInspector/MagazineInspector.csproj b/MagazineInspector/MagazineInspector.csproj index 45bb251..6ffd351 100644 --- a/MagazineInspector/MagazineInspector.csproj +++ b/MagazineInspector/MagazineInspector.csproj @@ -3,7 +3,7 @@ net472 IcyClawz.MagazineInspector - 1.4.0 + 1.5.0 IcyClawz.MagazineInspector latest diff --git a/MagazineInspector/Plugin.cs b/MagazineInspector/Plugin.cs index 4686071..eaa1876 100644 --- a/MagazineInspector/Plugin.cs +++ b/MagazineInspector/Plugin.cs @@ -4,7 +4,7 @@ using System.Reflection; namespace IcyClawz.MagazineInspector; -[BepInPlugin("com.IcyClawz.MagazineInspector", "IcyClawz.MagazineInspector", "1.4.0")] +[BepInPlugin("com.IcyClawz.MagazineInspector", "IcyClawz.MagazineInspector", "1.5.0")] public class Plugin : BaseUnityPlugin { private void Awake() => @@ -14,9 +14,9 @@ public class Plugin : BaseUnityPlugin internal class MagazinePatch : ModulePatch { protected override MethodBase GetTargetMethod() => - typeof(MagazineClass).GetConstructors()[0]; + typeof(MagazineItemClass).GetConstructors()[0]; [PatchPostfix] - private static void PatchPostfix(ref MagazineClass __instance) => + private static void PatchPostfix(ref MagazineItemClass __instance) => __instance.AddAmmoCountAttribute(); } diff --git a/MunitionsExpert/MunitionsExpert.csproj b/MunitionsExpert/MunitionsExpert.csproj index 8a37dc7..1d29aeb 100644 --- a/MunitionsExpert/MunitionsExpert.csproj +++ b/MunitionsExpert/MunitionsExpert.csproj @@ -3,7 +3,7 @@ net472 IcyClawz.MunitionsExpert - 1.4.2 + 1.5.0 IcyClawz.MunitionsExpert latest diff --git a/MunitionsExpert/Plugin.cs b/MunitionsExpert/Plugin.cs index bb9c918..c1997ec 100644 --- a/MunitionsExpert/Plugin.cs +++ b/MunitionsExpert/Plugin.cs @@ -13,24 +13,24 @@ using UnityEngine.UI; namespace IcyClawz.MunitionsExpert; -[BepInPlugin("com.IcyClawz.MunitionsExpert", "IcyClawz.MunitionsExpert", "1.4.2")] +[BepInPlugin("com.IcyClawz.MunitionsExpert", "IcyClawz.MunitionsExpert", "1.5.0")] public class Plugin : BaseUnityPlugin { - private static ConfigEntry ColorizeSwitch { get; set; } - private static ConfigEntry[] ArmorClassColors { get; set; } + private static ConfigEntry ColorizeConfig { get; set; } + private static ConfigEntry[] ArmorClassColorConfigs { get; set; } private void Awake() { - const string COLORIZE = "Colorize Icon Backgrounds"; - ColorizeSwitch = Config.Bind(COLORIZE, "", true, new ConfigurationManagerAttributes { Order = 7 }); - ArmorClassColors = [ - Config.Bind(COLORIZE, "Unarmored", ColorName.Purple, new ConfigurationManagerAttributes { Order = 6 }), - Config.Bind(COLORIZE, "Class 1", ColorName.Blue, new ConfigurationManagerAttributes { Order = 5 }), - Config.Bind(COLORIZE, "Class 2", ColorName.Cyan, new ConfigurationManagerAttributes { Order = 4 }), - Config.Bind(COLORIZE, "Class 3", ColorName.Green, new ConfigurationManagerAttributes { Order = 3 }), - Config.Bind(COLORIZE, "Class 4", ColorName.Yellow, new ConfigurationManagerAttributes { Order = 2 }), - Config.Bind(COLORIZE, "Class 5", ColorName.Orange, new ConfigurationManagerAttributes { Order = 1 }), - Config.Bind(COLORIZE, "Class 6+", ColorName.Red, new ConfigurationManagerAttributes { Order = 0 }), + const string SECTION = "Colorize Icon Backgrounds"; + ColorizeConfig = Config.Bind(SECTION, "", true, new ConfigurationManagerAttributes { Order = 7 }); + ArmorClassColorConfigs = [ + Config.Bind(SECTION, "Unarmored", ColorName.Purple, new ConfigurationManagerAttributes { Order = 6 }), + Config.Bind(SECTION, "Class 1", ColorName.Blue, new ConfigurationManagerAttributes { Order = 5 }), + Config.Bind(SECTION, "Class 2", ColorName.Cyan, new ConfigurationManagerAttributes { Order = 4 }), + Config.Bind(SECTION, "Class 3", ColorName.Green, new ConfigurationManagerAttributes { Order = 3 }), + Config.Bind(SECTION, "Class 4", ColorName.Yellow, new ConfigurationManagerAttributes { Order = 2 }), + Config.Bind(SECTION, "Class 5", ColorName.Orange, new ConfigurationManagerAttributes { Order = 1 }), + Config.Bind(SECTION, "Class 6+", ColorName.Red, new ConfigurationManagerAttributes { Order = 0 }), ]; new StaticIconsPatch().Enable(); new AmmoTemplatePatch().Enable(); @@ -38,12 +38,12 @@ public class Plugin : BaseUnityPlugin new EntityIconPatch().Enable(); } - internal static bool Colorize => ColorizeSwitch.Value; + internal static bool Colorize => ColorizeConfig.Value; internal static Color GetArmorClassColor(int index) { - index = Mathf.Clamp(index, 0, ArmorClassColors.Length - 1); - return ColorCache.Get(ArmorClassColors[index].Value); + index = Mathf.Clamp(index, 0, ArmorClassColorConfigs.Length - 1); + return ColorCache.Get(ArmorClassColorConfigs[index].Value); } } @@ -87,9 +87,9 @@ internal class ItemViewPatch : ModulePatch [PatchPrefix] private static void PatchPrefix(ref ItemView __instance) { - if (!Plugin.Colorize || __instance.Item is not BulletClass bullet || bullet.PenetrationPower <= 0) + if (!Plugin.Colorize || __instance.Item is not AmmoItemClass ammo || ammo.PenetrationPower <= 0) return; - int armorClass = bullet.AmmoTemplate.GetPenetrationArmorClass(); + int armorClass = ammo.AmmoTemplate.GetPenetrationArmorClass(); BackgroundColorField.SetValue(__instance, Plugin.GetArmorClassColor(armorClass)); } } @@ -105,11 +105,11 @@ internal class EntityIconPatch : ModulePatch [PatchPostfix] private static void PatchPostfix(ref EntityIcon __instance, Item item) { - if (!Plugin.Colorize || item is not BulletClass bullet || bullet.PenetrationPower <= 0) + if (!Plugin.Colorize || item is not AmmoItemClass ammo || ammo.PenetrationPower <= 0) return; if (ColorPanelField.GetValue(__instance) is not Image image) return; - int armorClass = bullet.AmmoTemplate.GetPenetrationArmorClass(); + int armorClass = ammo.AmmoTemplate.GetPenetrationArmorClass(); image.color = Plugin.GetArmorClassColor(armorClass); } }