Upload from upload_mods.ps1
This commit is contained in:
336
Scripts/Items/ModularActions/ActionModuleFireModeSelector.cs
Normal file
336
Scripts/Items/ModularActions/ActionModuleFireModeSelector.cs
Normal file
@@ -0,0 +1,336 @@
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib;
|
||||
using KFCommonUtilityLib.Scripts.Attributes;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using KFCommonUtilityLib.Scripts.Utilities;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[TypeTarget(typeof(ItemActionRanged)), ActionDataTarget(typeof(FireModeData))]
|
||||
public class ActionModuleFireModeSelector
|
||||
{
|
||||
public struct FireMode
|
||||
{
|
||||
public byte burstCount;
|
||||
public bool isFullAuto;
|
||||
}
|
||||
public string fireModeSwitchingSound = null;
|
||||
private List<FireMode> modeCache = new List<FireMode>();
|
||||
private List<string> nameCache = new List<string>();
|
||||
public static string[] FireModeNames = new[]
|
||||
{
|
||||
"FireMode",
|
||||
"FireMode1",
|
||||
"FireMode2",
|
||||
"FireMode3",
|
||||
"FireMode4",
|
||||
};
|
||||
public static int[] FireModeParamHashes = new[]
|
||||
{
|
||||
Animator.StringToHash("FireMode"),
|
||||
Animator.StringToHash("FireMode1"),
|
||||
Animator.StringToHash("FireMode2"),
|
||||
Animator.StringToHash("FireMode3"),
|
||||
Animator.StringToHash("FireMode4"),
|
||||
};
|
||||
public static int[] FireModeSwitchParamHashes = new[]
|
||||
{
|
||||
Animator.StringToHash("FireModeChanged"),
|
||||
Animator.StringToHash("FireModeChanged1"),
|
||||
Animator.StringToHash("FireModeChanged2"),
|
||||
Animator.StringToHash("FireModeChanged3"),
|
||||
Animator.StringToHash("FireModeChanged4"),
|
||||
};
|
||||
|
||||
[HarmonyPatch(nameof(ItemAction.OnModificationsChanged)), MethodTargetPostfix]
|
||||
private void Postfix_OnModificationChanged(ItemActionData _data, FireModeData __customData, ItemActionRanged __instance)
|
||||
{
|
||||
__instance.Properties.ParseString("FireModeSwitchingSound", ref fireModeSwitchingSound);
|
||||
int actionIndex = _data.indexInEntityOfAction;
|
||||
for (int i = 0; i < 99; i++)
|
||||
{
|
||||
if (!__instance.Properties.Contains($"FireMode{i}.BurstCount"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
string burstCount = 1.ToString();
|
||||
__instance.Properties.ParseString($"FireMode{i}.BurstCount", ref burstCount);
|
||||
string isFullAuto = false.ToString();
|
||||
__instance.Properties.ParseString($"FireMode{i}.IsFullAuto", ref isFullAuto);
|
||||
string modeName = null;
|
||||
__instance.Properties.ParseString($"FireMode{i}.ModeName", ref modeName);
|
||||
modeCache.Add(new FireMode
|
||||
{
|
||||
burstCount = byte.Parse(_data.invData.itemValue.GetPropertyOverrideForAction($"FireMode{i}.BurstCount", burstCount, actionIndex)),
|
||||
isFullAuto = bool.Parse(_data.invData.itemValue.GetPropertyOverrideForAction($"FireMode{i}.IsFullAuto", isFullAuto, actionIndex))
|
||||
});
|
||||
nameCache.Add(_data.invData.itemValue.GetPropertyOverrideForAction($"FireMode{i}.ModeName", modeName, actionIndex));
|
||||
}
|
||||
for (int i = 0; i < 99; i++)
|
||||
{
|
||||
string burstCount = _data.invData.itemValue.GetPropertyOverrideForAction($"FireModePlus{i}.BurstCount", null, actionIndex);
|
||||
if (burstCount == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
modeCache.Add(new FireMode
|
||||
{
|
||||
burstCount = byte.Parse(_data.invData.itemValue.GetPropertyOverrideForAction($"FireModePlus{i}.BurstCount", burstCount, actionIndex)),
|
||||
isFullAuto = bool.Parse(_data.invData.itemValue.GetPropertyOverrideForAction($"FireModePlus{i}.IsFullAuto", "false", actionIndex))
|
||||
});
|
||||
nameCache.Add(_data.invData.itemValue.GetPropertyOverrideForAction($"FireModePlus{i}.ModeName", null, actionIndex));
|
||||
}
|
||||
__customData.fireModes = modeCache.ToArray();
|
||||
modeCache.Clear();
|
||||
__customData.modeNames = nameCache.ToArray();
|
||||
nameCache.Clear();
|
||||
if (_data.invData.itemValue.GetMetadata(FireModeNames[actionIndex]) is int mode)
|
||||
{
|
||||
__customData.currentFireMode = (byte)mode;
|
||||
}
|
||||
if (__customData.currentFireMode < 0 || __customData.currentFireMode >= __customData.fireModes.Length)
|
||||
{
|
||||
__customData.currentFireMode = 0;
|
||||
}
|
||||
if (__customData.delayFiringCo != null)
|
||||
{
|
||||
ThreadManager.StopCoroutine(__customData.delayFiringCo);
|
||||
__customData.delayFiringCo = null;
|
||||
}
|
||||
__customData.isRequestedByCoroutine = false;
|
||||
}
|
||||
|
||||
[HarmonyPatch(nameof(ItemAction.StartHolding)), MethodTargetPostfix]
|
||||
private void Postfix_StartHolding(ItemActionData _data, FireModeData __customData)
|
||||
{
|
||||
__customData.SetFireMode(_data, __customData.currentFireMode);
|
||||
}
|
||||
|
||||
[HarmonyPatch(nameof(ItemAction.OnHoldingUpdate)), MethodTargetPostfix]
|
||||
private static void Postfix_OnHoldingUpdate(ItemActionData _actionData, FireModeData __customData)
|
||||
{
|
||||
__customData.UpdateDelay(_actionData);
|
||||
__customData.inputReleased = true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(nameof(ItemAction.StopHolding)), MethodTargetPostfix]
|
||||
private static void Postfix_StopHolding(FireModeData __customData)
|
||||
{
|
||||
if (__customData.delayFiringCo != null)
|
||||
{
|
||||
ThreadManager.StopCoroutine(__customData.delayFiringCo);
|
||||
__customData.delayFiringCo = null;
|
||||
}
|
||||
__customData.isRequestedByCoroutine = false;
|
||||
__customData.inputReleased = true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(nameof(ItemAction.ExecuteAction)), MethodTargetPrefix]
|
||||
private bool Prefix_ExecuteAction(ItemActionData _actionData, ItemActionRanged __instance, FireModeData __customData, bool _bReleased)
|
||||
{
|
||||
if (__customData.isRequestedByCoroutine)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
__customData.inputReleased = _bReleased;
|
||||
if (__customData.delayFiringCo == null)
|
||||
{
|
||||
if (_bReleased || _actionData.invData.itemValue.Meta == 0 || _actionData.invData.itemValue.PercentUsesLeft <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
FireMode curFireMode = __customData.fireModes[__customData.currentFireMode];
|
||||
if (curFireMode.burstCount == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var rangedData = _actionData as ItemActionRanged.ItemActionDataRanged;
|
||||
if (__instance.GetBurstCount(_actionData) > rangedData.curBurstCount)
|
||||
{
|
||||
__customData.StartFiring(__instance, _actionData);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPatch(nameof(ItemActionRanged.GetBurstCount)), MethodTargetPostfix]
|
||||
private void Postfix_GetBurstCount(FireModeData __customData, ref int __result)
|
||||
{
|
||||
FireMode fireMode = __customData.fireModes[__customData.currentFireMode];
|
||||
__result = fireMode.isFullAuto ? 999 : fireMode.burstCount;
|
||||
}
|
||||
|
||||
[HarmonyPatch(nameof(ItemAction.IsActionRunning)), MethodTargetPostfix]
|
||||
private void Postfix_IsActionRunning(FireModeData __customData, ref bool __result)
|
||||
{
|
||||
__result |= __customData.delayFiringCo != null;
|
||||
}
|
||||
|
||||
public class FireModeData
|
||||
{
|
||||
public string switchSound;
|
||||
public FireMode[] fireModes;
|
||||
public string[] modeNames;
|
||||
public byte currentFireMode;
|
||||
public Coroutine delayFiringCo;
|
||||
public bool isRequestedByCoroutine;
|
||||
public float shotDelay;
|
||||
public float burstDelay;
|
||||
public bool inputReleased;
|
||||
|
||||
public FireModeData(ItemInventoryData invData, int actionIndex, ActionModuleFireModeSelector module)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void CycleFireMode(ItemActionData _data)
|
||||
{
|
||||
SetFireMode(_data, (byte)((currentFireMode + 1) % fireModes.Length));
|
||||
}
|
||||
|
||||
public void SetFireMode(ItemActionData _data, byte _fireMode)
|
||||
{
|
||||
if (currentFireMode != _fireMode)
|
||||
{
|
||||
currentFireMode = _fireMode;
|
||||
FireMode curFireMode = fireModes[currentFireMode];
|
||||
if (!string.IsNullOrEmpty(switchSound))
|
||||
{
|
||||
_data.invData.holdingEntity.PlayOneShot(switchSound);
|
||||
}
|
||||
_data.invData.holdingEntity.emodel.avatarController.TriggerEvent(FireModeSwitchParamHashes[_data.indexInEntityOfAction]);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(modeNames[_fireMode]))
|
||||
{
|
||||
GameManager.ShowTooltip(_data.invData.holdingEntity as EntityPlayerLocal, modeNames[_fireMode], true);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameManager.ShowTooltip(_data.invData.holdingEntity as EntityPlayerLocal, "ttCurrentFiringMode", _fireMode.ToString(), null, null, true);
|
||||
}
|
||||
//GameManager.ShowTooltip(_data.invData.holdingEntity as EntityPlayerLocal, "ttCurrentFiringMode", string.IsNullOrEmpty(modeNames[_fireMode]) ? _fireMode.ToString() : Localization.Get(modeNames[_fireMode]), null, null, true);
|
||||
_data.invData.holdingEntity.FireEvent(CustomEnums.onSelfBurstModeChanged);
|
||||
UpdateDelay(_data);
|
||||
|
||||
ItemValue itemValue = _data.invData.itemValue;
|
||||
if (itemValue != null)
|
||||
{
|
||||
if (itemValue.Metadata == null)
|
||||
{
|
||||
itemValue.Metadata = new Dictionary<string, TypedMetadataValue>();
|
||||
}
|
||||
|
||||
if (!itemValue.Metadata.TryGetValue(ActionModuleFireModeSelector.FireModeNames[_data.indexInEntityOfAction], out var metadata) || !metadata.SetValue((int)_fireMode))
|
||||
{
|
||||
itemValue.Metadata[ActionModuleFireModeSelector.FireModeNames[_data.indexInEntityOfAction]] = new TypedMetadataValue((int)_fireMode, TypedMetadataValue.TypeTag.Integer);
|
||||
}
|
||||
_data.invData.holdingEntity.inventory.CallOnToolbeltChangedInternal();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateDelay(ItemActionData _data)
|
||||
{
|
||||
FireMode curFireMode = fireModes[currentFireMode];
|
||||
if (curFireMode.burstCount == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
float burstInterval = EffectManager.GetValue(CustomEnums.BurstShotInterval, _data.invData.itemValue, -1, _data.invData.holdingEntity);
|
||||
var rangedData = _data as ItemActionRanged.ItemActionDataRanged;
|
||||
if (burstInterval > 0 && rangedData.Delay > burstInterval)
|
||||
{
|
||||
shotDelay = burstInterval;
|
||||
burstDelay = (rangedData.Delay - burstInterval) * curFireMode.burstCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
shotDelay = rangedData.Delay;
|
||||
burstDelay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartFiring(ItemActionRanged _instance, ItemActionData _data)
|
||||
{
|
||||
UpdateDelay(_data);
|
||||
if (delayFiringCo != null)
|
||||
{
|
||||
ThreadManager.StopCoroutine(delayFiringCo);
|
||||
}
|
||||
((ItemActionRanged.ItemActionDataRanged)_data).bPressed = true;
|
||||
((ItemActionRanged.ItemActionDataRanged)_data).bReleased = false;
|
||||
|
||||
delayFiringCo = ThreadManager.StartCoroutine(DelayFiring(_instance, _data));
|
||||
}
|
||||
|
||||
private IEnumerator DelayFiring(ItemActionRanged _instance, ItemActionData _data)
|
||||
{
|
||||
FireMode curFireMode = fireModes[currentFireMode];
|
||||
var rangedData = _data as ItemActionRanged.ItemActionDataRanged;
|
||||
byte curBurstCount = rangedData.curBurstCount;
|
||||
for (int i = 0; i < curFireMode.burstCount; i++)
|
||||
{
|
||||
isRequestedByCoroutine = true;
|
||||
rangedData.bPressed = true;
|
||||
rangedData.bReleased = false;
|
||||
rangedData.m_LastShotTime = 0;
|
||||
_instance.ExecuteAction(_data, false);
|
||||
rangedData.curBurstCount = (byte)(curBurstCount + i + 1);
|
||||
isRequestedByCoroutine = false;
|
||||
if (rangedData.invData.itemValue.Meta <= 0 && !_instance.HasInfiniteAmmo(_data))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
yield return new WaitForSeconds(shotDelay);
|
||||
}
|
||||
yield return new WaitForSeconds(burstDelay);
|
||||
|
||||
cleanup:
|
||||
delayFiringCo = null;
|
||||
if (inputReleased)
|
||||
{
|
||||
_instance.ExecuteAction(_data, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
public static class FireModePatches
|
||||
{
|
||||
[HarmonyPatch(typeof(PlayerMoveController), nameof(PlayerMoveController.Update))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_Update_PlayerMoveController(PlayerMoveController __instance)
|
||||
{
|
||||
if (DroneManager.Debug_LocalControl || !__instance.gameManager.gameStateManager.IsGameStarted() || GameStats.GetInt(EnumGameStats.GameState) != 1)
|
||||
return true;
|
||||
|
||||
bool isUIOpen = __instance.windowManager.IsCursorWindowOpen() || __instance.windowManager.IsInputActive() || __instance.windowManager.IsModalWindowOpen();
|
||||
|
||||
UpdateLocalInput(__instance.entityPlayerLocal, isUIOpen);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void UpdateLocalInput(EntityPlayerLocal _player, bool _isUIOpen)
|
||||
{
|
||||
if (_isUIOpen || _player.emodel.IsRagdollActive || _player.IsDead() || _player.AttachedToEntity != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayerActionKFLib.Instance.Enabled && PlayerActionKFLib.Instance.ToggleFireMode.WasPressed)
|
||||
{
|
||||
if (_player.inventory.IsHoldingItemActionRunning())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var actionData = _player.inventory.holdingItemData.actionData[MultiActionManager.GetActionIndexForEntity(_player)];
|
||||
if (actionData is IModuleContainerFor<ActionModuleFireModeSelector.FireModeData> fireModeData)
|
||||
{
|
||||
fireModeData.Instance.CycleFireMode(actionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user