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();
|
||||
FilterOutOfStockPatches.Enable();
|
||||
SortPatches.Enable();
|
||||
ReloadInPlacePatches.Enable();
|
||||
}
|
||||
|
||||
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<bool> ShowMultiSelectDebug { get; set; } // Advanced
|
||||
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> ReorderGrids { get; set; }
|
||||
public static ConfigEntry<bool> SynchronizeStashScrolling { get; set; }
|
||||
@@ -398,6 +399,15 @@ internal class Settings
|
||||
null,
|
||||
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(
|
||||
InventorySection,
|
||||
"Swap with Incompatible Containers",
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net471</TargetFramework>
|
||||
<AssemblyName>Tyfon.UIFixes</AssemblyName>
|
||||
<Description>SPT UI Fixes</Description>
|
||||
<Version>2.2.2</Version>
|
||||
<Version>2.3.0</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uifixes",
|
||||
"version": "2.2.2",
|
||||
"version": "2.3.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Tyfon",
|
||||
|
Reference in New Issue
Block a user