reload in place
This commit is contained in:
156
Patches/ReloadInPlacePatches.cs
Normal file
156
Patches/ReloadInPlacePatches.cs
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
using EFT;
|
||||||
|
using EFT.UI;
|
||||||
|
using HarmonyLib;
|
||||||
|
using SPT.Reflection.Patching;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace UIFixes;
|
||||||
|
|
||||||
|
public static class ReloadInPlacePatches
|
||||||
|
{
|
||||||
|
private static bool IsReloading = false;
|
||||||
|
private static MagazineClass FoundMagazine = null;
|
||||||
|
|
||||||
|
public static void Enable()
|
||||||
|
{
|
||||||
|
// These patch ItemUiContext.ReloadWeapon, which is called from the context menu Reload
|
||||||
|
new ReloadInPlacePatch().Enable();
|
||||||
|
new ReloadInPlaceFindMagPatch().Enable();
|
||||||
|
new ReloadInPlaceFindSpotPatch().Enable();
|
||||||
|
|
||||||
|
// This patches the firearmsController code when you hit R in raid with an external magazine class
|
||||||
|
new SwapIfNoSpacePatch().Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReloadInPlacePatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(ItemUiContext), nameof(ItemUiContext.ReloadWeapon));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPrefix]
|
||||||
|
public static void Prefix()
|
||||||
|
{
|
||||||
|
IsReloading = Settings.SwapMags.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
public static void Postfix()
|
||||||
|
{
|
||||||
|
IsReloading = false;
|
||||||
|
FoundMagazine = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReloadInPlaceFindMagPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(ItemUiContext), nameof(ItemUiContext.method_5));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
public static void Postfix(MagazineClass __result)
|
||||||
|
{
|
||||||
|
if (IsReloading)
|
||||||
|
{
|
||||||
|
FoundMagazine = __result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReloadInPlaceFindSpotPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
Type type = typeof(ItemUiContext).GetNestedTypes().Single(t => t.GetField("currentMagazine") != null);
|
||||||
|
return AccessTools.Method(type, "method_0");
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPrefix]
|
||||||
|
public static void Prefix(StashGridClass grid, ref GStruct414<GClass2801> __state)
|
||||||
|
{
|
||||||
|
if (!Settings.SwapMags.Value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grid.Contains(FoundMagazine))
|
||||||
|
{
|
||||||
|
__state = InteractionsHandlerClass.Remove(FoundMagazine, grid.ParentItem.Owner as TraderControllerClass, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
public static void Postfix(GStruct414<GClass2801> __state)
|
||||||
|
{
|
||||||
|
if (!Settings.SwapMags.Value || __state.Value == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__state.Succeeded)
|
||||||
|
{
|
||||||
|
__state.Value.RollBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SwapIfNoSpacePatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(Player.FirearmController), nameof(Player.FirearmController.ReloadMag));
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default this method will do a series of removes and adds, but not swap, to reload
|
||||||
|
// This tied to a different animation state machine sequence than Swap(), and is faster than Swap.
|
||||||
|
// So only use Swap if *needed*, otherwise its penalizing all reload speeds
|
||||||
|
[PatchPrefix]
|
||||||
|
public static bool Prefix(Player.FirearmController __instance, MagazineClass magazine, ItemAddressClass gridItemAddress)
|
||||||
|
{
|
||||||
|
// If gridItemAddress isn't null, it already found a place for the current mag, so let it run
|
||||||
|
if (gridItemAddress != null || !Settings.SwapMags.Value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Weapon doesn't currently have a magazine, let the default run (will load one)
|
||||||
|
MagazineClass currentMagazine = __instance.Weapon.GetCurrentMagazine();
|
||||||
|
if (currentMagazine == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryControllerClass controller = __instance.Weapon.Owner as InventoryControllerClass;
|
||||||
|
|
||||||
|
// Null address means it couldn't find a spot. Try to remove magazine (temporarily) and try again
|
||||||
|
var operation = InteractionsHandlerClass.Remove(magazine, controller, false, false);
|
||||||
|
if (operation.Failed)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
gridItemAddress = controller.Inventory.Equipment.GetPrioritizedGridsForUnloadedObject(false)
|
||||||
|
.Select(grid => grid.FindLocationForItem(currentMagazine))
|
||||||
|
.Where(address => address != null)
|
||||||
|
.OrderBy(address => address.Grid.GridWidth.Value * address.Grid.GridHeight.Value)
|
||||||
|
.FirstOrDefault(); // BSG's version checks null again, but there's no nulls already. If there's no matches, the enumerable is empty
|
||||||
|
|
||||||
|
// Put the magazine back
|
||||||
|
operation.Value.RollBack();
|
||||||
|
|
||||||
|
if (gridItemAddress == null)
|
||||||
|
{
|
||||||
|
// Didn't work, nowhere to put magazine. Let it run (will drop mag on ground)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.TryRunNetworkTransaction(InteractionsHandlerClass.Swap(currentMagazine, gridItemAddress, magazine, new GClass2783(__instance.Weapon.GetMagazineSlot()), controller, true), null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,6 +65,7 @@ public class Plugin : BaseUnityPlugin
|
|||||||
MoveSortingTablePatches.Enable();
|
MoveSortingTablePatches.Enable();
|
||||||
FilterOutOfStockPatches.Enable();
|
FilterOutOfStockPatches.Enable();
|
||||||
SortPatches.Enable();
|
SortPatches.Enable();
|
||||||
|
ReloadInPlacePatches.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool InRaid()
|
public static bool InRaid()
|
||||||
|
|||||||
10
Settings.cs
10
Settings.cs
@@ -81,6 +81,7 @@ internal class Settings
|
|||||||
public static ConfigEntry<MultiSelectStrategy> MultiSelectStrat { get; set; }
|
public static ConfigEntry<MultiSelectStrategy> MultiSelectStrat { get; set; }
|
||||||
public static ConfigEntry<bool> ShowMultiSelectDebug { get; set; } // Advanced
|
public static ConfigEntry<bool> ShowMultiSelectDebug { get; set; } // Advanced
|
||||||
public static ConfigEntry<bool> SwapItems { get; set; }
|
public static ConfigEntry<bool> SwapItems { get; set; }
|
||||||
|
public static ConfigEntry<bool> SwapMags { get; set; }
|
||||||
public static ConfigEntry<bool> SwapImpossibleContainers { get; set; }
|
public static ConfigEntry<bool> SwapImpossibleContainers { get; set; }
|
||||||
public static ConfigEntry<bool> ReorderGrids { get; set; }
|
public static ConfigEntry<bool> ReorderGrids { get; set; }
|
||||||
public static ConfigEntry<bool> SynchronizeStashScrolling { get; set; }
|
public static ConfigEntry<bool> SynchronizeStashScrolling { get; set; }
|
||||||
@@ -398,6 +399,15 @@ internal class Settings
|
|||||||
null,
|
null,
|
||||||
new ConfigurationManagerAttributes { })));
|
new ConfigurationManagerAttributes { })));
|
||||||
|
|
||||||
|
configEntries.Add(SwapMags = config.Bind(
|
||||||
|
InventorySection,
|
||||||
|
"Reload Magazines In-Place",
|
||||||
|
true,
|
||||||
|
new ConfigDescription(
|
||||||
|
"When reloading a weapon with a magazine, swap locations with the new magazine (if possible)",
|
||||||
|
null,
|
||||||
|
new ConfigurationManagerAttributes { })));
|
||||||
|
|
||||||
configEntries.Add(SwapImpossibleContainers = config.Bind(
|
configEntries.Add(SwapImpossibleContainers = config.Bind(
|
||||||
InventorySection,
|
InventorySection,
|
||||||
"Swap with Incompatible Containers",
|
"Swap with Incompatible Containers",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>net471</TargetFramework>
|
<TargetFramework>net471</TargetFramework>
|
||||||
<AssemblyName>Tyfon.UIFixes</AssemblyName>
|
<AssemblyName>Tyfon.UIFixes</AssemblyName>
|
||||||
<Description>SPT UI Fixes</Description>
|
<Description>SPT UI Fixes</Description>
|
||||||
<Version>2.2.2</Version>
|
<Version>2.3.0</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "uifixes",
|
"name": "uifixes",
|
||||||
"version": "2.2.2",
|
"version": "2.3.0",
|
||||||
"main": "src/mod.js",
|
"main": "src/mod.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "Tyfon",
|
"author": "Tyfon",
|
||||||
|
|||||||
Reference in New Issue
Block a user