using UnityEngine; namespace Invector.vCharacterController { using IK; using vShooter; [vClassHeader("SHOOTER/MELEE INPUT", iconName = "inputIcon")] public class vShooterMeleeInput : vMeleeCombatInput, vIShooterIKController, PlayerController.vILockCamera { #region Shooter Variables [HideInInspector] public vShooterManager shooterManager; public vArmAimAlign leftArmAim, rightArmAim; public virtual bool isAimingByInput { get; set; } public virtual bool isReloading { get; set; } public virtual bool ignoreIK { get; set; } public virtual bool aimConditions { get; protected set; } public virtual bool allowAttack { get; set; } public virtual bool isCameraRightSwitched { get; set; } protected virtual bool wasAiming { get; set; } protected virtual bool wasAimingWithScope { get; set; } protected virtual bool lockShooterInput { get; set; } protected virtual bool checkCanAimInit { get; set; } protected virtual bool _ignoreIKFromAnimator { get; set; } protected virtual bool _walkingByDefaultWasChanged { get; set; } protected bool _isUsingScopeView; protected virtual bool isUsingScopeView { get { return _isUsingScopeView; } set { _isUsingScopeView = value; } } public virtual int onlyArmsLayer { get; set; } public virtual int shotLayer { get; set; } public virtual int shootCountA { get; set; } public virtual float onlyArmsLayerWeight { get; set; } public virtual float supportIKWeight { get; set; } public virtual float weaponIKWeight { get; set; } public virtual float armAlignmentWeight { get; protected set; } protected virtual float _aimTiming { get; set; } protected virtual float checkCanAimOffsetStartX { get; set; } protected virtual float checkCanAimOffsetStartY { get; set; } protected virtual float checkCanAimOffsetEndX { get; set; } protected virtual float checkCanAimOffsetEndY { get; set; } protected virtual float checkCanAimHeight { get; set; } protected virtual float scopeDirectionWeight { get; set; } protected virtual GameObject aimAngleReference { get; set; } protected virtual GameObject lastShooterWeapon { get; set; } protected virtual Vector3 localAimPosition { get; set; } protected virtual Vector3 aimHitPoint { get; set; } protected virtual Vector3 upperArmPosition { get; set; } protected virtual Vector3 muzzlePosition { get; set; } protected virtual Vector3 muzzleForward { get; set; } protected virtual Vector3 ikRotationOffset { get; set; } protected virtual Vector3 ikPositionOffset { get; set; } protected virtual Vector3 scopeLocalPosition { get; set; } protected virtual Vector3 scopeCameraLocalPosition { get; set; } protected virtual Vector3 scopeLocalForward { get; set; } protected virtual Vector3 scopeCameraLocalForward { get; set; } protected virtual Vector3 lastTargetCameraEuler { get; set; } protected virtual Quaternion handRotation { get; set; } protected virtual Quaternion upperArmRotation { get; set; } protected virtual Quaternion upperArmRotationAlignment { get; set; } protected virtual Quaternion handRotationAlignment { get; set; } protected vHeadTrack headTrack; protected vControlAimCanvas _controlAimCanvas; protected IKAdjust _currentIKAdjust; protected RaycastHit checkCanAimHit; protected Transform leftHand, rightHand, rightLowerArm, leftLowerArm, rightUpperArm, leftUpperArm; #region IKController Interface Properties public virtual vIKSolver LeftIK { get; set; } public virtual vIKSolver RightIK { get; set; } public virtual vWeaponIKAdjustList WeaponIKAdjustList { get { if (shooterManager) { return shooterManager.weaponIKAdjustList; } return null; } set { if (shooterManager) { shooterManager.weaponIKAdjustList = value; } } } public virtual vWeaponIKAdjust CurrentWeaponIK { get { if (shooterManager) { return shooterManager.CurrentWeaponIK; } return null; } } public virtual IKAdjust CurrentIKAdjust { get { if (CurrentWeaponIK == null) return null; if (CurrentIKAdjustStateWithTag != (IKWeaponTag + TargetIKAdjustState) || _currentIKAdjust == null) { CurrentIKAdjustStateWithTag = (IKWeaponTag + TargetIKAdjustState); CurrentIKAdjustState = TargetIKAdjustState; _currentIKAdjust = CurrentWeaponIK.GetIKAdjust(CurrentIKAdjustState, CurrentActiveWeapon.isLeftWeapon); } return _currentIKAdjust; } } public virtual bool EditingIKGlobalOffset { get; set; } public virtual string DefaultIKAdjustState => CurrentWeaponIK ? CurrentWeaponIK.GetDefaultStateName(this) : string.Empty; protected virtual string TargetIKAdjustState => (!IsUsingCustomIKAdjust ? DefaultIKAdjustState : CustomIKAdjustState); protected virtual string IKWeaponTag => CurrentActiveWeapon ? CurrentActiveWeapon.weaponCategory + "@" : ""; public virtual string CurrentIKAdjustStateWithTag { get; set; } public virtual string CurrentIKAdjustState { get; protected set; } public virtual bool IsUsingCustomIKAdjust => !string.IsNullOrEmpty(CustomIKAdjustState); public string CustomIKAdjustState { get; protected set; } public virtual void SetCustomIKAdjustState(string value) { if (!string.IsNullOrEmpty(value)) CustomIKAdjustState = value; } public virtual void ResetCustomIKAdjustState() { if (!string.IsNullOrEmpty(CustomIKAdjustState)) CustomIKAdjustState = string.Empty; } public virtual bool IsIgnoreIK { get { return ignoreIK || _ignoreIKFromAnimator; } } public virtual bool IsIgnoreSupportHandIK { get { return cc.IsAnimatorTag("IgnoreSupportHandIK"); } } public virtual bool IsSupportHandIKEnabled { get; protected set; } public virtual void UpdateWeaponIK() { if (shooterManager) { shooterManager.UpdateWeaponIK(); if (CurrentWeaponIK == null) return; _currentIKAdjust = CurrentWeaponIK.GetIKAdjust(CurrentIKAdjustState, CurrentActiveWeapon.isLeftWeapon); } } public event IKUpdateEvent onStartUpdateIK; public event IKUpdateEvent onFinishUpdateIK; /// /// Aim position including . /// This is a point calculated from position and forward to get the desired aim position. /// Used to align the arms and to define the /// public virtual Vector3 DesiredAimPosition { get; protected set; } /// /// Aim position including . /// This is a point calculated from of the weapon and /// public virtual Vector3 AimPosition { get; protected set; } public virtual bool LockAiming { get { return shooterManager && shooterManager.alwaysAiming; } set { shooterManager.alwaysAiming = value; } } public virtual bool LockHipFireAiming { get; set; } public virtual bool IsCrouching { get { return cc.isCrouching; } set { cc.isCrouching = value; } } public virtual bool IsLeftWeapon { get { return shooterManager && shooterManager.IsLeftWeapon; } } public virtual bool LockCamera { get { return tpCamera && tpCamera.LockCamera; } set { if (tpCamera) { tpCamera.LockCamera = value; } } } #endregion /// /// Is Aiming by or /// public virtual bool IsAiming { get { return lockShooterInput == false && (!cc.isRolling) && (isAimingByInput || isAimingByHipFire); } } public virtual bool isAimingByHipFire { get { if (!shooterManager.hipfireShot && _aimTiming > 0 || (isReloading && !shooterManager.keepAimingWhenReload) || isEquipping || lockShooterInput || cc.customAction) { _aimTiming = 0; return false; } return shooterManager.hipfireShot && (_aimTiming > 0 || (inputReader != null && inputReader.IsAttackHeld && shooterManager.CurrentWeapon != null) || (!isAimingByInput && shootCountA > 0)); } } public virtual vControlAimCanvas controlAimCanvas { get { if (!_controlAimCanvas) { _controlAimCanvas = FindObjectOfType(); if (_controlAimCanvas) { _controlAimCanvas.Init(cc); } } return _controlAimCanvas; } } public override bool lockInventory { get { return base.lockInventory || isReloading || cc.customAction || cc.isRolling; } } #endregion protected override void Start() { shooterManager = GetComponent(); base.Start(); checkCanAimHeight = cc._capsuleCollider.height; leftHand = animator.GetBoneTransform(HumanBodyBones.LeftHand); rightHand = animator.GetBoneTransform(HumanBodyBones.RightHand); leftLowerArm = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm); rightLowerArm = animator.GetBoneTransform(HumanBodyBones.RightLowerArm); leftUpperArm = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm); rightUpperArm = animator.GetBoneTransform(HumanBodyBones.RightUpperArm); onlyArmsLayer = animator.GetLayerIndex("OnlyArms"); shotLayer = animator.GetLayerIndex("Shot"); aimAngleReference = new GameObject("aimAngleReference"); aimAngleReference.tag = ("Ignore Ragdoll"); aimAngleReference.transform.rotation = transform.rotation; var aimAngleParent = animator.GetBoneTransform(HumanBodyBones.Head); aimAngleReference.transform.SetParent(aimAngleParent); aimAngleReference.transform.localPosition = Vector3.zero; headTrack = GetComponent(); if (headTrack) { headTrack.onInitUpdate.AddListener(UpdateAimAngleReference); } if (!controlAimCanvas) { Debug.LogWarning("Missing the AimCanvas, drag and drop the prefab to this scene in order to Aim", gameObject); } muzzlePosition = Vector3.forward * cc._capsuleCollider.radius * 2; muzzleForward = Vector3.forward; } protected override void LateUpdate() { if ((!updateIK && animator.updateMode == AnimatorUpdateMode.Fixed)) { return; } base.LateUpdate(); UpdateAimBehaviour(); } #region Shooter Inputs protected virtual void Reset() { } /// /// Lock only shooter inputs /// /// lock or unlock public virtual void SetLockShooterInput(bool value) { lockShooterInput = value; if (value) { isBlocking = false; isAimingByInput = false; _aimTiming = 0f; if (controlAimCanvas) { controlAimCanvas.SetActiveAim(false); controlAimCanvas.SetActiveScopeCamera(false); } } } public override void SetLockAllInput(bool value) { base.SetLockAllInput(value); SetLockShooterInput(value); } /// /// Set Always Aiming /// /// value to set aiming public virtual void SetAlwaysAim(bool value) { shooterManager.alwaysAiming = value; } /// /// Current active weapon (if weapon gameobject is disabled this return null) /// public virtual vShooterWeapon CurrentActiveWeapon { get { return shooterManager.CurrentActiveWeapon; } } /// /// Handles all the Controller Input /// public override void InputHandle() { if (cc == null || cc.isDead) { return; } #region BasicInput if (!cc.ragdolled && !lockInput) { MoveInput(); SprintInput(); CrouchInput(); StrafeInput(); JumpInput(); RollInput(); } #endregion #region MeleeInput if (MeleeAttackConditions() && !IsAiming && !isReloading && !lockMeleeInput && !CurrentActiveWeapon) { if (shooterManager.canUseMeleeWeakAttack_H || shooterManager.CurrentWeapon == null) { MeleeWeakAttackInput(); } if (shooterManager.canUseMeleeStrongAttack_H || shooterManager.CurrentWeapon == null) { MeleeStrongAttackInput(); } if (shooterManager.canUseMeleeBlock_H || shooterManager.CurrentWeapon == null) { BlockingInput(); } else { isBlocking = false; } } #endregion #region ShooterInput if (lockShooterInput) { isAimingByInput = false; _aimTiming = 0; if (controlAimCanvas != null) { if (controlAimCanvas.isAimActive || controlAimCanvas.isScopeCameraActive) { isUsingScopeView = false; controlAimCanvas.DisableAim(); } } } else if (shooterManager.CurrentWeapon) { if (MeleeAttackConditions() && (!IsAiming || shooterManager.canUseMeleeAiming)) { if (shooterManager.canUseMeleeWeakAttack_E) { MeleeWeakAttackInput(); } if (shooterManager.canUseMeleeStrongAttack_E) { MeleeStrongAttackInput(); } if (shooterManager.canUseMeleeBlock_E) { BlockingInput(); } else { isBlocking = false; } } else { isBlocking = false; } if (shooterManager == null || CurrentActiveWeapon == null || isEquipping) { if (_walkingByDefaultWasChanged) { _walkingByDefaultWasChanged = false; ResetWalkByDefault(); } if (IsAiming) { isAimingByInput = false; _aimTiming = 0; if (!cc.lockInStrafe && cc.isStrafing) { cc.Strafe(); } if (controlAimCanvas != null) { if (controlAimCanvas.isAimActive || controlAimCanvas.isScopeCameraActive) { isUsingScopeView = false; controlAimCanvas.DisableAim(); } } if (shooterManager && shooterManager.CurrentWeapon && shooterManager.CurrentWeapon.chargeWeapon && shooterManager.CurrentWeapon.powerCharge != 0) { CurrentActiveWeapon.powerCharge = 0; } shootCountA = 0; } } else { AimInput(); ShotInput(); ReloadInput(); SwitchCameraSideInput(); ScopeViewInput(); } } else { isAimingByInput = false; _aimTiming = 0; if (!cc.lockInStrafe && cc.isStrafing && cc.locomotionType != vThirdPersonMotor.LocomotionType.OnlyStrafe) { cc.Strafe(); } if (_walkingByDefaultWasChanged && !IsAiming) { _walkingByDefaultWasChanged = false; ResetWalkByDefault(); } if (controlAimCanvas != null) { if (controlAimCanvas.isAimActive || controlAimCanvas.isScopeCameraActive) { isUsingScopeView = false; controlAimCanvas.DisableAim(); } } } #endregion } /// /// Override the Melee TriggerStrongAttack method to add the call to CancelReload when attacking /// public override void TriggerStrongAttack() { shooterManager.CancelReload(); base.TriggerStrongAttack(); } /// /// Control Aim Input /// public virtual void AimInput() { //Change Rotation Method While Aiming cc.strafeSpeed.rotateWithCamera = IsAiming ? true : cc.strafeSpeed.defaultRotateWithCamera; if (_walkingByDefaultWasChanged && !IsAiming) { _walkingByDefaultWasChanged = false; ResetWalkByDefault(); } if (!shooterManager || isEquipping || isAttacking || (isReloading && (isUsingScopeView || !shooterManager.keepAimingWhenReload))) { if (!isReloading || (isReloading && !shooterManager.keepAimingWhenReload)) { isAimingByInput = false; ResetWalkByDefault(); _walkingByDefaultWasChanged = false; if (cc.isStrafing && cc.locomotionType != vThirdPersonMotor.LocomotionType.OnlyStrafe) { cc.Strafe(); } } if (controlAimCanvas) { if (controlAimCanvas.isAimActive || controlAimCanvas.isScopeCameraActive) { isUsingScopeView = false; controlAimCanvas.DisableAim(); } } return; } if (LockHipFireAiming) _aimTiming = 1f; if (shooterManager.onlyWalkWhenAiming && (!isReloading || shooterManager.keepAimingWhenReload)) { if (isAimingByInput) { SetWalkByDefault(true); _walkingByDefaultWasChanged = true; } else { ResetWalkByDefault(); _walkingByDefaultWasChanged = false; } } if (cc.locomotionType == vThirdPersonMotor.LocomotionType.OnlyFree) { Debug.LogWarning("Shooter behaviour needs to be OnlyStrafe or Free with Strafe. \n Please change the Locomotion Type."); return; } if (shooterManager.hipfireShot && !LockHipFireAiming) { // countdown for the hipfire to reset the aim back to idle if (_aimTiming > 0 && CanRotateAimArm()) { _aimTiming -= Time.deltaTime; } // reset the aimTimming if you sprint while still aiming through the hipfire // if (sprintInput.GetButtonDown() && _aimTiming > 0f) // { // _aimTiming = 0f; // } if(inputReader != null && inputReader.IsSprintHeld && _aimTiming > 0f) { _aimTiming = 0f; } } if (!shooterManager || !CurrentActiveWeapon) { if (controlAimCanvas) { if (controlAimCanvas.isAimActive || controlAimCanvas.isScopeCameraActive) { isUsingScopeView = false; controlAimCanvas.DisableAim(); } } isAimingByInput = false; if (cc.isStrafing) { cc.Strafe(); } return; } if (!cc.isRolling) { isAimingByInput = (!isReloading || shooterManager.keepAimingWhenReload) && (inputReader.IsAimHeld || (shooterManager.alwaysAiming && CurrentActiveWeapon)) && !cc.ragdolled && !cc.customAction; } if (inputReader.ConsumeAimReleased() && !inputReader.IsAttackHeld) { _aimTiming = 0f; } if (headTrack) { headTrack.alwaysFollowCamera = isAimingByInput; } if (cc.locomotionType == vThirdPersonMotor.LocomotionType.FreeWithStrafe) { if (!cc.lockInStrafe) { if (IsAiming && !cc.isStrafing) { cc.Strafe(); } else if (!IsAiming && cc.isStrafing) { cc.Strafe(); } } } if (IsAiming && shooterManager.onlyWalkWhenAiming && cc.isSprinting) { cc.isSprinting = false; } if (controlAimCanvas) { if (!isUsingScopeView) { if (IsAiming && !controlAimCanvas.isAimActive) { controlAimCanvas.SetActiveAim(true); } if (!IsAiming && controlAimCanvas.isAimActive) { controlAimCanvas.SetActiveAim(false); } } } if (shooterManager.rWeapon) { shooterManager.rWeapon.SetActiveAim(IsAiming && aimConditions); shooterManager.rWeapon.SetActiveScope(IsAiming && isUsingScopeView); } else if (shooterManager.lWeapon) { shooterManager.lWeapon.SetActiveAim(IsAiming && aimConditions); shooterManager.lWeapon.SetActiveScope(IsAiming && isUsingScopeView); } } /// /// Control shot inputs (primary and secundary weapons) /// public virtual void ShotInput() { if (!shooterManager || CurrentActiveWeapon == null || cc.isDead || isReloading || isAttacking || isEquipping) { if (shooterManager && shooterManager.CurrentWeapon.chargeWeapon && shooterManager.CurrentWeapon.powerCharge != 0) { CurrentActiveWeapon.powerCharge = 0; } shootCountA = 0; return; } if (IsAiming && !shooterManager.isShooting && aimConditions) { if (CurrentActiveWeapon || (shooterManager.CurrentWeapon && shooterManager.hipfireShot)) { // HandleShotCount(shooterManager.CurrentWeapon, shotInput.GetButton()); HandleShotCount(shooterManager.CurrentWeapon, inputReader.IsAttackHeld); } } else if (!IsAiming) { if (shooterManager.CurrentWeapon.chargeWeapon && shooterManager.CurrentWeapon.powerCharge != 0) { CurrentActiveWeapon.powerCharge = 0; } shootCountA = 0; } } /// /// Control Shot count /// /// target weapon /// check input public virtual void HandleShotCount(vShooterWeapon weapon, bool weaponInput = true) { if (weapon.chargeWeapon) { if (shooterManager.WeaponHasLoadedAmmo() && weapon.powerCharge < 1 && weaponInput) { if (shooterManager.hipfireShot) { _aimTiming = shooterManager.HipfireAimTime; } weapon.powerCharge += Time.fixedDeltaTime * weapon.chargeSpeed; } else if ((weapon.powerCharge >= 1 && weapon.autoShotOnFinishCharge && weaponInput) || (!weaponInput && IsAiming && weapon.powerCharge > 0f)) { if (shooterManager.hipfireShot) { _aimTiming = shooterManager.HipfireAimTime; } shootCountA = 1; } animator.SetFloat(vAnimatorParameters.PowerCharger, weapon.powerCharge); } else if (weapon.automaticWeapon && weaponInput) { if (shooterManager.hipfireShot && !isAimingByInput) { _aimTiming = shooterManager.HipfireAimTime; } shootCountA = 1; } else if (weaponInput) { if (shooterManager.hipfireShot && !isAimingByInput) { _aimTiming = shooterManager.HipfireAimTime; } if (allowAttack == false) { shootCountA = 1; allowAttack = true; } } else { allowAttack = false; } } /// /// Do Shots by shotcount after Ik behaviour updated /// public virtual void DoShots() { if (CanDoShots()) { TriggerShot(); } } public virtual void TriggerShot() { animator.SetFloat(vAnimatorParameters.Shot_ID, shooterManager.GetShotID()); shooterManager.Shoot(AimPosition, !isAimingByInput); if (CurrentActiveWeapon.chargeWeapon) CurrentActiveWeapon.powerCharge = 0; shootCountA--; } /// /// Reload current weapon /// public virtual void ReloadInput() { if (!shooterManager || CurrentActiveWeapon == null || isReloading || cc.customAction || shooterManager.isShooting || cc.ragdolled) { return; } if (inputReader.ConsumeReload()) { shootCountA = 0; _aimTiming = 0f; shooterManager.ReloadWeapon(); } else { if (CurrentActiveWeapon.autoReload && !shooterManager.WeaponHasLoadedAmmo() && shooterManager.WeaponHasUnloadedAmmo()) { switch (CurrentActiveWeapon.autoReloadStyle) { case vShooterWeapon.AutoReloadStyle.WhenAiming: if (IsAiming) shooterManager.ReloadWeapon(); break; case vShooterWeapon.AutoReloadStyle.WhenShot: if (inputReader.ConsumeAttack()) shooterManager.ReloadWeapon(); break; case vShooterWeapon.AutoReloadStyle.WhenAmmoAvailable: shooterManager.ReloadWeapon(); break; } } } } /// /// Control Switch Camera side Input /// public virtual void SwitchCameraSideInput() { if (tpCamera == null || inputReader == null) { return; } if (inputReader.ConsumeSwitchSide()) { SwitchCameraSide(); } } /// /// Change side view of the /// public virtual void SwitchCameraSide() { if (tpCamera == null) { return; } isCameraRightSwitched = !isCameraRightSwitched; tpCamera.SwitchRight(isCameraRightSwitched); } /// /// Reset the Aiming and AimCanvas to false /// public virtual void CancelAiming() { isAimingByInput = false; _aimTiming = 0; if (controlAimCanvas) { controlAimCanvas.SetActiveAim(false); controlAimCanvas.SetActiveScopeCamera(false); } } /// /// Control Scope view input /// public virtual void ScopeViewInput() { if (!shooterManager || CurrentActiveWeapon == null) { return; } if (isAimingByInput && aimConditions && (inputReader.ConsumeScopeView() || CurrentActiveWeapon.onlyUseScopeUIView)) { if (controlAimCanvas && CurrentActiveWeapon.scopeTarget) { if (!isUsingScopeView && CurrentActiveWeapon.onlyUseScopeUIView) { EnableScopeView(); } else if (isUsingScopeView && !CurrentActiveWeapon.onlyUseScopeUIView) { DisableScopeView(); } else if (!isUsingScopeView) { EnableScopeView(); } } } else if (isUsingScopeView && (controlAimCanvas && !isAimingByInput || controlAimCanvas && !aimConditions || cc.isRolling)) { DisableScopeView(); } } /// /// Enable scope view (just if is aiming) /// public virtual void EnableScopeView() { if (!isAimingByInput || !controlAimCanvas.scopeBackgroundCamera || isReloading || isEquipping) { return; } isUsingScopeView = true; controlAimCanvas.SetActiveScopeCamera(true, CurrentActiveWeapon.useUI); controlAimCanvas.SetActiveAim(false); } /// /// Disable scope view /// public virtual void DisableScopeView() { if (!controlAimCanvas.scopeBackgroundCamera) return; isUsingScopeView = false; var lastState = tpCamera.useSmooth; tpCamera.useSmooth = false; tpCamera.mouseX = lastTargetCameraEuler.y; tpCamera.mouseY = lastTargetCameraEuler.x; tpCamera.CameraMovement(); tpCamera.useSmooth = lastState; controlAimCanvas.SetActiveScopeCamera(false); controlAimCanvas.SetActiveAim(IsAiming); } #endregion #region Update Animations protected override void UpdateMeleeAnimations() { // disable the onlyarms layer and run the melee methods if the character is not using any shooter weapon if (!animator) { return; } // find states with the IsEquipping tag isEquipping = cc.IsAnimatorTag("IsEquipping"); // Check if Animator state need to ignore IK _ignoreIKFromAnimator = cc.IsAnimatorTag("IgnoreIK"); if (cc.customAction) { ResetMeleeAnimations(); ResetShooterAnimations(); // reset to the default camera state UpdateCameraStates(); // reset the aiming CancelAiming(); return; } // update MeleeManager Animator Properties if ((shooterManager == null || !CurrentActiveWeapon) && meleeManager) { base.UpdateMeleeAnimations(); // set the uppbody id (armsonly layer) //animator.SetFloat(vAnimatorParameters.UpperBody_ID, 0, .2f, Time.fixedDeltaTime); // turn on the onlyarms layer to aim onlyArmsLayerWeight = Mathf.Lerp(onlyArmsLayerWeight, 0, 6f * vTime.fixedDeltaTime); animator.SetLayerWeight(onlyArmsLayer, onlyArmsLayerWeight); // reset aiming parameter animator.SetBool(vAnimatorParameters.IsAiming, false); // animator.SetBool(vAnimatorParameters.IsHipFire, false); isReloading = false; } // update ShooterManager Animator Properties else if (shooterManager && CurrentActiveWeapon) { UpdateShooterAnimations(); } // reset Animator Properties else { ResetMoveSet(); ResetMeleeAnimations(); ResetShooterAnimations(); } } public virtual void ResetMoveSet() { cc.animator.SetFloat(vAnimatorParameters.MoveSet_ID, defaultMoveSetID, .2f, Time.fixedDeltaTime); } public virtual void ResetShooterAnimations() { if (shooterManager == null || !animator) { return; } // set the uppbody id (armsonly layer) animator.SetFloat(vAnimatorParameters.UpperBody_ID, 0, .2f, vTime.fixedDeltaTime); // set if the character can aim or not (upperbody layer) animator.SetBool(vAnimatorParameters.CanAim, false); // character is aiming animator.SetBool(vAnimatorParameters.IsAiming, false); // animator.SetBool(vAnimatorParameters.IsHipFire, false); // turn on the onlyarms layer to aim onlyArmsLayerWeight = Mathf.Lerp(onlyArmsLayerWeight, 0, 6f * vTime.fixedDeltaTime); animator.SetLayerWeight(onlyArmsLayer, onlyArmsLayerWeight); } protected virtual void UpdateShooterAnimations() { if (shooterManager == null) { return; } // turn on the onlyarms layer to aim onlyArmsLayerWeight = Mathf.Lerp(onlyArmsLayerWeight, (CurrentActiveWeapon || isEquipping) ? 1f : 0f, shooterManager.onlyArmsSpeed * vTime.fixedDeltaTime); animator.SetLayerWeight(onlyArmsLayer, onlyArmsLayerWeight); if (CurrentActiveWeapon && IsAiming) animator.SetLayerWeight(shotLayer, isUsingScopeView ? CurrentActiveWeapon.scopeShootAnimationWeight : 1f); if (CurrentActiveWeapon && !shooterManager.useDefaultMovesetWhenNotAiming || IsAiming) { // set the move set id (base layer) animator.SetFloat(vAnimatorParameters.MoveSet_ID, shooterMoveSetID, .1f, vTime.fixedDeltaTime); } else if (!CurrentActiveWeapon && !shooterManager.useDefaultMovesetWhenNotAiming || shooterManager.useDefaultMovesetWhenNotAiming) { // set the move set id (base layer) animator.SetFloat(vAnimatorParameters.MoveSet_ID, defaultMoveSetID, .1f, vTime.fixedDeltaTime); } animator.SetInteger(vAnimatorParameters.DefenseID, DefenseID); // set the isBlocking false while using shooter weapons animator.SetBool(vAnimatorParameters.IsBlocking, isBlocking); // set the uppbody id (armsonly layer) animator.SetFloat(vAnimatorParameters.UpperBody_ID, shooterManager.GetUpperBodyID()); // set if the character can aim or not (upperbody layer) animator.SetBool(vAnimatorParameters.CanAim, aimConditions); // character is aiming animator.SetBool(vAnimatorParameters.IsAiming, IsAiming); // animator.SetBool(vAnimatorParameters.IsHipFire, isAimingByHipFire); // find states with the Reload tag isReloading = cc.IsAnimatorTag("IsReloading") || shooterManager.isReloadingWeapon; vAnimatorParameter ap = new vAnimatorParameter(animator, "IsReloading"); } /// /// Current moveset id based if is using weapon or not /// public virtual int shooterMoveSetID { get { int id = shooterManager.GetMoveSetID(); if (id == 0 || overrideWeaponMoveSetID) { id = defaultMoveSetID; } return id; } } public override void UpdateCameraStates() { // CAMERA STATE - you can change the CameraState here, the bool means if you want lerp of not, make sure to use the same CameraState String that you named on TPCameraListData if (ignoreTpCamera) { return; } if (tpCamera == null) { tpCamera = FindObjectOfType(); if (tpCamera == null) { return; } if (tpCamera) { tpCamera.SetMainTarget(this.transform); tpCamera.Init(); } } if (changeCameraState) { tpCamera.ChangeState(customCameraState, customlookAtPoint, true); } else if (cc.isCrouching && !isAimingByInput) { tpCamera.ChangeState("Crouch", true); } else if (cc.isStrafing && !isAimingByInput) { tpCamera.ChangeState("Strafing", true); } else if (isAimingByInput && CurrentActiveWeapon) { if (isUsingScopeView) { if (string.IsNullOrEmpty(CurrentActiveWeapon.customScopeCameraState)) { tpCamera.ChangeState(cc.isCrouching ? "CrouchingAiming" : "Aiming", true); } else { tpCamera.ChangeState(CurrentActiveWeapon.customScopeCameraState, true); } } else { if (string.IsNullOrEmpty(CurrentActiveWeapon.customAimCameraState)) { tpCamera.ChangeState(cc.isCrouching ? "CrouchingAiming" : "Aiming", true); } else { tpCamera.ChangeState(CurrentActiveWeapon.customAimCameraState, true); } } } else { tpCamera.ChangeState("Default", true); } } #endregion #region Update Aim protected Ray ray = new Ray(); /// /// Calculate the /// protected virtual void UpdateDesiredAimPosition() { if (!shooterManager) { return; } if (CurrentActiveWeapon == null) { return; } if (isUsingScopeView) { DesiredAimPosition = cameraMain.transform.TransformPoint(localAimPosition); return; } var camT = cameraMain.transform; var vOrigin = camT.position; var desiredAimPoint = camT.position + camT.forward * cameraMain.farClipPlane; ray.origin = vOrigin; ray.direction = camT.forward; if (shooterManager.raycastAimTarget && CurrentActiveWeapon.raycastAimTarget) { RaycastHit hit; if (Physics.Raycast(ray, out hit, cameraMain.farClipPlane, shooterManager.damageLayer)) { bool canAimToHit = false; var dist = cameraMain.farClipPlane; //Check if hit object is child of character transform if (hit.collider.transform.IsChildOf(transform)) { var collider = hit.collider; //Clear last hit infor hit = new RaycastHit(); var hits = Physics.RaycastAll(ray, cameraMain.farClipPlane, shooterManager.damageLayer); ///Try to find other hit point next to character transform for (int i = 0; i < hits.Length; i++) { if (hits[i].distance < dist && hits[i].collider.gameObject != collider.gameObject && !hits[i].collider.transform.IsChildOf(transform)) { dist = hits[i].distance; hit = hits[i]; canAimToHit = true; } } } else canAimToHit = true; if (canAimToHit) { desiredAimPoint = hit.point; } } } var localAimPoint = aimAngleReference.transform.InverseTransformPoint(desiredAimPoint); if (!isUsingScopeView) { if (!shooterManager.ignoreBackAimPoint) localAimPoint.z = Mathf.Max(localAimPoint.z, (muzzlePosition.z + shooterManager.backAimPointOffset + shooterManager.minAimHitPointDistance)); desiredAimPoint = aimAngleReference.transform.TransformPoint(localAimPoint); } DesiredAimPosition = desiredAimPoint; localAimPosition = cameraMain.transform.InverseTransformPoint(DesiredAimPosition); } /// /// Calculate the /// protected virtual void UpdateAimPosition() { if (!shooterManager) { return; } if (CurrentActiveWeapon == null) { return; } Vector3 rayDirection = DesiredAimPosition - CurrentActiveWeapon.aimReference.position; ray.origin = CurrentActiveWeapon.aimReference.position; ray.direction = rayDirection; Vector3 desiredAimPoint = DesiredAimPosition; RaycastHit hit; var castLayer = shooterManager.blockAimLayer; var castDistance = rayDirection.magnitude; var castRay = ray; if (Physics.Raycast(castRay, out hit, castDistance, castLayer)) { bool canAimToHit = false; var dist = cameraMain.farClipPlane; //Check if hit object is child of character transform if (hit.collider.transform.IsChildOf(transform)) { var collider = hit.collider; //Clear last hit infor hit = new RaycastHit(); var hits = Physics.RaycastAll(castRay, castDistance, castLayer); ///Try to find other hit point next to character transform for (int i = 0; i < hits.Length; i++) { if (hits[i].distance < dist && hits[i].collider.gameObject != collider.gameObject && !hits[i].collider.transform.IsChildOf(transform)) { dist = hits[i].distance; hit = hits[i]; canAimToHit = true; } } } else canAimToHit = true; if (hit.collider && canAimToHit) { desiredAimPoint = hit.point; } } AimPosition = desiredAimPoint; if (isUsingScopeView) { var rotation = Quaternion.LookRotation(AimPosition - cameraMain.transform.position, cameraMain.transform.up); lastTargetCameraEuler = rotation.eulerAngles.NormalizeAngle(); } if (isAimingByInput) { shooterManager.CameraSway(); } } public override void ControlRotation() { base.ControlRotation(); } public override void CameraInput() { base.CameraInput(); } #endregion #region IK behaviour protected virtual void UpdateAimBehaviour() { if (cc.isDead || cc.ragdolled) { return; } UpdateDesiredAimPosition(); UpdateHeadTrack(); OnStartUpdateIK(); CheckAimConditions(); if (shooterManager && CurrentActiveWeapon) { UpdateIKAdjust(shooterManager.IsLeftWeapon); AlignArmToAimPosition(shooterManager.IsLeftWeapon); UpdateArmsIK(shooterManager.IsLeftWeapon); } UpdateAimPosition(); OnFinishUpdateIK(); UpdateAimHud(); DoShots(); CheckAimEvents(); } protected virtual void CheckAimEvents() { if (IsAiming != wasAiming) { wasAiming = IsAiming; if (IsAiming) shooterManager.onEnableAim.Invoke(shooterManager.CurrentWeapon); else shooterManager.onDisableAim.Invoke(shooterManager.CurrentWeapon); } if (isUsingScopeView != wasAimingWithScope) { wasAimingWithScope = isUsingScopeView; if (IsAiming) shooterManager.onEnableScopeView.Invoke(shooterManager.CurrentWeapon); else shooterManager.onDisableScopeView.Invoke(shooterManager.CurrentWeapon); } } protected virtual void UpdateAimAngleReference() { aimAngleReference.transform.rotation = transform.rotation; UpdateCheckAimHelpers(shooterManager.IsLeftWeapon); } protected void UpdateCheckAimHelpers(bool isUsingLeftHand) { if (!CurrentActiveWeapon) return; var weight = (float)System.Math.Round(armAlignmentWeight, 1); var upperArm = isUsingLeftHand ? leftUpperArm : rightUpperArm; upperArmPosition = Vector3.Lerp(upperArmPosition, aimAngleReference.transform.InverseTransformPoint(upperArm.position), weight); muzzlePosition = Vector3.Lerp(muzzlePosition, aimAngleReference.transform.InverseTransformPoint(CurrentActiveWeapon.muzzle.position), weight); muzzleForward = Vector3.Lerp(muzzleForward, aimAngleReference.transform.InverseTransformDirection(CurrentActiveWeapon.muzzle.forward), weight); } public virtual void UpdateCheckAimPoints(ref Vector3 start, ref Vector3 end) { if (CurrentActiveWeapon) { float checkAimSmooth = shooterManager.checkAimOffsetSmooth; ///Lerp offsets checkCanAimOffsetStartX = Mathf.Lerp(checkCanAimOffsetStartX, IsCrouching ? shooterManager.checkAimCrouchedOffsetStartX : shooterManager.checkAimStandingOffsetStartX, checkAimSmooth * Time.fixedDeltaTime); checkCanAimOffsetStartY = Mathf.Lerp(checkCanAimOffsetStartY, IsCrouching ? shooterManager.checkAimCrouchedOffsetStartY : shooterManager.checkAimStandingOffsetStartY, checkAimSmooth * Time.fixedDeltaTime); checkCanAimOffsetEndX = Mathf.Lerp(checkCanAimOffsetEndX, IsCrouching ? shooterManager.checkAimCrouchedOffsetEndX : shooterManager.checkAimStandingOffsetEndX, checkAimSmooth * Time.fixedDeltaTime); checkCanAimOffsetEndY = Mathf.Lerp(checkCanAimOffsetEndY, IsCrouching ? shooterManager.checkAimCrouchedOffsetEndY : shooterManager.checkAimStandingOffsetEndY, checkAimSmooth * Time.fixedDeltaTime); var startX = checkCanAimOffsetStartX; var startY = checkCanAimOffsetStartY; var endX = checkCanAimOffsetEndX; var endY = checkCanAimOffsetEndY; onUpdateCheckAimPointsEvent?.Invoke(ref startX, ref endX, ref startY, ref endY); /// Make original points to check aim Vector3 startPoint = aimAngleReference.transform.TransformPoint(upperArmPosition); float upperArmToMuzzleDistance = Vector3.Distance(startPoint, aimAngleReference.transform.TransformPoint(muzzlePosition)); var endPoint = startPoint + (DesiredAimPosition - startPoint).normalized * upperArmToMuzzleDistance; Vector3 forward = (DesiredAimPosition - startPoint).normalized; ///Apply offsets Vector3 newStartPoint = startPoint + cameraMain.transform.right * (startX * (tpCamera.switchRight > 0 ? 1 : -1)) + cameraMain.transform.up * startY; Vector3 newEndPoint = endPoint + cameraMain.transform.right * (endX * (tpCamera.switchRight > 0 ? 1 : -1)) + cameraMain.transform.up * endY + forward * shooterManager.checkAimOffsetZ; start = newStartPoint; end = newEndPoint; } } public delegate void UpdateCheckAimPointsEvent(ref float startX, ref float endX,ref float startY,ref float endY); public UpdateCheckAimPointsEvent onUpdateCheckAimPointsEvent; protected virtual void OnFinishUpdateIK() { onFinishUpdateIK?.Invoke(); } protected virtual void OnStartUpdateIK() { onStartUpdateIK?.Invoke(); } protected virtual void UpdateIKAdjust(bool isUsingLeftHand) { // create left arm ik solver if equal null if (LeftIK == null || !LeftIK.isValidBones) { LeftIK = new vIKSolver(animator, AvatarIKGoal.LeftHand); LeftIK.UpdateIK(); } if (RightIK == null || !RightIK.isValidBones) { RightIK = new vIKSolver(animator, AvatarIKGoal.RightHand); RightIK.UpdateIK(); } if (WeaponIKAdjustList == null) return; else { CurrentActiveWeapon.handIKTargetOffset.localPosition = isUsingLeftHand ? WeaponIKAdjustList.ikTargetPositionOffsetL : WeaponIKAdjustList.ikTargetPositionOffsetR; CurrentActiveWeapon.handIKTargetOffset.localEulerAngles = isUsingLeftHand ? WeaponIKAdjustList.ikTargetRotationOffsetL : WeaponIKAdjustList.ikTargetRotationOffsetR; } if (!CurrentWeaponIK ) { LeftIK.UpdateIK(); RightIK.UpdateIK(); RightIK.SetIKWeight(0); LeftIK.SetIKWeight(0); weaponIKWeight = 0; return; } bool isValidIK = !IsIgnoreIK && !cc.customAction && !isReloading && !isEquipping && CurrentWeaponIK != null && CurrentIKAdjust != null; weaponIKWeight = Mathf.Lerp(weaponIKWeight, isValidIK ? 1 : 0, shooterManager.ikAdjustSmooth*Time.fixedDeltaTime); if (weaponIKWeight <= 0) { return; } if (isUsingLeftHand) { ApplyOffsets(LeftIK, RightIK, isValidIK); } else { ApplyOffsets(RightIK, LeftIK, isValidIK); } } protected virtual void ApplyOffsets(vIKSolver weaponHand, vIKSolver supportHand, bool isValidIK = true) { if (!weaponHand.isValidBones || !supportHand.isValidBones) return; //Apply Offset to Weapon Arm weaponHand.SetIKWeight(shooterManager.ikAdjustWeightCurve.Evaluate(weaponIKWeight)); ApplyOffsetToTargetBone(isValidIK ? CurrentIKAdjust.weaponHandOffset : null, weaponHand.endBoneOffset, isValidIK); ApplyOffsetToTargetBone(isValidIK ? CurrentIKAdjust.weaponHintOffset : null, weaponHand.middleBoneOffset, isValidIK); weaponHand.AnimationToIK(); //Apply offset to Support Weapon Arm ApplyOffsetToTargetBone(isValidIK ? CurrentIKAdjust.supportHandOffset : null, supportHand.endBoneOffset, !EditingIKGlobalOffset && isValidIK); ApplyOffsetToTargetBone(isValidIK ? CurrentIKAdjust.supportHintOffset : null, supportHand.middleBoneOffset, !EditingIKGlobalOffset && isValidIK); } protected virtual void ApplyOffsetToTargetBone(IKOffsetTransform iKOffset, Transform target, bool isValidIK) { try { target.localPosition = Vector3.Lerp(target.localPosition, isValidIK ? iKOffset.position : Vector3.zero, shooterManager.ikAdjustSmooth * vTime.fixedDeltaTime); target.localRotation = Quaternion.Lerp(target.localRotation, isValidIK ? Quaternion.Euler(iKOffset.eulerAngles) : Quaternion.Euler(Vector3.zero), shooterManager.ikAdjustSmooth * vTime.fixedDeltaTime); } catch { Debug.LogWarning("Can't Get IK Adjust"); } } protected virtual void UpdateArmsIK(bool isUsingLeftHand = false) { // create left arm ik solver if equal null if (LeftIK == null || !LeftIK.isValidBones) { LeftIK = new vIKSolver(animator, AvatarIKGoal.LeftHand); } if (RightIK == null || !RightIK.isValidBones) { RightIK = new vIKSolver(animator, AvatarIKGoal.RightHand); } vIKSolver targetIK = null; if (isUsingLeftHand) { targetIK = RightIK; } else { targetIK = LeftIK; } bool useIK = isUsingLeftHand ? shooterManager.useLeftIK : shooterManager.useRightIK; if ((!shooterManager || !CurrentActiveWeapon || IsIgnoreIK || isEquipping) || (cc.IsAnimatorTag("Shot Fire") && CurrentActiveWeapon.disableIkOnShot)) { useIK = false; } bool useIkConditions = false; var animatorInput = System.Math.Round(cc.inputMagnitude, 1); if(!useIK) { useIkConditions = false; } else if (!IsAiming && !isAttacking) { var locomotionValidation = cc.isStrafing ? CurrentActiveWeapon.strafeIKOptions : CurrentActiveWeapon.freeIKOptions; if (locomotionValidation.use) { if (animatorInput <= 0.1f) { useIkConditions = locomotionValidation.useOnIdle; } else if (animatorInput <= 0.5f) { useIkConditions = locomotionValidation.useOnWalk; } else if (animatorInput <= 1f) { useIkConditions = locomotionValidation.useOnRun; } else if (animatorInput <= 1.5f) { useIkConditions = locomotionValidation.useOnSprint; } } else useIkConditions = false; } else if (IsAiming && !isAttacking) { useIkConditions = shooterManager.isShooting ? !CurrentActiveWeapon.disableIkOnShot : CurrentActiveWeapon.useIKOnAiming; } else if (isAttacking) { useIkConditions = CurrentActiveWeapon.useIkAttacking; } IsSupportHandIKEnabled = useIkConditions && !IsIgnoreSupportHandIK; if (targetIK != null) { if (shooterManager.weaponIKAdjustList) { if (isUsingLeftHand) { ikRotationOffset = shooterManager.weaponIKAdjustList.ikTargetRotationOffsetR; ikPositionOffset = shooterManager.weaponIKAdjustList.ikTargetPositionOffsetR; } else { ikRotationOffset = shooterManager.weaponIKAdjustList.ikTargetRotationOffsetL; ikPositionOffset = shooterManager.weaponIKAdjustList.ikTargetPositionOffsetL; } } // Debug.Log($"using ik {useIkConditions.ToStringColor()}");//Debug IK Conditions // control weight of ik if (CurrentActiveWeapon && CurrentActiveWeapon.handIKTargetOffset && !isReloading && !cc.customAction && (cc.isGrounded || (IsAiming)) && IsSupportHandIKEnabled) { supportIKWeight = Mathf.Lerp(supportIKWeight, 1, shooterManager.armIKSmoothIn * vTime.fixedDeltaTime); } else { supportIKWeight = Mathf.Lerp(supportIKWeight, 0, shooterManager.armIKSmoothOut * vTime.fixedDeltaTime); } if (supportIKWeight <= 0 ) { if (!IsSupportHandIKEnabled && shooterManager.CurrentWeaponIK) { targetIK.SetIKWeight(shooterManager.armIKCurve.Evaluate(supportIKWeight)); targetIK.AnimationToIK(); } return; } // update IK targetIK.SetIKWeight(shooterManager.armIKCurve.Evaluate(supportIKWeight)); if (shooterManager && CurrentActiveWeapon && CurrentActiveWeapon.handIKTargetOffset) { targetIK.SetIKPosition(CurrentActiveWeapon.handIKTargetOffset.position); targetIK.SetIKRotation(CurrentActiveWeapon.handIKTargetOffset.rotation); if (shooterManager.CurrentWeaponIK) { targetIK.AnimationToIK(); } } } } protected virtual bool CanRotateAimArm() { return cc.IsAnimatorTag("Upperbody Pose") && cc.animatorStateInfos.GetCurrentNormalizedTime(cc.upperBodyLayer) > 0.5f; } protected virtual bool CanDoShots() { return armAlignmentWeight >= 0.5f && cc.IsAnimatorTag("Upperbody Pose") && shootCountA > 0 && !isReloading; } protected virtual void AlignArmToAimPosition(bool isUsingLeftHand = false) { if (!shooterManager) { return; } ///Init the arms, if needs that if (leftArmAim == null) leftArmAim = new vArmAimAlign(leftUpperArm, leftLowerArm, leftHand); if (rightArmAim == null) rightArmAim = new vArmAimAlign(rightUpperArm, rightLowerArm, rightHand); /// Select the arm vArmAimAlign arm = isUsingLeftHand ? leftArmAim : rightArmAim; ///Calculate the Alignment weight based on aim conditions. armAlignmentWeight = IsAiming && aimConditions && CanRotateAimArm() ? Mathf.Lerp(armAlignmentWeight, Mathf.Clamp(cc.upperBodyInfo.normalizedTime, 0, 1f), shooterManager.smoothArmWeight * (.001f + Time.fixedDeltaTime)) : 0; if (CurrentActiveWeapon) { if (!shooterManager.isShooting) { ///Update arm to use default animation rotation while not shooting arm.UpdateDefaultAlignment(); } else { ///Use last alignment to ignore shoot animation rotation ///When shooting the arm position and rotation will be changed by the animation ///This method avoid this changes using the last alignment before the shot was performed arm.RestoreToLastAlignment(); } /// Set the Arm aligment values arm.smoothIKAlignmentPoint = shooterManager.smoothIKAlignmentPoint; arm.aimReference = CurrentActiveWeapon.aimReference; arm.smooth = shooterManager.smoothArmIKRotation; arm.maxVerticalAligmentAngle = shooterManager.maxVerticalAimAngle; arm.maxHorizontalAligmentAngle = shooterManager.maxHorizontalAimAngle; if (shooterManager.showCheckAimGizmos) arm.DrawBones(Color.blue); ///Align arm to target aim position arm.AlignToArmToPosition(targetArmAlignmentPosition, armAlignmentWeight, CurrentActiveWeapon.alignRightUpperArmToAim, CurrentActiveWeapon.alignRightHandToAim); if (shooterManager.showCheckAimGizmos) arm.DrawHelpers(Color.green); } } protected virtual void CheckAimConditions() { if (!shooterManager) { return; } var weaponSide = (tpCamera.switchRight < 0 ? -1 : 1); if (CurrentActiveWeapon == null) { aimConditions = false; return; } if (shooterManager.useCheckAim == false) { aimConditions = true; return; } Vector3 startPoint = Vector3.zero; Vector3 endPoint = Vector3.zero; Ray _ray = new Ray(startPoint, ((endPoint) - startPoint).normalized); bool _aimCondition = aimConditions; if (animator.IsInTransition(0)) { if (Physics.SphereCast(_ray, shooterManager.checkAimRadius, out checkCanAimHit, (endPoint - startPoint).magnitude, shooterManager.blockAimLayer)) { aimConditions = false; } _aimCondition = aimConditions; checkAimConditionOverride?.Invoke(startPoint, endPoint, ref _aimCondition); aimConditions = _aimCondition; return; } UpdateCheckAimPoints(ref startPoint, ref endPoint); _ray = new Ray(startPoint, ((endPoint) - startPoint).normalized); if (Vector3.Distance(startPoint, AimPosition) < Vector3.Distance(startPoint, endPoint)) aimConditions = false; if (Physics.SphereCast(_ray, shooterManager.checkAimRadius, out checkCanAimHit, (endPoint - startPoint).magnitude, shooterManager.blockAimLayer)) { aimConditions = false; } else { aimConditions = true; } _aimCondition = aimConditions; checkAimConditionOverride?.Invoke(startPoint, endPoint, ref _aimCondition); aimConditions = _aimCondition; } public delegate void CheckAimConditionsEvent( Vector3 startPoint, Vector3 endPoint,ref bool aimConditions); public CheckAimConditionsEvent checkAimConditionOverride; protected virtual Vector3 targetArmAlignmentPosition { get { return shooterManager.alignArmToHitPoint || isUsingScopeView ? DesiredAimPosition : cameraMain.transform.position + cameraMain.transform.forward * 100; } } protected virtual Transform targetCamera { get { var t = controlAimCanvas && controlAimCanvas.isScopeCameraActive && controlAimCanvas.scopeBackgroundCamera ? controlAimCanvas.scopeBackgroundCamera.transform : cameraMain.transform; return t; } } protected virtual Vector3 targetArmAlignmentDirection { get { return targetCamera.forward; } } protected virtual void UpdateHeadTrack() { if (headTrack) { UpdateHeadTrackLookPoint(); } if (!shooterManager || !headTrack) { if (headTrack) { headTrack.offsetSpine = Vector2.Lerp(headTrack.offsetSpine, Vector2.zero, weaponIKWeight); headTrack.offsetHead = Vector2.Lerp(headTrack.offsetHead, Vector2.zero, weaponIKWeight); } return; } if (!CurrentActiveWeapon || !headTrack || !CurrentWeaponIK || CurrentIKAdjust == null) { if (headTrack) { headTrack.offsetSpine = Vector2.Lerp(headTrack.offsetSpine, Vector2.zero, weaponIKWeight); headTrack.offsetHead = Vector2.Lerp(headTrack.offsetHead, Vector2.zero, weaponIKWeight); } return; } if (IsAiming) { var ikAdjust = CurrentIKAdjust; var offsetSpine = ikAdjust.spineOffset.spine; var offsetHead = ikAdjust.spineOffset.head; headTrack.offsetSpine = Vector2.Lerp(headTrack.offsetSpine, offsetSpine, weaponIKWeight); headTrack.offsetHead = Vector2.Lerp(headTrack.offsetHead, offsetHead, weaponIKWeight); } else { var ikAdjust = CurrentIKAdjust; var offsetSpine = ikAdjust.spineOffset.spine; var offsetHead = ikAdjust.spineOffset.head; headTrack.offsetSpine = Vector2.Lerp(headTrack.offsetSpine, offsetSpine, headTrack.Smooth); headTrack.offsetHead = Vector2.Lerp(headTrack.offsetHead, offsetHead, headTrack.Smooth); } } protected virtual void UpdateHeadTrackLookPoint() { if (IsAiming /*&& !isUsingScopeView*/ && CurrentActiveWeapon && aimConditions) { headTrack.SetTemporaryLookPoint(targetArmAlignmentPosition); //cameraMain.transform.TransformPoint(Vector3.forward * (cameraMain.transform.InverseTransformPoint(CurrentActiveWeapon.muzzle.position).z + 10)), 0.1f); } } protected virtual void UpdateAimHud() { if (!shooterManager || !controlAimCanvas) { return; } if (CurrentActiveWeapon == null) { return; } var _aimPoint = AimPosition; controlAimCanvas.SetAimCanvasID(CurrentActiveWeapon.scopeID); if (controlAimCanvas.scopeBackgroundCamera && controlAimCanvas.scopeBackgroundCamera.gameObject.activeSelf) { controlAimCanvas.SetAimToCenter(true); } else if (IsAiming && aimConditions) { var aimDistance = Vector3.Distance(aimAngleReference.transform.position, _aimPoint); var validAim = (aimDistance > shooterManager.maxAimHitPointIndicator || Vector3.Distance(AimPosition, DesiredAimPosition) < 0.1f) && aimConditions; if (aimDistance > shooterManager.maxAimHitPointIndicator || Vector3.Distance(AimPosition, DesiredAimPosition) < 0.1f) controlAimCanvas.SetAimToCenter(true); else controlAimCanvas.SetWordPosition(_aimPoint, validAim); } else { controlAimCanvas.SetAimToCenter(aimConditions); } if ((controlAimCanvas.scopeBackgroundCamera && CurrentActiveWeapon.scopeTarget)) { if (isUsingScopeView || controlAimCanvas.isScopeCameraActive) { vArmAimAlign arm = shooterManager.IsLeftWeapon ? leftArmAim : rightArmAim; if (!shooterManager.isShooting) { scopeLocalForward = arm.aimReferenceHelper.InverseTransformDirection(CurrentActiveWeapon.scopeTarget.forward); scopeLocalPosition = arm.aimReferenceHelper.InverseTransformPoint(CurrentActiveWeapon.scopeTarget.position); scopeCameraLocalForward = aimAngleReference.transform.InverseTransformDirection(controlAimCanvas.scopeBackgroundCamera.transform.forward); scopeCameraLocalPosition = aimAngleReference.transform.InverseTransformPoint(controlAimCanvas.scopeBackgroundCamera.transform.position); } var weight = (shooterManager.isShooting ? (1 - CurrentActiveWeapon.scopeShootAnimationWeight) : 1f); var scopCameraPosition = aimAngleReference.transform.TransformPoint(scopeCameraLocalPosition); var scopCameraForward = aimAngleReference.transform.TransformDirection(scopeCameraLocalForward); var scopeLookDirection = Vector3.Lerp(scopCameraForward, arm.aimReferenceHelper.TransformDirection(scopeLocalForward), scopeDirectionWeight = Mathf.Lerp(scopeDirectionWeight, 1.001f, (10f / CurrentActiveWeapon.shootFrequency) * Time.fixedDeltaTime)); var scopePosition = Vector3.Lerp(scopCameraPosition, arm.aimReferenceHelper.TransformPoint(scopeLocalPosition), weight); controlAimCanvas.UpdateScopeCamera(scopePosition, scopeLookDirection, aimAngleReference.transform.up, CurrentActiveWeapon.backGroundScopeZoom, IsAiming); } else scopeDirectionWeight = 1f; } } #endregion } public static partial class vAnimatorParameters { public static int UpperBody_ID = Animator.StringToHash("UpperBody_ID"); public static int CanAim = Animator.StringToHash("CanAim"); public static int IsAiming = Animator.StringToHash("IsAiming"); public static int IsHipFire = Animator.StringToHash("IsHipFire"); public static int Shot_ID = Animator.StringToHash("Shot_ID"); public static int PowerCharger = Animator.StringToHash("PowerCharger"); } }