Files
7d2dXG/Mods/0A-KFCommonUtilityLib/Scripts/Items/ModularActions/ActionModuleRampUp.cs
Nathaniel Cosford 062dfab2cd Patched
2025-05-30 01:04:40 +09:30

276 lines
14 KiB
C#

using HarmonyLib;
using KFCommonUtilityLib.Scripts.Attributes;
using KFCommonUtilityLib.Scripts.Utilities;
using UnityEngine;
using static ItemActionRanged;
[TypeTarget(typeof(ItemActionRanged)), TypeDataTarget(typeof(RampUpData))]
public class ActionModuleRampUp
{
public enum State
{
RampUp,
Stable,
RampDown
}
private readonly static int prepareHash = Animator.StringToHash("prepare");
private readonly static int prepareSpeedHash = Animator.StringToHash("prepareSpeed");
private readonly static int rampHash = Animator.StringToHash("ramp");
private readonly static int prepareRatioHash = Animator.StringToHash("prepareRatio");
private readonly static int rampRatioHash = Animator.StringToHash("rampRatio");
private readonly static int totalRatioHash = Animator.StringToHash("totalRatio");
[HarmonyPatch(nameof(ItemAction.OnHoldingUpdate)), MethodTargetPostfix]
public void Postfix_OnHoldingUpdate(ItemActionData _actionData, RampUpData __customData, ItemActionRanged __instance)
{
var rangedData = _actionData as ItemActionDataRanged;
__customData.originalDelay = rangedData.Delay;
if (rangedData.invData.holdingEntity.isEntityRemote)
return;
bool aiming = rangedData.invData.holdingEntity.AimingGun;
bool isRampUp = ((rangedData.bPressed && !rangedData.bReleased && __instance.notReloading(rangedData) && rangedData.curBurstCount < __instance.GetBurstCount(rangedData)) || (__customData.zoomPrepare && aiming)) && (__instance.InfiniteAmmo || _actionData.invData.itemValue.Meta > 0) && _actionData.invData.itemValue.PercentUsesLeft > 0;
UpdateTick(__customData, _actionData, isRampUp);
if (__customData.rampRatio > 0)
{
rangedData.Delay /= __customData.rampRatio >= 1f ? __customData.maxMultiplier : __customData.rampRatio * (__customData.maxMultiplier - 1f) + 1f;
}
}
[HarmonyPatch(nameof(ItemAction.OnModificationsChanged)), MethodTargetPostfix]
public void Postfix_OnModificationsChanged(ItemActionData _data, RampUpData __customData, ItemActionRanged __instance)
{
int actionIndex = __instance.ActionIndex;
string originalValue = 1.ToString();
__instance.Properties.ParseString("RampMultiplier", ref originalValue);
__customData.maxMultiplier = Mathf.Max(float.Parse(_data.invData.itemValue.GetPropertyOverrideForAction("RampMultiplier", originalValue, actionIndex)), 1);
originalValue = 0.ToString();
__instance.Properties.ParseString("RampUpTime", ref originalValue);
__customData.rampUpTime = float.Parse(_data.invData.itemValue.GetPropertyOverrideForAction("RampTime", originalValue, actionIndex));
originalValue = string.Empty;
__instance.Properties.ParseString("RampUpSound", ref originalValue);
__customData.rampUpSound = _data.invData.itemValue.GetPropertyOverrideForAction("RampStartSound", originalValue, actionIndex);
originalValue = 0.ToString();
__instance.Properties.ParseString("RampDownTime", ref originalValue);
__customData.rampDownTime = Mathf.Max(float.Parse(_data.invData.itemValue.GetPropertyOverrideForAction("RampTime", originalValue, actionIndex)), 0);
originalValue = string.Empty;
__instance.Properties.ParseString("RampDownSound", ref originalValue);
__customData.rampDownSound = _data.invData.itemValue.GetPropertyOverrideForAction("RampStartSound", originalValue, actionIndex);
originalValue = 0.ToString();
__instance.Properties.ParseString("PrepareTime", ref originalValue);
__customData.prepareTime = float.Parse(_data.invData.itemValue.GetPropertyOverrideForAction("PrepareTime", originalValue, actionIndex));
__customData.prepareSpeed = float.Parse(originalValue) / __customData.prepareTime;
originalValue = string.Empty;
__instance.Properties.ParseString("PrepareSound", ref originalValue);
__customData.prepareSound = _data.invData.itemValue.GetPropertyOverrideForAction("PrepareSound", originalValue, actionIndex);
originalValue = false.ToString();
__instance.Properties.ParseString("PrepareOnAim", ref originalValue);
__customData.zoomPrepare = bool.Parse(_data.invData.itemValue.GetPropertyOverrideForAction("PrepareOnAim", originalValue, actionIndex));
originalValue = string.Empty;
__instance.Properties.ParseString("RampStableSound", ref originalValue);
__customData.rampStableSound = _data.invData.itemValue.GetPropertyOverrideForAction("RampStableSound", originalValue, actionIndex);
__customData.totalChargeTime = __customData.prepareTime + __customData.rampUpTime;
__customData.rampDownTimeScale = __customData.rampDownTime > 0 ? (__customData.totalChargeTime) / __customData.rampDownTime : float.MaxValue;
ResetAll(__customData, _data);
}
[HarmonyPatch(nameof(ItemAction.StopHolding)), MethodTargetPostfix]
public void Postfix_StopHolding(RampUpData __customData, ItemActionData _data)
{
ResetAll(__customData, _data);
}
[HarmonyPatch(nameof(ItemAction.ExecuteAction)), MethodTargetPrefix]
public bool Prefix_ExecuteAction(RampUpData __customData, ItemActionRanged __instance, ItemActionData _actionData, bool _bReleased)
{
ItemActionDataRanged rangedData = _actionData as ItemActionDataRanged;
if (!_bReleased && (__instance.InfiniteAmmo || _actionData.invData.itemValue.Meta > 0) && _actionData.invData.itemValue.PercentUsesLeft > 0)
{
rangedData.bReleased = false;
rangedData.bPressed = true;
if (__customData.curTime < __customData.prepareTime)
return false;
}
return true;
}
private void UpdateTick(RampUpData data, ItemActionData actionData, bool isRampUp)
{
float previousTime = data.curTime;
float deltaTime = Time.time - data.lastTickTime;
data.lastTickTime = Time.time;
ref float curTime = ref data.curTime;
ref State curState = ref data.curState;
float totalChargeTime = data.totalChargeTime;
switch (curState)
{
case State.RampUp:
{
curTime = Mathf.Max(curTime, 0);
if (isRampUp)
{
actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(prepareHash, true, true);
if (curTime < totalChargeTime)
{
curTime += deltaTime;
}
if (curTime >= data.prepareTime)
{
actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(rampHash, true, true);
}
if (curTime >= totalChargeTime)
{
//Log.Out($"change state from {curState} to stable");
actionData.invData.holdingEntity.PlayOneShot(data.rampStableSound);
curState = State.Stable;
}
}
else
{
//Log.Out($"change state from {curState} to ramp down");
actionData.invData.holdingEntity.StopOneShot(data.rampUpSound);
actionData.invData.holdingEntity.PlayOneShot(data.rampDownSound);
curState = State.RampDown;
}
break;
}
case State.RampDown:
{
curTime = Mathf.Min(curTime, totalChargeTime);
if (!isRampUp)
{
actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(rampHash, false, true);
if (curTime > 0)
{
curTime -= deltaTime * data.rampDownTimeScale;
}
if (curTime < data.prepareTime)
{
actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(prepareHash, false, true);
}
if (curTime <= 0)
{
//Log.Out($"change state from {curState} to stable");
//actionData.invData.holdingEntity.PlayOneShot(data.rampStableSound);
curState = State.Stable;
}
}
else
{
//Log.Out($"change state from {curState} to ramp up");
actionData.invData.holdingEntity.StopOneShot(data.rampDownSound);
actionData.invData.holdingEntity.PlayOneShot(data.rampUpSound);
curState = State.RampUp;
}
break;
}
case State.Stable:
{
if (isRampUp)
{
if (curTime < totalChargeTime)
{
//Log.Out($"change state from {curState} to ramp up");
actionData.invData.holdingEntity.StopOneShot(data.rampStableSound);
actionData.invData.holdingEntity.StopOneShot(data.rampDownSound);
actionData.invData.holdingEntity.PlayOneShot(data.rampUpSound);
curState = State.RampUp;
}
else
{
actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(prepareHash, true, true);
actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(rampHash, true, true);
}
}
else
{
if (curTime > 0)
{
//Log.Out($"change state from {curState} to ramp down");
actionData.invData.holdingEntity.StopOneShot(data.rampStableSound);
actionData.invData.holdingEntity.StopOneShot(data.rampUpSound);
actionData.invData.holdingEntity.PlayOneShot(data.rampDownSound);
curState = State.RampDown;
}
else
{
actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(prepareHash, false, true);
actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(rampHash, false, true);
}
}
break;
}
}
//Log.Out($"turret burst fire rate {turret.burstFireRate} max {turret.burstFireRateMax} cur time {curTime} cur state {curState} is ramp up {isRampUp} turret: ison {turret.IsOn} has target {turret.hasTarget} state {turret.state}");
actionData.invData.holdingEntity.emodel.avatarController.UpdateFloat(prepareSpeedHash, data.prepareSpeed);
if (curTime != previousTime)
{
actionData.invData.holdingEntity.emodel.avatarController.UpdateFloat(prepareRatioHash, data.prepareRatio = (data.prepareTime == 0 ? 1f : Mathf.Clamp01(curTime / data.prepareTime)));
actionData.invData.holdingEntity.emodel.avatarController.UpdateFloat(rampRatioHash, data.rampRatio = (data.rampUpTime == 0 ? 1f : Mathf.Clamp01((curTime - data.prepareTime) / data.rampUpTime)));
actionData.invData.holdingEntity.emodel.avatarController.UpdateFloat(totalRatioHash, data.totalRatio = (totalChargeTime == 0 ? 1f : Mathf.Clamp01(curTime / totalChargeTime)));
}
}
private void ResetAll(RampUpData _rampData, ItemActionData _actionData)
{
_rampData.curTime = 0f;
_rampData.lastTickTime = Time.time;
_rampData.curState = State.Stable;
_rampData.prepareRatio = 0f;
_rampData.rampRatio = 0f;
_rampData.totalRatio = 0f;
((ItemActionDataRanged)_actionData).Delay = _rampData.originalDelay;
_actionData.invData.holdingEntity.StopOneShot(_rampData.prepareSound);
_actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(prepareHash, false, true);
_actionData.invData.holdingEntity.StopOneShot(_rampData.rampUpSound);
_actionData.invData.holdingEntity.emodel.avatarController.UpdateBool(rampHash, false, true);
//Log.Out("Reset all!");
}
public class RampUpData
{
public float maxMultiplier = 1f;
public string prepareSound = string.Empty;
public float prepareSpeed = 1f;
public float prepareTime = 0f;
public string rampUpSound = string.Empty;
public float rampUpTime = 0f;
public float totalChargeTime = 0f;
public string rampDownSound = string.Empty;
public float rampDownTime = 0f;
public float rampDownTimeScale = float.MaxValue;
public string rampStableSound = string.Empty;
public float originalDelay = 0f;
public float curTime = 0f;
public State curState = State.Stable;
public float prepareRatio = 0f;
public float rampRatio = 0f;
public float totalRatio = 0f;
public float lastTickTime = 0f;
public bool zoomPrepare = false;
public ActionModuleRampUp rampUpModule;
public RampUpData(ItemActionData actionData, ItemInventoryData _invData, int _indexInEntityOfAction, ActionModuleRampUp _module)
{
rampUpModule = _module;
}
}
}