225 lines
9.7 KiB
C#
225 lines
9.7 KiB
C#
using HarmonyLib;
|
|
using KFCommonUtilityLib;
|
|
using KFCommonUtilityLib.Scripts.Attributes;
|
|
using KFCommonUtilityLib.Scripts.StaticManagers;
|
|
using UnityEngine;
|
|
|
|
[TypeTarget(typeof(ItemActionRanged)), ActionDataTarget(typeof(InterruptData))]
|
|
public class ActionModuleInterruptReload
|
|
{
|
|
public float holdBeforeCancel = 0.06f;
|
|
public string firingStateName = "";
|
|
public bool instantFiringCancel = false;
|
|
|
|
[HarmonyPatch(nameof(ItemAction.StartHolding)), MethodTargetPrefix]
|
|
private bool Prefix_StartHolding(InterruptData __customData)
|
|
{
|
|
__customData.Reset();
|
|
return true;
|
|
}
|
|
|
|
[HarmonyPatch(nameof(ItemAction.ReadFrom)), MethodTargetPostfix]
|
|
private void Postfix_ReadFrom(DynamicProperties _props)
|
|
{
|
|
firingStateName = _props.GetString("FiringStateFullName");
|
|
instantFiringCancel = _props.GetBool("InstantFiringCancel");
|
|
}
|
|
|
|
[HarmonyPatch(nameof(ItemAction.OnModificationsChanged)), MethodTargetPostfix]
|
|
private void Postfix_OnModificationsChanged(ItemActionData _data, InterruptData __customData)
|
|
{
|
|
var invData = _data.invData;
|
|
__customData.itemAnimator = AnimationGraphBuilder.DummyWrapper;
|
|
__customData.eventBridge = null;
|
|
if (invData.model && invData.model.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed && targets.IsAnimationSet)
|
|
{
|
|
__customData.itemAnimator = targets.GraphBuilder.WeaponWrapper;
|
|
if (__customData.itemAnimator.IsValid)
|
|
{
|
|
__customData.eventBridge = targets.ItemAnimator.GetComponent<AnimationReloadEvents>();
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct State
|
|
{
|
|
public bool executed;
|
|
public bool isReloading;
|
|
public bool isWeaponReloading;
|
|
public float lastShotTime;
|
|
}
|
|
|
|
[HarmonyPatch(nameof(ItemAction.IsActionRunning)), MethodTargetPostfix]
|
|
private void Postfix_IsActionRunning(ref bool __result, InterruptData __customData)
|
|
{
|
|
__result &= !__customData.instantFiringRequested;
|
|
}
|
|
|
|
[HarmonyPatch(nameof(ItemAction.ExecuteAction)), MethodTargetPrefix]
|
|
private bool Prefix_ExecuteAction(ItemActionData _actionData, bool _bReleased, InterruptData __customData, out State __state)
|
|
{
|
|
__state = default;
|
|
if (!_bReleased && __customData.isInterruptRequested && __customData.instantFiringRequested)
|
|
{
|
|
if (_actionData.invData.itemValue.Meta > 0)
|
|
{
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"instant firing cancel prefix!");
|
|
ItemActionRanged.ItemActionDataRanged rangedData = _actionData as ItemActionRanged.ItemActionDataRanged;
|
|
__state.executed = true;
|
|
__state.isReloading = rangedData.isReloading;
|
|
__state.isWeaponReloading = rangedData.isWeaponReloading;
|
|
__state.lastShotTime = rangedData.m_LastShotTime;
|
|
rangedData.isReloading = false;
|
|
rangedData.isWeaponReloading = false;
|
|
}
|
|
else
|
|
{
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"not fired! meta is 0");
|
|
__customData.isInterruptRequested = false;
|
|
__customData.instantFiringRequested = false;
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
[HarmonyPatch(nameof(ItemAction.ExecuteAction)), MethodTargetPostfix]
|
|
private void Postfix_ExecuteAction(ItemActionData _actionData, InterruptData __customData, State __state)
|
|
{
|
|
if (__state.executed)
|
|
{
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"instant firing cancel postfix!");
|
|
ItemActionRanged.ItemActionDataRanged rangedData = _actionData as ItemActionRanged.ItemActionDataRanged;
|
|
rangedData.isReloading = __state.isReloading;
|
|
rangedData.isWeaponReloading = __state.isWeaponReloading;
|
|
if (__customData.itemAnimator.IsValid && __customData.eventBridge)
|
|
{
|
|
if (rangedData.m_LastShotTime > __state.lastShotTime && rangedData.m_LastShotTime < Time.time + 1f)
|
|
{
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"executed!");
|
|
__customData.eventBridge.OnReloadEnd();
|
|
__customData.itemAnimator.Play(firingStateName, -1, 0f);
|
|
}
|
|
else
|
|
{
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"not fired! last shot time {__state.lastShotTime} ranged data shot time {rangedData.m_LastShotTime} cur time {Time.time}");
|
|
__customData.isInterruptRequested = false;
|
|
__customData.instantFiringRequested = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(nameof(ItemAction.ItemActionEffects)), MethodTargetPrefix]
|
|
private bool Prefix_ItemActionEffects(ItemActionData _actionData, int _firingState, InterruptData __customData)
|
|
{
|
|
var rangedData = _actionData as ItemActionRanged.ItemActionDataRanged;
|
|
if (_firingState != 0 && (rangedData.isReloading || rangedData.isWeaponReloading) && !(rangedData.invData.holdingEntity is EntityPlayerLocal) && __customData.eventBridge)
|
|
{
|
|
__customData.eventBridge.OnReloadEnd();
|
|
__customData.itemAnimator.Play(firingStateName, -1, 0f);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public bool IsRequestPossible(InterruptData interruptData)
|
|
{
|
|
return interruptData.eventBridge && interruptData.itemAnimator.IsValid;
|
|
}
|
|
|
|
public class InterruptData
|
|
{
|
|
public bool isInterruptRequested;
|
|
public float holdStartTime = -1f;
|
|
public bool instantFiringRequested = false;
|
|
public AnimationReloadEvents eventBridge;
|
|
public IAnimatorWrapper itemAnimator;
|
|
|
|
public InterruptData(ItemInventoryData invData, int actionIndex, ActionModuleInterruptReload module)
|
|
{
|
|
//if (invData.model && invData.model.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
|
//{
|
|
// itemAnimator = targets.ItemAnimator;
|
|
// if (itemAnimator)
|
|
// {
|
|
// eventBridge = itemAnimator.GetComponent<AnimationReloadEvents>();
|
|
// }
|
|
//}
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
isInterruptRequested = false;
|
|
holdStartTime = -1f;
|
|
instantFiringRequested = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch]
|
|
internal static class ReloadInterruptionPatches
|
|
{
|
|
//interrupt reload with firing
|
|
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.ExecuteAction))]
|
|
[HarmonyPrefix]
|
|
private static bool Prefix_ExecuteAction_ItemClass(ItemClass __instance, int _actionIdx, ItemInventoryData _data, bool _bReleased, PlayerActionsLocal _playerActions)
|
|
{
|
|
ItemAction curAction = __instance.Actions[_actionIdx];
|
|
if (curAction is ItemActionRanged || curAction is ItemActionZoom)
|
|
{
|
|
int curActionIndex = MultiActionManager.GetActionIndexForEntity(_data.holdingEntity);
|
|
var rangedAction = __instance.Actions[curActionIndex] as ItemActionRanged;
|
|
var rangedData = _data.actionData[curActionIndex] as ItemActionRanged.ItemActionDataRanged;
|
|
if (rangedData != null && rangedData is IModuleContainerFor<ActionModuleInterruptReload.InterruptData> dataModule && rangedAction is IModuleContainerFor<ActionModuleInterruptReload> actionModule)
|
|
{
|
|
if (!_bReleased && _playerActions != null && actionModule.Instance.IsRequestPossible(dataModule.Instance) && ((_playerActions.Primary.IsPressed && _actionIdx == curActionIndex && _data.itemValue.Meta > 0) || (_playerActions.Secondary.IsPressed && curAction is ItemActionZoom)) && (rangedData.isReloading || rangedData.isWeaponReloading) && !dataModule.Instance.isInterruptRequested)
|
|
{
|
|
if (dataModule.Instance.holdStartTime < 0)
|
|
{
|
|
dataModule.Instance.holdStartTime = Time.time;
|
|
return false;
|
|
}
|
|
if (Time.time - dataModule.Instance.holdStartTime >= actionModule.Instance.holdBeforeCancel)
|
|
{
|
|
if (!rangedAction.reloadCancelled(rangedData))
|
|
{
|
|
rangedAction.CancelReload(rangedData);
|
|
}
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"interrupt requested!");
|
|
dataModule.Instance.isInterruptRequested = true;
|
|
if (actionModule.Instance.instantFiringCancel && curAction is ItemActionRanged)
|
|
{
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"instant firing cancel!");
|
|
dataModule.Instance.instantFiringRequested = true;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
if (_bReleased)
|
|
{
|
|
dataModule.Instance.Reset();
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
[HarmonyPatch(typeof(ItemAction), nameof(ItemAction.CancelReload))]
|
|
[HarmonyPrefix]
|
|
private static bool Prefix_CancelReload_ItemAction(ItemActionData _actionData)
|
|
{
|
|
if (_actionData?.invData?.holdingEntity is EntityPlayerLocal && AnimationRiggingManager.IsHoldingRiggedWeapon(_actionData.invData.holdingEntity as EntityPlayerLocal))
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
} |