slow mo in combos
This commit is contained in:
@@ -732,13 +732,17 @@ MonoBehaviour:
|
|||||||
ignoreDefense: 0
|
ignoreDefense: 0
|
||||||
activeRagdoll: 0
|
activeRagdoll: 0
|
||||||
senselessTime: 0
|
senselessTime: 0
|
||||||
resetAttackTrigger: 0
|
resetAttackTrigger: 1
|
||||||
resetTriggerBeforeTime: 0.3
|
resetTriggerBeforeTime: 0.5
|
||||||
unlockRotationTime: 0.7
|
unlockRotationTime: 0.5
|
||||||
lerpPositionTowardsTarget: 1
|
lerpPositionTowardsTarget: 1
|
||||||
maxLerpDistance: 3.5
|
maxLerpDistance: 3.5
|
||||||
positionLerpSpeed: 2
|
positionLerpSpeed: 2
|
||||||
stoppingDistance: 1.2
|
stoppingDistance: 1.2
|
||||||
|
useComboTimingWindow: 1
|
||||||
|
comboWindowStartTime: 0.5
|
||||||
|
comboWindowDuration: 0.2
|
||||||
|
comboWindowTimeScale: 0.3
|
||||||
useAttackTimeScale: 0
|
useAttackTimeScale: 0
|
||||||
maxTargetDistance: 3
|
maxTargetDistance: 3
|
||||||
lowHealthTh: 10
|
lowHealthTh: 10
|
||||||
@@ -747,7 +751,7 @@ MonoBehaviour:
|
|||||||
attackTimeScaleEnd: 0.37
|
attackTimeScaleEnd: 0.37
|
||||||
rotatePlayerTowardsTarget: 1
|
rotatePlayerTowardsTarget: 1
|
||||||
degreeThreshold: 100
|
degreeThreshold: 100
|
||||||
debug: 0
|
debug: 1
|
||||||
--- !u!1101 &-8051095333111886674
|
--- !u!1101 &-8051095333111886674
|
||||||
AnimatorStateTransition:
|
AnimatorStateTransition:
|
||||||
m_ObjectHideFlags: 1
|
m_ObjectHideFlags: 1
|
||||||
@@ -2694,7 +2698,11 @@ MonoBehaviour:
|
|||||||
maxLerpDistance: 3.5
|
maxLerpDistance: 3.5
|
||||||
positionLerpSpeed: 2
|
positionLerpSpeed: 2
|
||||||
stoppingDistance: 1.2
|
stoppingDistance: 1.2
|
||||||
useAttackTimeScale: 0
|
useComboTimingWindow: 1
|
||||||
|
comboWindowStartTime: 0.6
|
||||||
|
comboWindowDuration: 0.2
|
||||||
|
comboWindowTimeScale: 0.3
|
||||||
|
useAttackTimeScale: 1
|
||||||
maxTargetDistance: 3
|
maxTargetDistance: 3
|
||||||
lowHealthTh: 30
|
lowHealthTh: 30
|
||||||
attackTimeScale: 0.1
|
attackTimeScale: 0.1
|
||||||
@@ -2702,7 +2710,7 @@ MonoBehaviour:
|
|||||||
attackTimeScaleEnd: 0.5
|
attackTimeScaleEnd: 0.5
|
||||||
rotatePlayerTowardsTarget: 1
|
rotatePlayerTowardsTarget: 1
|
||||||
degreeThreshold: 100
|
degreeThreshold: 100
|
||||||
debug: 0
|
debug: 1
|
||||||
--- !u!114 &-4885966736990036633
|
--- !u!114 &-4885966736990036633
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 1
|
m_ObjectHideFlags: 1
|
||||||
@@ -5045,7 +5053,11 @@ MonoBehaviour:
|
|||||||
maxLerpDistance: 3.5
|
maxLerpDistance: 3.5
|
||||||
positionLerpSpeed: 2
|
positionLerpSpeed: 2
|
||||||
stoppingDistance: 1.2
|
stoppingDistance: 1.2
|
||||||
useAttackTimeScale: 0
|
useComboTimingWindow: 1
|
||||||
|
comboWindowStartTime: 0.6
|
||||||
|
comboWindowDuration: 0.2
|
||||||
|
comboWindowTimeScale: 0.3
|
||||||
|
useAttackTimeScale: 1
|
||||||
maxTargetDistance: 3
|
maxTargetDistance: 3
|
||||||
lowHealthTh: 10
|
lowHealthTh: 10
|
||||||
attackTimeScale: 0.1
|
attackTimeScale: 0.1
|
||||||
@@ -5053,7 +5065,7 @@ MonoBehaviour:
|
|||||||
attackTimeScaleEnd: 0.3
|
attackTimeScaleEnd: 0.3
|
||||||
rotatePlayerTowardsTarget: 1
|
rotatePlayerTowardsTarget: 1
|
||||||
degreeThreshold: 100
|
degreeThreshold: 100
|
||||||
debug: 0
|
debug: 1
|
||||||
--- !u!114 &-1270803735202051326
|
--- !u!114 &-1270803735202051326
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 1
|
m_ObjectHideFlags: 1
|
||||||
@@ -5541,6 +5553,10 @@ MonoBehaviour:
|
|||||||
maxLerpDistance: 3.5
|
maxLerpDistance: 3.5
|
||||||
positionLerpSpeed: 2
|
positionLerpSpeed: 2
|
||||||
stoppingDistance: 1.2
|
stoppingDistance: 1.2
|
||||||
|
useComboTimingWindow: 0
|
||||||
|
comboWindowStartTime: 0.9
|
||||||
|
comboWindowDuration: 0.5
|
||||||
|
comboWindowTimeScale: 0.3
|
||||||
useAttackTimeScale: 0
|
useAttackTimeScale: 0
|
||||||
maxTargetDistance: 3
|
maxTargetDistance: 3
|
||||||
lowHealthTh: 10
|
lowHealthTh: 10
|
||||||
@@ -26299,6 +26315,10 @@ MonoBehaviour:
|
|||||||
maxLerpDistance: 3.5
|
maxLerpDistance: 3.5
|
||||||
positionLerpSpeed: 2
|
positionLerpSpeed: 2
|
||||||
stoppingDistance: 1.2
|
stoppingDistance: 1.2
|
||||||
|
useComboTimingWindow: 0
|
||||||
|
comboWindowStartTime: 0.9
|
||||||
|
comboWindowDuration: 0.5
|
||||||
|
comboWindowTimeScale: 0.3
|
||||||
useAttackTimeScale: 0
|
useAttackTimeScale: 0
|
||||||
maxTargetDistance: 3
|
maxTargetDistance: 3
|
||||||
lowHealthTh: 35
|
lowHealthTh: 35
|
||||||
@@ -47667,6 +47687,10 @@ MonoBehaviour:
|
|||||||
maxLerpDistance: 3.5
|
maxLerpDistance: 3.5
|
||||||
positionLerpSpeed: 2
|
positionLerpSpeed: 2
|
||||||
stoppingDistance: 1.2
|
stoppingDistance: 1.2
|
||||||
|
useComboTimingWindow: 0
|
||||||
|
comboWindowStartTime: 0.9
|
||||||
|
comboWindowDuration: 0.5
|
||||||
|
comboWindowTimeScale: 0.3
|
||||||
useAttackTimeScale: 0
|
useAttackTimeScale: 0
|
||||||
maxTargetDistance: 3
|
maxTargetDistance: 3
|
||||||
lowHealthTh: 10
|
lowHealthTh: 10
|
||||||
@@ -47818,6 +47842,10 @@ MonoBehaviour:
|
|||||||
maxLerpDistance: 3.5
|
maxLerpDistance: 3.5
|
||||||
positionLerpSpeed: 2
|
positionLerpSpeed: 2
|
||||||
stoppingDistance: 1.2
|
stoppingDistance: 1.2
|
||||||
|
useComboTimingWindow: 0
|
||||||
|
comboWindowStartTime: 0.9
|
||||||
|
comboWindowDuration: 0.5
|
||||||
|
comboWindowTimeScale: 0.3
|
||||||
useAttackTimeScale: 0
|
useAttackTimeScale: 0
|
||||||
maxTargetDistance: 3
|
maxTargetDistance: 3
|
||||||
lowHealthTh: 10
|
lowHealthTh: 10
|
||||||
|
|||||||
@@ -39,10 +39,9 @@ namespace Invector.vMelee
|
|||||||
[Header("Attack Flow")]
|
[Header("Attack Flow")]
|
||||||
[Tooltip("Check true in the last attack of your combo to reset the FSM attack triggers.")]
|
[Tooltip("Check true in the last attack of your combo to reset the FSM attack triggers.")]
|
||||||
public bool resetAttackTrigger;
|
public bool resetAttackTrigger;
|
||||||
[Tooltip("Normalized time point to reset attack triggers if resetAttackTrigger is true.")]
|
[Tooltip("Normalized time point to reset attack triggers. (Used only if Combo Timing Window is disabled)")]
|
||||||
public float resetTriggerBeforeTime = 0.5f;
|
public float resetTriggerBeforeTime = 0.5f;
|
||||||
|
|
||||||
// --- NEW ---: Combo Rotation and Position Lerp Settings
|
|
||||||
[Header("Combo & Movement")]
|
[Header("Combo & Movement")]
|
||||||
[Tooltip("Normalized time to unlock rotation, allowing the player to aim the next attack in a combo. Set to 1 to disable.")]
|
[Tooltip("Normalized time to unlock rotation, allowing the player to aim the next attack in a combo. Set to 1 to disable.")]
|
||||||
[Range(0,1)]
|
[Range(0,1)]
|
||||||
@@ -62,7 +61,22 @@ namespace Invector.vMelee
|
|||||||
[vHideInInspector("lerpPositionTowardsTarget")]
|
[vHideInInspector("lerpPositionTowardsTarget")]
|
||||||
[Tooltip("How close the character should get to the target.")]
|
[Tooltip("How close the character should get to the target.")]
|
||||||
public float stoppingDistance = 1.2f;
|
public float stoppingDistance = 1.2f;
|
||||||
// --- END NEW ---
|
|
||||||
|
// --- MODIFIED: Switched to a real-time duration model ---
|
||||||
|
[Header("Combo Timing Window")]
|
||||||
|
[Tooltip("Enable a special timing window at the end of the attack to chain the next combo hit.")]
|
||||||
|
public bool useComboTimingWindow = false;
|
||||||
|
|
||||||
|
[Tooltip("Normalized time to START the combo window.")]
|
||||||
|
[Range(0, 1)]
|
||||||
|
public float comboWindowStartTime = 0.8f;
|
||||||
|
|
||||||
|
[Tooltip("How long the combo window stays open in REAL-WORLD SECONDS.")]
|
||||||
|
public float comboWindowDuration = 0.5f;
|
||||||
|
|
||||||
|
[Tooltip("The time scale to use during the combo window for a slow-motion effect.")]
|
||||||
|
public float comboWindowTimeScale = 0.1f;
|
||||||
|
// --- END MODIFICATION ---
|
||||||
|
|
||||||
[Header("Slow Motion Settings")]
|
[Header("Slow Motion Settings")]
|
||||||
[Tooltip("Enable slow motion effect during this attack based on conditions below.")]
|
[Tooltip("Enable slow motion effect during this attack based on conditions below.")]
|
||||||
@@ -88,46 +102,39 @@ namespace Invector.vMelee
|
|||||||
private bool m_hasScaledTime;
|
private bool m_hasScaledTime;
|
||||||
private AutoTargetting _autoTargettingInstance;
|
private AutoTargetting _autoTargettingInstance;
|
||||||
|
|
||||||
// --- NEW ---: Private variables for new features
|
|
||||||
private bThirdPersonController _characterController;
|
private bThirdPersonController _characterController;
|
||||||
private bool _isRotationLockedByThis; // Tracks if this specific state has locked rotation
|
private bool _isRotationLockedByThis;
|
||||||
// --- END NEW ---
|
private bool _comboWindowEffectTriggered; // --- NEW ---: Tracks if the slow-mo effect has been fired.
|
||||||
|
private Animator _animator;
|
||||||
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||||
{
|
{
|
||||||
|
if (_animator == null) _animator = animator;
|
||||||
|
|
||||||
mFighter = animator.GetComponent<vIAttackListener>();
|
mFighter = animator.GetComponent<vIAttackListener>();
|
||||||
// --- NEW ---: Get reference to the character controller
|
|
||||||
_characterController = animator.GetComponent<bThirdPersonController>();
|
_characterController = animator.GetComponent<bThirdPersonController>();
|
||||||
// --- END NEW ---
|
|
||||||
|
|
||||||
if (Player.Instance != null)
|
if (Player.Instance != null)
|
||||||
{
|
|
||||||
_autoTargettingInstance = Player.Instance.AutoTarget;
|
_autoTargettingInstance = Player.Instance.AutoTarget;
|
||||||
}
|
|
||||||
|
|
||||||
if (_autoTargettingInstance == null && debug)
|
if (_autoTargettingInstance == null && debug)
|
||||||
{
|
Debug.LogWarning($"({damageType}) AutoTargetting instance not found. Rotation/Target features limited.");
|
||||||
Debug.LogWarning($"({damageType}) AutoTargetting instance not found on {animator.name}. Rotation and target-dependent features will be limited.");
|
|
||||||
}
|
|
||||||
|
|
||||||
isAttacking = true;
|
isAttacking = true;
|
||||||
isActive = false;
|
isActive = false;
|
||||||
m_hasScaledTime = false;
|
m_hasScaledTime = false;
|
||||||
|
_comboWindowEffectTriggered = false; // --- NEW ---: Reset the flag on enter.
|
||||||
// --- NEW ---: Lock character rotation at the beginning of the attack
|
|
||||||
if (_characterController != null)
|
if (_characterController != null)
|
||||||
{
|
{
|
||||||
_characterController.lockRotation = true;
|
_characterController.lockRotation = true;
|
||||||
_isRotationLockedByThis = true;
|
_isRotationLockedByThis = true;
|
||||||
if (debug) Debug.Log($"({damageType}) Rotation locked by state.");
|
|
||||||
}
|
}
|
||||||
// --- END NEW ---
|
|
||||||
|
|
||||||
if (mFighter != null)
|
if (mFighter != null)
|
||||||
mFighter.OnEnableAttack();
|
mFighter.OnEnableAttack();
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
Debug.Log($"({damageType}) OnStateEnter: {animator.name}, Layer: {layerIndex}");
|
Debug.Log($"({damageType}) OnStateEnter. The trigger that started this state has been consumed by the Animator.");
|
||||||
|
|
||||||
if (attackTimeScaleStart < 0f) attackTimeScaleStart = startDamage;
|
if (attackTimeScaleStart < 0f) attackTimeScaleStart = startDamage;
|
||||||
if (attackTimeScaleEnd < 0f) attackTimeScaleEnd = endDamage;
|
if (attackTimeScaleEnd < 0f) attackTimeScaleEnd = endDamage;
|
||||||
@@ -136,208 +143,187 @@ namespace Invector.vMelee
|
|||||||
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||||
{
|
{
|
||||||
if (Player.Instance.ActiveWeaponTrail)
|
if (Player.Instance.ActiveWeaponTrail)
|
||||||
{
|
|
||||||
Player.Instance.ActiveWeaponTrail.m_colorMultiplier = Color.white + Color.red * damageMultiplier;
|
Player.Instance.ActiveWeaponTrail.m_colorMultiplier = Color.white + Color.red * damageMultiplier;
|
||||||
}
|
|
||||||
|
|
||||||
float currentNormalizedTime = stateInfo.normalizedTime % 1;
|
float currentNormalizedTime = stateInfo.normalizedTime % 1;
|
||||||
if (currentNormalizedTime == 0 && stateInfo.normalizedTime > 0.5f) currentNormalizedTime = 1f;
|
if (currentNormalizedTime == 0 && stateInfo.normalizedTime > 0.5f) currentNormalizedTime = 1f;
|
||||||
|
|
||||||
// --- MODIFIED ---: Rotation and Movement logic is now more sophisticated
|
// --- NEW: Centralized combo logic management ---
|
||||||
// Only execute script-based rotation if the controller's rotation is locked
|
ManageComboLogic(currentNormalizedTime);
|
||||||
if (_characterController != null && _characterController.lockRotation)
|
|
||||||
{
|
if (_characterController != null && _characterController.lockRotation)
|
||||||
AttemptRotationTowardsAutoTarget(animator);
|
AttemptRotationTowardsAutoTarget(animator);
|
||||||
}
|
|
||||||
|
|
||||||
// Handle position lerping
|
|
||||||
AttemptPositionLerp(animator);
|
AttemptPositionLerp(animator);
|
||||||
|
|
||||||
// Handle unlocking rotation for combo aiming
|
|
||||||
UpdateRotationLock(currentNormalizedTime);
|
UpdateRotationLock(currentNormalizedTime);
|
||||||
// --- END MODIFIED ---
|
|
||||||
|
|
||||||
if (useAttackTimeScale)
|
if (useAttackTimeScale)
|
||||||
{
|
|
||||||
UpdateSlowMotion(animator, stateInfo, currentNormalizedTime);
|
UpdateSlowMotion(animator, stateInfo, currentNormalizedTime);
|
||||||
}
|
|
||||||
|
|
||||||
if (!isActive && currentNormalizedTime >= startDamage && currentNormalizedTime <= endDamage)
|
if (!isActive && currentNormalizedTime >= startDamage && currentNormalizedTime <= endDamage)
|
||||||
{
|
{
|
||||||
if (debug) Debug.Log($"({damageType}) Enable Damage: normTime={currentNormalizedTime:F2} (Start:{startDamage:F2}, End:{endDamage:F2})");
|
if (debug) Debug.Log($"({damageType}) Enable Damage: normTime={currentNormalizedTime:F2}");
|
||||||
isActive = true;
|
isActive = true;
|
||||||
ActiveDamage(animator, true);
|
ActiveDamage(animator, true);
|
||||||
}
|
}
|
||||||
else if (isActive && currentNormalizedTime > endDamage)
|
else if (isActive && currentNormalizedTime > endDamage)
|
||||||
{
|
{
|
||||||
if (debug) Debug.Log($"({damageType}) Disable Damage: normTime={currentNormalizedTime:F2} > {endDamage:F2}");
|
if (debug) Debug.Log($"({damageType}) Disable Damage: normTime={currentNormalizedTime:F2}");
|
||||||
isActive = false;
|
isActive = false;
|
||||||
ActiveDamage(animator, false);
|
ActiveDamage(animator, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAttacking)
|
if (isAttacking && currentNormalizedTime > endDamage)
|
||||||
{
|
{
|
||||||
if (currentNormalizedTime > endDamage)
|
if (mFighter != null) mFighter.OnDisableAttack();
|
||||||
{
|
isAttacking = false;
|
||||||
if (mFighter != null) mFighter.OnDisableAttack();
|
|
||||||
isAttacking = false;
|
|
||||||
if (debug) Debug.Log($"({damageType}) OnDisableAttack called: normTime={currentNormalizedTime:F2}");
|
|
||||||
}
|
|
||||||
else if (resetAttackTrigger && currentNormalizedTime >= resetTriggerBeforeTime)
|
|
||||||
{
|
|
||||||
if (mFighter != null) mFighter.ResetAttackTriggers();
|
|
||||||
if (debug) Debug.Log($"({damageType}) ResetAttackTriggers called: normTime={currentNormalizedTime:F2}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||||
{
|
{
|
||||||
if (debug) Debug.Log($"({damageType}) OnStateExit: {animator.name}");
|
if (debug) Debug.Log($"({damageType}) OnStateExit.");
|
||||||
|
|
||||||
if (isActive)
|
if (isActive)
|
||||||
{
|
{
|
||||||
isActive = false;
|
isActive = false;
|
||||||
ActiveDamage(animator, false);
|
ActiveDamage(animator, false);
|
||||||
if (debug) Debug.Log($"({damageType}) Damage disabled on StateExit.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAttacking && mFighter != null)
|
if (isAttacking && mFighter != null)
|
||||||
{
|
|
||||||
mFighter.OnDisableAttack();
|
mFighter.OnDisableAttack();
|
||||||
if (debug) Debug.Log($"({damageType}) OnDisableAttack called on StateExit (fallback).");
|
|
||||||
}
|
|
||||||
isAttacking = false;
|
|
||||||
|
|
||||||
|
isAttacking = false;
|
||||||
m_hasScaledTime = false;
|
m_hasScaledTime = false;
|
||||||
|
|
||||||
|
// The TimeController now reliably handles resetting the time scale via its own coroutine.
|
||||||
|
// A manual reset here is no longer necessary and could cause conflicts.
|
||||||
|
/*
|
||||||
if (mFighter != null && resetAttackTrigger)
|
if (mFighter != null && resetAttackTrigger)
|
||||||
{
|
{
|
||||||
mFighter.ResetAttackTriggers();
|
mFighter.ResetAttackTriggers();
|
||||||
if (debug) Debug.Log($"({damageType}) ResetAttackTriggers called on StateExit due to resetAttackTrigger flag.");
|
if (debug) Debug.Log($"({damageType}) Final trigger reset on exit due to 'Reset Attack Trigger' flag.");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// --- NEW ---: Ensure rotation is unlocked upon exiting the state
|
|
||||||
if (_characterController != null && _isRotationLockedByThis)
|
if (_characterController != null && _isRotationLockedByThis)
|
||||||
{
|
{
|
||||||
_characterController.lockRotation = false;
|
_characterController.lockRotation = false;
|
||||||
_isRotationLockedByThis = false;
|
_isRotationLockedByThis = false;
|
||||||
if (debug) Debug.Log($"({damageType}) Rotation unlocked by state on exit.");
|
|
||||||
}
|
}
|
||||||
// --- END NEW ---
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AttemptRotationTowardsAutoTarget(Animator animator)
|
/// <summary>
|
||||||
|
/// Manages the combo logic, including input window and time scale effects.
|
||||||
|
/// </summary>
|
||||||
|
private void ManageComboLogic(float currentNormalizedTime)
|
||||||
{
|
{
|
||||||
if (!rotatePlayerTowardsTarget || _autoTargettingInstance == null || _autoTargettingInstance.CurrentTarget == null)
|
if (!useComboTimingWindow)
|
||||||
{
|
{
|
||||||
|
// Fallback to old logic if new system is disabled for this state
|
||||||
|
if (resetAttackTrigger && currentNormalizedTime >= resetTriggerBeforeTime)
|
||||||
|
{
|
||||||
|
if (mFighter != null)
|
||||||
|
mFighter.ResetAttackTriggers();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_autoTargettingInstance.IsTargetInAngle(animator.transform, _autoTargettingInstance.CurrentTarget, degreeThreshold))
|
// --- FIX 2: Corrected window logic ---
|
||||||
|
bool isInsideWindow = currentNormalizedTime >= comboWindowStartTime;
|
||||||
|
|
||||||
|
if (isInsideWindow)
|
||||||
{
|
{
|
||||||
_autoTargettingInstance.ExecuteRotationTowardsCurrentTarget(Time.deltaTime);
|
// --- We are INSIDE the combo window ---
|
||||||
|
// We STOP resetting the trigger to allow the player's input to register.
|
||||||
|
|
||||||
|
if (!_comboWindowEffectTriggered && TimeController.Instance != null)
|
||||||
|
{
|
||||||
|
_comboWindowEffectTriggered = true;
|
||||||
|
|
||||||
|
TimeController.Instance.SetTimeScaleForRealTimeSec(comboWindowTimeScale, comboWindowDuration, false);
|
||||||
|
|
||||||
|
if (debug) Debug.Log($"({damageType}) COMBO WINDOW OPEN. Accepting input. Animator mode set to UnscaledTime.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// --- We are OUTSIDE the combo window ---
|
||||||
|
// We continuously reset the trigger to consume any premature/late input.
|
||||||
|
if (mFighter != null)
|
||||||
|
mFighter.ResetAttackTriggers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- NEW ---
|
// --- Other methods remain unchanged ---
|
||||||
|
|
||||||
|
private void AttemptRotationTowardsAutoTarget(Animator animator)
|
||||||
|
{
|
||||||
|
if (!rotatePlayerTowardsTarget || _autoTargettingInstance == null || _autoTargettingInstance.CurrentTarget == null) return;
|
||||||
|
if (_autoTargettingInstance.IsTargetInAngle(animator.transform, _autoTargettingInstance.CurrentTarget, degreeThreshold))
|
||||||
|
_autoTargettingInstance.ExecuteRotationTowardsCurrentTarget(Time.deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateRotationLock(float normalizedTime)
|
private void UpdateRotationLock(float normalizedTime)
|
||||||
{
|
{
|
||||||
if (_characterController != null && _isRotationLockedByThis && normalizedTime >= unlockRotationTime)
|
if (_characterController != null && _isRotationLockedByThis && normalizedTime >= unlockRotationTime)
|
||||||
{
|
{
|
||||||
_characterController.lockRotation = false;
|
_characterController.lockRotation = false;
|
||||||
_isRotationLockedByThis = false; // Stop this state from managing the lock
|
_isRotationLockedByThis = false;
|
||||||
if(debug) Debug.Log($"({damageType}) Rotation unlocked for combo aiming at normTime={normalizedTime:F2}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AttemptPositionLerp(Animator animator)
|
private void AttemptPositionLerp(Animator animator)
|
||||||
{
|
{
|
||||||
if (!lerpPositionTowardsTarget || _characterController == null || _autoTargettingInstance == null || _autoTargettingInstance.CurrentTarget == null)
|
if (!lerpPositionTowardsTarget || _characterController == null || _autoTargettingInstance == null || _autoTargettingInstance.CurrentTarget == null) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform playerTransform = _characterController.transform;
|
Transform playerTransform = _characterController.transform;
|
||||||
Transform targetTransform = _autoTargettingInstance.CurrentTarget.transform;
|
Transform targetTransform = _autoTargettingInstance.CurrentTarget.transform;
|
||||||
|
|
||||||
float distance = Vector3.Distance(playerTransform.position, targetTransform.position);
|
float distance = Vector3.Distance(playerTransform.position, targetTransform.position);
|
||||||
|
|
||||||
// Only lerp if within max distance and further than stopping distance
|
|
||||||
if (distance <= maxLerpDistance && distance > stoppingDistance)
|
if (distance <= maxLerpDistance && distance > stoppingDistance)
|
||||||
{
|
{
|
||||||
Vector3 directionToTarget = (targetTransform.position - playerTransform.position).normalized;
|
Vector3 directionToTarget = (targetTransform.position - playerTransform.position).normalized;
|
||||||
directionToTarget.y = 0; // Keep movement on the horizontal plane
|
directionToTarget.y = 0;
|
||||||
|
|
||||||
// The target position is a point in front of the enemy at the stopping distance
|
|
||||||
Vector3 targetPosition = targetTransform.position - directionToTarget * stoppingDistance;
|
Vector3 targetPosition = targetTransform.position - directionToTarget * stoppingDistance;
|
||||||
|
|
||||||
// Use MoveTowards for consistent speed. This adds to root motion rather than fighting it.
|
|
||||||
playerTransform.position = Vector3.MoveTowards(playerTransform.position, targetPosition, positionLerpSpeed * Time.deltaTime);
|
playerTransform.position = Vector3.MoveTowards(playerTransform.position, targetPosition, positionLerpSpeed * Time.deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// --- END NEW ---
|
|
||||||
|
|
||||||
private void UpdateSlowMotion(Animator animator, AnimatorStateInfo stateInfo, float currentNormalizedTime)
|
private void UpdateSlowMotion(Animator animator, AnimatorStateInfo stateInfo, float currentNormalizedTime)
|
||||||
{
|
{
|
||||||
// ... (this method remains unchanged)
|
|
||||||
if (_autoTargettingInstance == null || TimeController.Instance == null) return;
|
if (_autoTargettingInstance == null || TimeController.Instance == null) return;
|
||||||
if (!m_hasScaledTime)
|
if (!m_hasScaledTime && currentNormalizedTime >= attackTimeScaleStart && currentNormalizedTime <= attackTimeScaleEnd)
|
||||||
{
|
{
|
||||||
if (currentNormalizedTime >= attackTimeScaleStart && currentNormalizedTime <= attackTimeScaleEnd)
|
bool triggerSlowMo = false;
|
||||||
|
if (_autoTargettingInstance.CurrentTarget != null)
|
||||||
{
|
{
|
||||||
bool triggerSlowMo = false;
|
float distSqr = (_autoTargettingInstance.CurrentTarget.transform.position - animator.transform.position).sqrMagnitude;
|
||||||
if (_autoTargettingInstance.CurrentTarget != null)
|
if (distSqr <= maxTargetDistance * maxTargetDistance)
|
||||||
{
|
{
|
||||||
float distSqr = (_autoTargettingInstance.CurrentTarget.transform.position - animator.transform.position).sqrMagnitude;
|
triggerSlowMo = true;
|
||||||
bool targetNear = distSqr <= maxTargetDistance * maxTargetDistance;
|
|
||||||
if (targetNear)
|
|
||||||
{
|
|
||||||
float currentTargetHealth = _autoTargettingInstance.GetCurrentTargetHealth();
|
|
||||||
bool targetHealthLow = currentTargetHealth > 0f && currentTargetHealth < lowHealthTh;
|
|
||||||
if (targetHealthLow)
|
|
||||||
{
|
|
||||||
triggerSlowMo = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
triggerSlowMo = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (triggerSlowMo)
|
}
|
||||||
|
if (triggerSlowMo)
|
||||||
|
{
|
||||||
|
float slowMoEffectDuration = (attackTimeScaleEnd - currentNormalizedTime) * stateInfo.length;
|
||||||
|
if (slowMoEffectDuration > 0.01f)
|
||||||
{
|
{
|
||||||
float slowMoEffectDuration = (attackTimeScaleEnd - currentNormalizedTime) * stateInfo.length;
|
TimeController.Instance.SetTimeScaleForSec(attackTimeScale, slowMoEffectDuration);
|
||||||
if (slowMoEffectDuration > 0.01f)
|
|
||||||
{
|
|
||||||
TimeController.Instance.SetTimeScaleForSec(attackTimeScale, slowMoEffectDuration);
|
|
||||||
if (debug) Debug.Log($"({damageType}) Slow-mo ACTIVATED. Target: {_autoTargettingInstance.CurrentTarget?.name ?? "N/A"}. Duration: {slowMoEffectDuration:F2}s. NormTime: {currentNormalizedTime:F2}");
|
|
||||||
}
|
|
||||||
else if (debug) Debug.Log($"({damageType}) Slow-mo trigger met, but calculated duration too short ({slowMoEffectDuration:F2}s). NormTime: {currentNormalizedTime:F2}");
|
|
||||||
m_hasScaledTime = true;
|
m_hasScaledTime = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (currentNormalizedTime > attackTimeScaleEnd && m_hasScaledTime)
|
else if (m_hasScaledTime && currentNormalizedTime > attackTimeScaleEnd)
|
||||||
{
|
{
|
||||||
m_hasScaledTime = false;
|
m_hasScaledTime = false;
|
||||||
if (debug) Debug.Log($"({damageType}) Slow-mo window ended (normTime={currentNormalizedTime:F2}). m_hasScaledTime reset.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActiveDamage(Animator animator, bool value)
|
void ActiveDamage(Animator animator, bool value)
|
||||||
{
|
{
|
||||||
// ... (this method remains unchanged)
|
|
||||||
var meleeManager = animator.GetComponent<vMeleeManager>();
|
var meleeManager = animator.GetComponent<vMeleeManager>();
|
||||||
if (meleeManager)
|
if (meleeManager)
|
||||||
{
|
meleeManager.SetActiveAttack(bodyParts, meleeAttackType, value, damageMultiplier, recoilID, reactionID, ignoreDefense, activeRagdoll, senselessTime, damageType);
|
||||||
meleeManager.SetActiveAttack(bodyParts, meleeAttackType, value, damageMultiplier, recoilID, reactionID,
|
|
||||||
ignoreDefense, activeRagdoll, senselessTime, damageType);
|
|
||||||
}
|
|
||||||
else if(debug)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"({damageType}) vMeleeManager not found on {animator.name}. Cannot activate/deactivate damage.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace Beyond
|
|||||||
|
|
||||||
public UnityEvent<float> m_OnTimeScaleChanged;
|
public UnityEvent<float> m_OnTimeScaleChanged;
|
||||||
|
|
||||||
private float m_startingFixedDelta;
|
private float m_startingFixedDelta = 0.02f;
|
||||||
private float m_currentTimeScale = 1f;
|
private float m_currentTimeScale = 1f;
|
||||||
|
|
||||||
public void SetTimeScale(float s)
|
public void SetTimeScale(float s)
|
||||||
@@ -32,7 +32,7 @@ namespace Beyond
|
|||||||
StopAllCoroutines();
|
StopAllCoroutines();
|
||||||
SetTimeScale(1f);
|
SetTimeScale(1f);
|
||||||
}
|
}
|
||||||
|
[Sirenix.OdinInspector.Button]
|
||||||
public void SetTimeScaleForRealTimeSec(float s, float seconds, bool forceStop = false)
|
public void SetTimeScaleForRealTimeSec(float s, float seconds, bool forceStop = false)
|
||||||
{
|
{
|
||||||
if (forceStop)
|
if (forceStop)
|
||||||
@@ -58,19 +58,8 @@ namespace Beyond
|
|||||||
protected override void Awake()
|
protected override void Awake()
|
||||||
{
|
{
|
||||||
base.Awake();
|
base.Awake();
|
||||||
m_startingFixedDelta = Time.fixedDeltaTime;
|
//m_startingFixedDelta = Time.fixedDeltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start is called before the first frame update
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is called once per frame
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,12 @@
|
|||||||
--- !u!5 &1
|
--- !u!5 &1
|
||||||
TimeManager:
|
TimeManager:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
Fixed Timestep: 0.02
|
serializedVersion: 2
|
||||||
|
Fixed Timestep:
|
||||||
|
m_Count: 2822399
|
||||||
|
m_Rate:
|
||||||
|
m_Denominator: 1
|
||||||
|
m_Numerator: 141120000
|
||||||
Maximum Allowed Timestep: 0.33333334
|
Maximum Allowed Timestep: 0.33333334
|
||||||
m_TimeScale: 1
|
m_TimeScale: 1
|
||||||
Maximum Particle Timestep: 0.03
|
Maximum Particle Timestep: 0.03
|
||||||
|
|||||||
Reference in New Issue
Block a user