271 lines
12 KiB
C#
271 lines
12 KiB
C#
using HarmonyLib;
|
|
using KFCommonUtilityLib;
|
|
using KFCommonUtilityLib.Scripts.Attributes;
|
|
using KFCommonUtilityLib.Scripts.StaticManagers;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[TypeTarget(typeof(ItemActionZoom)), ActionDataTarget(typeof(ProceduralAimingData))]
|
|
public class ActionModuleProceduralAiming
|
|
{
|
|
[HarmonyPatch(nameof(ItemAction.OnModificationsChanged)), MethodTargetPostfix]
|
|
public void Postfix_OnModificationsChanged(ItemActionZoom __instance, ItemActionData _data, ProceduralAimingData __customData)
|
|
{
|
|
if (_data is IModuleContainerFor<ActionModuleErgoAffected.ErgoData> dataModule)
|
|
{
|
|
__customData.zoomInTime = dataModule.Instance.module.zoomInTimeBase / dataModule.Instance.module.aimSpeedModifierBase;
|
|
__customData.ergoData = dataModule.Instance;
|
|
}
|
|
else
|
|
{
|
|
float zoomInTimeBase = 0.3f;
|
|
__instance.Properties.ParseFloat("ZoomInTimeBase", ref zoomInTimeBase);
|
|
float aimSpeedModifierBase = 1f;
|
|
__instance.Properties.ParseFloat("AimSpeedModifierBase", ref aimSpeedModifierBase);
|
|
__customData.zoomInTime = zoomInTimeBase / aimSpeedModifierBase;
|
|
__customData.ergoData = null;
|
|
}
|
|
|
|
__customData.playerOriginTransform = null;
|
|
__customData.playerCameraPosRef = _data.invData.holdingEntity is EntityPlayerLocal player && player.bFirstPersonView ? player.cameraTransform : null;
|
|
var targets = AnimationRiggingManager.GetRigTargetsFromPlayer(_data.invData.holdingEntity);
|
|
if (__customData.playerCameraPosRef)
|
|
{
|
|
if (targets.ItemFpv)
|
|
{
|
|
if (targets is RigTargets)
|
|
{
|
|
__customData.isRigWeapon = true;
|
|
__customData.playerOriginTransform = targets.ItemAnimator.transform;
|
|
__customData.rigWeaponLocalPosition = __customData.playerOriginTransform.localPosition;
|
|
__customData.rigWeaponLocalRotation = __customData.playerOriginTransform.localRotation;
|
|
}
|
|
else
|
|
{
|
|
__customData.isRigWeapon = false;
|
|
__customData.playerOriginTransform = __customData.playerCameraPosRef.FindInAllChildren("Hips");
|
|
}
|
|
__customData.playerCameraPosRef = targets.ItemFpv.Find("PlayerCameraPositionReference");
|
|
}
|
|
else
|
|
{
|
|
__customData.playerCameraPosRef = null;
|
|
}
|
|
}
|
|
if (__customData.playerCameraPosRef)
|
|
{
|
|
__customData.aimRefTransform = targets.ItemFpv.Find("ScopeBasePositionReference");
|
|
if (__customData.aimRefTransform)
|
|
{
|
|
var scopeRefTrans = __customData.aimRefTransform.Find("ScopePositionReference");
|
|
if (!scopeRefTrans)
|
|
{
|
|
scopeRefTrans = new GameObject("ScopePositionReference").transform;
|
|
scopeRefTrans.SetParent(__customData.aimRefTransform, false);
|
|
}
|
|
scopeRefTrans.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
|
scopeRefTrans.localScale = Vector3.one;
|
|
__customData.aimRefTransform = scopeRefTrans;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__customData.aimRefTransform = null;
|
|
}
|
|
|
|
__customData.ResetAiming();
|
|
__customData.UpdateCurrentReference(true);
|
|
}
|
|
|
|
[HarmonyPatch(nameof(ItemAction.StopHolding)), MethodTargetPostfix]
|
|
public void Postfix_StopHolding(ProceduralAimingData __customData)
|
|
{
|
|
__customData.ResetAiming();
|
|
}
|
|
|
|
//[HarmonyPatch(nameof(ItemAction.ExecuteAction)), MethodTargetPostfix]
|
|
//public void Postfix_ExecuteAction(ProceduralAimingData __customData, ItemActionData _actionData)
|
|
//{
|
|
// if (__customData.isAiming != ((ItemActionZoom.ItemActionDataZoom)_actionData).aimingValue)
|
|
// {
|
|
// __customData.UpdateCurrentReference();
|
|
// __customData.isAiming = ((ItemActionZoom.ItemActionDataZoom)_actionData).aimingValue;
|
|
// }
|
|
//}
|
|
|
|
public class ProceduralAimingData
|
|
{
|
|
public ActionModuleErgoAffected.ErgoData ergoData;
|
|
public float zoomInTime;
|
|
public Transform aimRefTransform;
|
|
public Transform playerCameraPosRef;
|
|
public Transform playerOriginTransform;
|
|
public bool isRigWeapon;
|
|
public Vector3 rigWeaponLocalPosition;
|
|
public Quaternion rigWeaponLocalRotation;
|
|
|
|
public bool isAiming;
|
|
public int curAimRefIndex = -1;
|
|
//move curAimRefOffset towards aimRefOffset first, then move curAimOffset towards curAimRefOffset
|
|
public Vector3 aimRefPosOffset;
|
|
public Quaternion aimRefRotOffset;
|
|
public Vector3 curAimPosOffset;
|
|
public Quaternion curAimRotOffset;
|
|
private Vector3 curAimPosVelocity;
|
|
private Quaternion curAimRotVelocity;
|
|
private Vector3 targetSwitchPosVelocity;
|
|
private Quaternion targetSwitchRotVelocity;
|
|
public List<AimReference> registeredReferences = new List<AimReference>();
|
|
private EntityPlayerLocal holdingEntity;
|
|
private int CurAimRefIndex
|
|
{
|
|
get
|
|
{
|
|
for (int i = registeredReferences.Count - 1; i >= 0; i--)
|
|
{
|
|
if (registeredReferences[i].gameObject.activeInHierarchy)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
private AimReference CurAimRef => curAimRefIndex >= 0 && curAimRefIndex < registeredReferences.Count ? registeredReferences[curAimRefIndex] : null;
|
|
|
|
public ProceduralAimingData(ItemInventoryData _invData, int _indexInEntityOfAction, ActionModuleProceduralAiming _module)
|
|
{
|
|
holdingEntity = _invData.holdingEntity as EntityPlayerLocal;
|
|
}
|
|
|
|
public void ResetAiming()
|
|
{
|
|
isAiming = false;
|
|
curAimRefIndex = -1;
|
|
aimRefPosOffset = Vector3.zero;
|
|
aimRefRotOffset = Quaternion.identity;
|
|
if (aimRefTransform)
|
|
{
|
|
aimRefTransform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
|
}
|
|
curAimPosOffset = Vector3.zero;
|
|
curAimRotOffset = Quaternion.identity;
|
|
curAimPosVelocity = Vector3.zero;
|
|
curAimRotVelocity = Quaternion.identity;
|
|
targetSwitchPosVelocity = Vector3.zero;
|
|
targetSwitchRotVelocity = Quaternion.identity;
|
|
if (isRigWeapon && playerOriginTransform)
|
|
{
|
|
playerOriginTransform.localPosition = rigWeaponLocalPosition;
|
|
playerOriginTransform.localRotation = rigWeaponLocalRotation;
|
|
}
|
|
}
|
|
|
|
public bool RegisterGroup(AimReference[] group, string name)
|
|
{
|
|
if (holdingEntity && holdingEntity.bFirstPersonView)
|
|
{
|
|
foreach (var reference in group)
|
|
{
|
|
if (reference.index == -1)
|
|
{
|
|
reference.index = registeredReferences.Count;
|
|
registeredReferences.Add(reference);
|
|
}
|
|
}
|
|
UpdateCurrentReference();
|
|
//Log.Out($"Register group {name}\n{StackTraceUtility.ExtractStackTrace()}");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void UpdateCurrentReference(bool snapTo = false)
|
|
{
|
|
curAimRefIndex = CurAimRefIndex;
|
|
AimReference curAimRef = CurAimRef;
|
|
if (aimRefTransform && curAimRef)
|
|
{
|
|
aimRefPosOffset = curAimRef.positionOffset;
|
|
aimRefRotOffset = curAimRef.rotationOffset;
|
|
if (curAimRef.asReference)
|
|
{
|
|
aimRefPosOffset -= Vector3.Project(aimRefPosOffset - aimRefTransform.parent.InverseTransformPoint(playerCameraPosRef.position), aimRefRotOffset * Vector3.forward);
|
|
}
|
|
if (snapTo)
|
|
{
|
|
aimRefTransform.localPosition = aimRefPosOffset;
|
|
aimRefTransform.localRotation = aimRefRotOffset;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < registeredReferences.Count; i++)
|
|
{
|
|
registeredReferences[i].UpdateEnableState(isAiming && curAimRefIndex == i);
|
|
}
|
|
}
|
|
|
|
public void LateUpdateAiming()
|
|
{
|
|
if (aimRefTransform && playerCameraPosRef && playerOriginTransform && CurAimRef)
|
|
{
|
|
if (isRigWeapon)
|
|
{
|
|
playerOriginTransform.SetLocalPositionAndRotation(rigWeaponLocalPosition, rigWeaponLocalRotation);
|
|
}
|
|
float zoomInTimeMod = ergoData == null ? zoomInTime : zoomInTime / ergoData.ModifiedErgo;
|
|
zoomInTimeMod *= 0.25f;
|
|
//move aimRef towards target
|
|
aimRefTransform.localPosition = Vector3.SmoothDamp(aimRefTransform.localPosition, aimRefPosOffset, ref targetSwitchPosVelocity, 0.075f);
|
|
aimRefTransform.localRotation = QuaternionUtil.SmoothDamp(aimRefTransform.localRotation, aimRefRotOffset, ref targetSwitchRotVelocity, 0.075f);
|
|
//calculate current target aim offset
|
|
Vector3 aimTargetPosOffset = playerCameraPosRef.InverseTransformDirection(playerCameraPosRef.position - aimRefTransform.position);
|
|
Quaternion aimTargetRotOffset = playerCameraPosRef.localRotation * Quaternion.Inverse(aimRefTransform.parent.localRotation * aimRefTransform.localRotation);
|
|
//move current aim offset towards target aim offset
|
|
if (isAiming)
|
|
{
|
|
curAimPosOffset = Vector3.SmoothDamp(curAimPosOffset, aimTargetPosOffset, ref curAimPosVelocity, zoomInTimeMod);
|
|
curAimRotOffset = QuaternionUtil.SmoothDamp(curAimRotOffset, aimTargetRotOffset, ref curAimRotVelocity, zoomInTimeMod);
|
|
}
|
|
else
|
|
{
|
|
curAimPosOffset = Vector3.SmoothDamp(curAimPosOffset, Vector3.zero, ref curAimPosVelocity, zoomInTimeMod);
|
|
curAimRotOffset = QuaternionUtil.SmoothDamp(curAimRotOffset, Quaternion.identity, ref curAimRotVelocity, zoomInTimeMod);
|
|
}
|
|
//apply offset to player
|
|
if (isRigWeapon)
|
|
{
|
|
(playerCameraPosRef.parent.rotation * curAimRotOffset * Quaternion.Inverse(playerCameraPosRef.parent.rotation)).ToAngleAxis(out var angle, out var axis);
|
|
playerOriginTransform.RotateAround(aimRefTransform.position, axis, angle);
|
|
playerOriginTransform.position += playerCameraPosRef.TransformDirection(curAimPosOffset);
|
|
}
|
|
else
|
|
{
|
|
playerOriginTransform.position += playerCameraPosRef.TransformDirection(curAimPosOffset);
|
|
(playerCameraPosRef.parent.rotation * curAimRotOffset * Quaternion.Inverse(playerCameraPosRef.parent.rotation)).ToAngleAxis(out var angle, out var axis);
|
|
playerOriginTransform.RotateAround(aimRefTransform.position, axis, angle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch]
|
|
public static class ProceduralAimingPatches
|
|
{
|
|
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.LateUpdate))]
|
|
[HarmonyPostfix]
|
|
private static void Postfix_LateUpdate_EntityPlayerLocal(EntityPlayerLocal __instance)
|
|
{
|
|
if (__instance.inventory?.holdingItemData?.actionData?[1] is IModuleContainerFor<ActionModuleProceduralAiming.ProceduralAimingData> module)
|
|
{
|
|
if (__instance.AimingGun != module.Instance.isAiming)
|
|
{
|
|
module.Instance.isAiming = __instance.AimingGun;
|
|
module.Instance.UpdateCurrentReference(true);
|
|
}
|
|
module.Instance.LateUpdateAiming();
|
|
}
|
|
}
|
|
} |