improvements to magic attacks, full arena logic, improvements to NPCs fresnel rendering for targetting

This commit is contained in:
2025-05-23 09:54:57 +02:00
parent 2705b6c4cb
commit abc5ef0332
6 changed files with 673 additions and 237 deletions

View File

@@ -6,14 +6,14 @@ using Invector;
using Invector.vCharacterController;
using Invector.vCharacterController.vActions;
using Sirenix.OdinInspector;
// using UnityEditor; // Best to remove if not strictly needed for runtime
// using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.VFX;
// using static Invector.vObjectDamage; // Not used directly, consider removing
// using static Invector.vObjectDamage;
using DG.Tweening;
using Invector.vCharacterController.AI.FSMBehaviour;
using Beyond; // For Player, GameStateManager, AutoTargetting (if Player.Instance.AutoTarget is of this type)
using Beyond;
namespace Beyond
{
@@ -51,8 +51,8 @@ namespace Beyond
private Coroutine lastPushRoutine = null;
private ParticleSystem flame;
private BoxCollider flameDamager;
private bLockOn lockOn; // Retained for fallback aiming or non-combat interactions if needed
private const float fireballAimerThreshold = -1.0f; // Used for fallback aiming if no auto-target
private bLockOn lockOn;
private const float fireballAimerThreshold = -1.0f;
private const float fireballAimerHeightAdjuster = 0.1f;
private const float fireballDamagerDuration = 0.3f;
private const float fireballTargetYPositionOffset = 0.75f;
@@ -64,21 +64,12 @@ namespace Beyond
private bool canPlayNoFaithClip = true;
private bool canPlayCantDoClip = true;
// NEW: AutoTargetting fields
private AutoTargetting _autoTargettingInstance;
// REMOVED: public bool enableAutoTargetIntegration = true;
// REMOVED: public float maxTurnTowardDistance = 10f;
// REMOVED: public float rotationSpeed = 500f;
// REMOVED: public float degreeThreshold = 100f; (already removed in previous step)
[BoxGroup("Auto targetting")]
[Tooltip("Enable to use AutoTargetting for player rotation and spell aiming.")]
public bool enableAutoTargetIntegration = true;
[BoxGroup("Auto targetting")]
[Tooltip("Max distance for player to turn towards an auto-target during spell casting.")]
public float maxTurnTowardDistance = 10f;
[BoxGroup("Auto targetting")]
[Tooltip("Rotation speed when turning towards an auto-target.")]
public float rotationSpeed = 500f;
[BoxGroup("Auto targetting")]
[Tooltip("Angle threshold within which the player will rotate towards an auto-target.")]
public float degreeThreshold = 100f;
public UnityAction<Collider> onHitFireball;
@@ -86,20 +77,19 @@ namespace Beyond
{
tpInput = GetComponent<bThirdPersonInput>();
// NEW: Initialize AutoTargetting instance
if (Player.Instance != null)
{
_autoTargettingInstance = Player.Instance.AutoTarget; // Assuming Player.Instance has an AutoTarget property of type AutoTargetting
if (_autoTargettingInstance == null && enableAutoTargetIntegration)
_autoTargettingInstance = Player.Instance.AutoTarget;
if (_autoTargettingInstance == null) // Simplified warning
{
Debug.LogWarning("MagicAttacks: AutoTargetting component not found on Player.Instance.AutoTarget, but enableAutoTargetIntegration is true. Targeting features will be limited.");
Debug.LogWarning("MagicAttacks: AutoTargetting component not found on Player.Instance.AutoTarget. Auto-targeting features will not be available.");
}
}
else
{
Debug.LogError("MagicAttacks: Player.Instance is null in Awake. Cannot get AutoTargetting component.");
}
lockOn = GetComponent<bLockOn>(); // Keep for potential fallback
lockOn = GetComponent<bLockOn>();
EffectDesc mpush = m_effects[(int)EffectType.MAGIC_PUSH];
EffectDesc flameThrowe = m_effects[(int)EffectType.FLAME_THROWER];
@@ -165,8 +155,8 @@ namespace Beyond
[Button]
private void OnSilentPeek()
{
StopCoroutine(SilentPeekCoroutine());
StartCoroutine(SilentPeekCoroutine());
StopCoroutine(nameof(SilentPeekCoroutine));
StartCoroutine(nameof(SilentPeekCoroutine));
}
private IEnumerator SilentPeekCoroutine()
@@ -202,13 +192,12 @@ namespace Beyond
private IEnumerator MagicPushCoroutine()
{
EffectDesc mpush = m_effects[(int)EffectType.MAGIC_PUSH];
// MODIFIED: Use TurnTowardTargetCoroutine for potential rotation during wind-up
yield return TurnTowardTargetCoroutine(mpush.startTime);
mpush.effectObject.SetActive(false);
mpush.effectObject.SetActive(true);
yield return new WaitForSeconds(mpush.delay);
Debug.Log("Bum!"); // Consider replacing with actual effect logic
yield return new WaitForSeconds(mpush.endTime); // This is endTime after delay, might be confusing.
Debug.Log("Bum!");
yield return new WaitForSeconds(mpush.endTime);
mpush.effectObject.SetActive(false);
yield return null;
}
@@ -221,13 +210,12 @@ namespace Beyond
private IEnumerator FlameThrowerhCoroutine()
{
EffectDesc flameThrowe = m_effects[(int)EffectType.FLAME_THROWER];
// MODIFIED: TurnTowardTargetCoroutine will handle rotation based on AutoTargetting
yield return TurnTowardTargetCoroutine(flameThrowe.startTime);
flameDamager.enabled = true;
flame.Play();
yield return new WaitForSeconds(flameThrowe.endTime); // Duration of flame
yield return new WaitForSeconds(flameThrowe.endTime);
flame.Stop();
yield return new WaitForSeconds(flameThrowe.delay); // Cooldown/after-effect
yield return new WaitForSeconds(flameThrowe.delay);
flameDamager.enabled = false;
yield return null;
}
@@ -241,11 +229,10 @@ namespace Beyond
private IEnumerator ScanCoroutine()
{
EffectDesc scan = m_effects[(int)EffectType.SCAN];
// Scan might not need rotation, but if it had a wind-up animation, TurnTowardTargetCoroutine could be used.
yield return new WaitForSeconds(scan.startTime);
float time = scan.startTime - scan.delay; // This calculation seems off if delay is for after effect. Assuming startTime is actual start.
float time = scan.startTime - scan.delay;
float maxRange = 50f;
float speed = maxRange / (scan.endTime - scan.startTime); // scan.endTime is duration here
float speed = maxRange / (scan.endTime - scan.startTime);
int mask = 1 << LayerMask.NameToLayer("Triggers") | 1 << LayerMask.NameToLayer("HiddenObject");
if (scan.effectObject)
{
@@ -258,11 +245,11 @@ namespace Beyond
while (waveEffectTimer < waveEffectDuration)
{
Shader.SetGlobalFloat("_WaveTime", speed * waveEffectTimer); // Use timer relative to effect start
Shader.SetGlobalFloat("_WaveTime", speed * waveEffectTimer);
waveEffectTimer += Time.deltaTime;
yield return null;
}
Shader.SetGlobalFloat("_WaveTime", 0f); // Reset shader global
Shader.SetGlobalFloat("_WaveTime", 0f);
var colliders = Physics.OverlapSphere(transform.position, maxRange, mask);
foreach (var c in colliders)
{
@@ -270,7 +257,7 @@ namespace Beyond
if (h != null)
h.OnScanned();
}
if (scan.effectObject) scan.effectObject.SetActive(false); // Deactivate after use
if (scan.effectObject) scan.effectObject.SetActive(false);
yield return null;
}
@@ -279,12 +266,11 @@ namespace Beyond
StartCoroutine(FireballCoroutine());
}
// MODIFIED: Centralized coroutine for turning towards target during spell animations
private IEnumerator TurnTowardTargetCoroutine(float maxDuration)
{
if (!enableAutoTargetIntegration || _autoTargettingInstance == null)
// *** MODIFIED: Condition relies only on _autoTargettingInstance and its CurrentTarget ***
if (_autoTargettingInstance == null || _autoTargettingInstance.CurrentTarget == null)
{
// If auto-targeting is off or unavailable, just wait for the duration without rotation.
if (maxDuration > 0) yield return new WaitForSeconds(maxDuration);
yield break;
}
@@ -292,31 +278,34 @@ namespace Beyond
float timeElapsed = 0;
while (timeElapsed < maxDuration)
{
// Re-check CurrentTarget in loop in case it becomes null (e.g., target dies mid-turn)
if (_autoTargettingInstance.CurrentTarget != null)
{
vFSMBehaviourController currentTarget = _autoTargettingInstance.CurrentTarget;
Transform playerTransform = transform; // Character's transform
Transform playerTransform = transform;
float distSqr = (currentTarget.transform.position - playerTransform.position).sqrMagnitude;
// Check distance using MagicAttacks.maxTurnTowardDistance
if (distSqr <= maxTurnTowardDistance * maxTurnTowardDistance)
if (distSqr <= _autoTargettingInstance.maxTargetingDistance * _autoTargettingInstance.maxTargetingDistance)
{
// Check angle using MagicAttacks.degreeThreshold and AutoTargetting's utility
if (_autoTargettingInstance.IsTargetInAngle(playerTransform, currentTarget, degreeThreshold))
if (_autoTargettingInstance.IsTargetInAngle(playerTransform, currentTarget, _autoTargettingInstance.targetingAngleThreshold))
{
Vector3 directionToTarget = currentTarget.transform.position - playerTransform.position;
directionToTarget.y = 0f; // Horizontal rotation only
directionToTarget.y = 0f;
if (directionToTarget.sqrMagnitude > 0.0001f) // Ensure there's a direction
if (directionToTarget.sqrMagnitude > 0.0001f)
{
Quaternion targetRotation = Quaternion.LookRotation(directionToTarget.normalized);
// Use MagicAttacks.rotationSpeed for the rotation
playerTransform.rotation = Quaternion.RotateTowards(playerTransform.rotation, targetRotation, Time.deltaTime * rotationSpeed);
// *** MODIFIED: Use playerRotationSpeed from AutoTargetting ***
playerTransform.rotation = Quaternion.RotateTowards(playerTransform.rotation, targetRotation, Time.deltaTime * _autoTargettingInstance.playerRotationSpeed);
}
}
}
}
else // Target became null during the loop
{
yield break; // Exit if no target
}
timeElapsed += Time.deltaTime;
yield return null;
}
@@ -324,11 +313,10 @@ namespace Beyond
private IEnumerator FireballCoroutine()
{
EffectDesc fireball = m_effects[(int)EffectType.FIREBALL];
// MODIFIED: Use new TurnTowardTargetCoroutine
yield return TurnTowardTargetCoroutine(fireball.startTime);
EffectDesc fireballDesc = m_effects[(int)EffectType.FIREBALL]; // Renamed to avoid conflict
yield return TurnTowardTargetCoroutine(fireballDesc.startTime);
var fireballClone = Instantiate(fireball.effectObject, fireball.effectObject.transform.position, fireball.effectObject.transform.rotation);
var fireballClone = Instantiate(fireballDesc.effectObject, fireballDesc.effectObject.transform.position, fireballDesc.effectObject.transform.rotation);
fireballClone.SetActive(true);
RFX4_PhysicsMotion fireballMotionController = fireballClone.GetComponentInChildren<RFX4_PhysicsMotion>();
if (fireballMotionController != null)
@@ -341,66 +329,81 @@ namespace Beyond
fireballDamageComponent.onHit.AddListener(onHitFireball);
}
// MODIFIED: Use new AimFireball method
AimFireball(fireballClone);
Destroy(fireballClone, 10f); // Self-destruct after time
Destroy(fireballClone, 10f);
yield return null;
}
private void EnableBrieflyFireballDamager(object sender, RFX4_PhysicsMotion.RFX4_CollisionInfo e)
{
RFX4_PhysicsMotion rFX4_PhysicsMotion = (RFX4_PhysicsMotion)sender;
CapsuleCollider collider = rFX4_PhysicsMotion.GetComponentInChildren<CapsuleCollider>(); // Assuming damager is a CapsuleCollider
CapsuleCollider collider = rFX4_PhysicsMotion.GetComponentInChildren<CapsuleCollider>();
if(collider != null) StartCoroutine(EnableBrieflyFireballDamagerCoroutine(collider));
}
// NEW: Refactored fireball aiming logic
private void AimFireball(GameObject fireballClone)
{
Vector3 aimDirection = transform.forward; // Default aim is player's forward
Vector3 aimDirection = transform.forward;
if (enableAutoTargetIntegration && _autoTargettingInstance != null && _autoTargettingInstance.CurrentTarget != null)
// *** MODIFIED: Condition relies only on _autoTargettingInstance and its CurrentTarget ***
if (_autoTargettingInstance != null && _autoTargettingInstance.CurrentTarget != null)
{
vFSMBehaviourController autoTarget = _autoTargettingInstance.CurrentTarget;
Vector3 targetPosition = autoTarget.transform.position;
targetPosition.y += fireballTargetYPositionOffset; // Adjust height for aiming
aimDirection = (targetPosition - fireballClone.transform.position).normalized;
Transform playerTransform = transform;
float distSqrToAutoTarget = (autoTarget.transform.position - playerTransform.position).sqrMagnitude;
if (distSqrToAutoTarget <= _autoTargettingInstance.maxTargetingDistance * _autoTargettingInstance.maxTargetingDistance &&
_autoTargettingInstance.IsTargetInAngle(playerTransform, autoTarget, _autoTargettingInstance.targetingAngleThreshold))
{
Vector3 targetPosition = autoTarget.transform.position;
targetPosition.y += fireballTargetYPositionOffset;
aimDirection = (targetPosition - fireballClone.transform.position).normalized;
}
}
else if (lockOn != null && lockOn.isLockingOn && lockOn.currentTarget != null) // Fallback to bLockOn target
if (aimDirection == transform.forward && lockOn != null && lockOn.isLockingOn && lockOn.currentTarget != null)
{
Vector3 targetPosition = lockOn.currentTarget.position;
targetPosition.y += fireballTargetYPositionOffset;
aimDirection = (targetPosition - fireballClone.transform.position).normalized;
}
else if (lockOn != null) // Fallback to nearest enemy in front (from bLockOn)
else if (aimDirection == transform.forward && lockOn != null)
{
List<Transform> closeEnemies = lockOn.GetNearbyTargets();
List<Transform> closeEnemies = lockOn.GetNearbyTargets();
if (closeEnemies.Count > 0)
{
foreach (var enemyTransform in closeEnemies) // Find first suitable enemy in front
Transform bestFallbackTarget = null;
float minAngle = float.MaxValue;
foreach (var enemyTransform in closeEnemies)
{
Vector3 targetPosition = enemyTransform.position;
targetPosition.y += fireballTargetYPositionOffset;
Vector3 directionToEnemy = (targetPosition - fireballClone.transform.position).normalized;
// Check if enemy is generally in front of the player (fireball origin)
if (Vector3.Dot(transform.forward, directionToEnemy) > fireballAimerThreshold)
Vector3 directionToEnemyFromPlayer = (enemyTransform.position - transform.position).normalized;
float angleToEnemy = Vector3.Angle(transform.forward, directionToEnemyFromPlayer);
if (Vector3.Dot(transform.forward, directionToEnemyFromPlayer) > fireballAimerThreshold)
{
aimDirection = directionToEnemy;
break;
if (angleToEnemy < minAngle) {
minAngle = angleToEnemy;
bestFallbackTarget = enemyTransform;
}
}
}
if (bestFallbackTarget != null)
{
Vector3 targetPosition = bestFallbackTarget.position;
targetPosition.y += fireballTargetYPositionOffset;
aimDirection = (targetPosition - fireballClone.transform.position).normalized;
}
}
}
// Apply calculated aim direction to the fireball, adding vertical adjustment
Vector3 finalAimDirection = new Vector3(aimDirection.x, aimDirection.y + fireballAimerHeightAdjuster, aimDirection.z);
if (finalAimDirection.sqrMagnitude > 0.001f)
{
fireballClone.transform.rotation = Quaternion.LookRotation(finalAimDirection.normalized);
}
// If aimDirection is zero (shouldn't happen with defaults), it will use its instantiated rotation.
}
@@ -413,26 +416,24 @@ namespace Beyond
public void Shield()
{
StopCoroutine(ShieldCoroutine()); // Ensure only one shield coroutine runs
StartCoroutine(ShieldCoroutine());
StopCoroutine(nameof(ShieldCoroutine));
StartCoroutine(nameof(ShieldCoroutine));
}
private IEnumerator ShieldCoroutine()
{
shieldAnimationIsActive = true;
// Shield typically doesn't need offensive targeting/rotation.
// If there was a wind-up animation where player *should* face an enemy, TurnTowardTargetCoroutine could be used.
yield return new WaitForSeconds(shield.startTime);
shieldEffectIsActive = true;
shieldEffectController.InitializeEffect();
shield.effectObject.SetActive(true);
shieldCollisionController.shieldCollider.enabled = true;
yield return new WaitForSeconds(shield.endTime); // Duration shield is active
yield return new WaitForSeconds(shield.endTime);
shieldEffectController.DisableEffect();
yield return new WaitForSeconds(shield.delay / 2f); // Fade out time part 1
yield return new WaitForSeconds(shield.delay / 2f);
shieldEffectIsActive = false;
shieldCollisionController.shieldCollider.enabled = false;
yield return new WaitForSeconds(shield.delay / 2f); // Fade out time part 2
yield return new WaitForSeconds(shield.delay / 2f);
shield.effectObject.SetActive(false);
shieldAnimationIsActive = false;
}
@@ -450,21 +451,21 @@ namespace Beyond
[Tooltip("Input to trigger the custom animation")]
public GenericInput actionInput = new GenericInput("L", "L", "L");
[Tooltip("Name of the animation clip")]
public string animationClip; // This will be set by selectedEffect.animClipName
public string animationClip;
[Tooltip("Where in the end of the animation will trigger the event OnEndAnimation")]
public float animationEnd = 0.8f;
public UnityEvent OnPlayAnimation; // Consider if this is still needed or how it fits
public UnityEvent OnPlayAnimation;
public UnityEvent OnEndAnimation;
public bool isPlaying; // Tracks if the spell animation is currently playing
protected bool triggerOnce; // For OnEndAnimation event
protected vThirdPersonInput tpInput; // Renamed from tpInput to avoid conflict with Invector's tpInput if any confusion
public bool isPlaying;
protected bool triggerOnce;
protected bThirdPersonInput tpInput;
internal bool shieldEffectIsActive;
private bool shieldAnimationIsActive;
private int equipAreaSelectedIndex = 0;
protected virtual void LateUpdate() // LateUpdate for animation state checks is common
protected virtual void LateUpdate()
{
TriggerSpellAnimation();
AnimationBehaviour();
@@ -481,7 +482,7 @@ namespace Beyond
public void TryToPlaySpellAnimation()
{
selectedEffect = GetCurrentlySelectedPower(); // Ensure current selected effect is fetched
selectedEffect = GetCurrentlySelectedPower();
if (selectedEffect == shield && shieldAnimationIsActive)
{
@@ -489,7 +490,7 @@ namespace Beyond
return;
}
if (Player.Instance == null) // Safeguard
if (Player.Instance == null)
{
Debug.LogError("Player.Instance is null. Cannot cast spell.");
return;
@@ -498,37 +499,33 @@ namespace Beyond
if (selectedEffect != null && currentSpellFaithCost <= Player.Instance.GetCurrentFaithValue())
{
Player.Instance.UpdateFaithCurrentValue(-currentSpellFaithCost);
animationClip = selectedEffect.animClipName; // Set animation clip for AnimationBehaviour
animationClip = selectedEffect.animClipName;
// NEW: Perform initial snap rotation if auto-targeting is enabled
if (enableAutoTargetIntegration)
// *** MODIFIED: Snap look if AutoTargetting is available and has a target ***
if (_autoTargettingInstance != null && _autoTargettingInstance.CurrentTarget != null)
{
SnapLookTowardsAutoTarget();
SnapLookTowardsAutoTarget();
}
// else // OLD logic for turning - can be removed or kept as fallback
// {
// TryToTurnTowordsEnemy();
// }
if (tpInput != null && tpInput.cc != null && tpInput.cc.animator != null)
{
tpInput.cc.animator.CrossFadeInFixedTime(animationClip, 0.1f);
OnPlayAnimation.Invoke(); // Invoke OnPlay event
triggerOnce = true; // Allow OnEndAnimation to be called
OnPlayAnimation.Invoke();
triggerOnce = true;
}
else
{
Debug.LogError("Cannot play spell animation: tpInput or its components are null.");
return; // Don't proceed to call delegate if animation components are missing
return;
}
selectedEffect.del?.Invoke(); // Call the spell's primary action delegate
selectedEffect.del?.Invoke();
if (powersArea.equipSlots[equipAreaSelectedIndex].item.destroyAfterUse)
{
if (selectedEffect == silentPeek)
{
// Special handling for Silent Peek item destruction (likely in its controller)
// Special handling
}
else
{
@@ -536,39 +533,37 @@ namespace Beyond
}
}
}
else if (selectedEffect != null) // Not enough faith
else if (selectedEffect != null)
{
TryToPlayNoEnoughFaithClip();
}
// If selectedEffect is null, nothing happens (no spell selected/valid)
}
// NEW: Method for an immediate snap-look towards the auto-target
private void SnapLookTowardsAutoTarget()
{
// *** MODIFIED: Condition relies only on _autoTargettingInstance and its CurrentTarget ***
// This check is somewhat redundant due to call site, but good for safety if called elsewhere.
if (_autoTargettingInstance == null || _autoTargettingInstance.CurrentTarget == null)
{
return; // No auto-target system or no current target
return;
}
vFSMBehaviourController currentTarget = _autoTargettingInstance.CurrentTarget;
Transform playerTransform = transform;
// Check distance condition from MagicAttacks settings
float distSqr = (currentTarget.transform.position - playerTransform.position).sqrMagnitude;
if (distSqr > maxTurnTowardDistance * maxTurnTowardDistance)
if (distSqr > _autoTargettingInstance.maxTargetingDistance * _autoTargettingInstance.maxTargetingDistance)
{
return; // Target is too far for this specific snap-look interaction
return;
}
// Check angle condition from MagicAttacks settings
if (!_autoTargettingInstance.IsTargetInAngle(playerTransform, currentTarget, degreeThreshold))
if (!_autoTargettingInstance.IsTargetInAngle(playerTransform, currentTarget, _autoTargettingInstance.targetingAngleThreshold))
{
return; // Target is not within the desired cone for snap-look
return;
}
Vector3 directionToTarget = currentTarget.transform.position - playerTransform.position;
directionToTarget.y = 0f; // Horizontal rotation only
directionToTarget.y = 0f;
if (directionToTarget.sqrMagnitude > 0.0001f)
{
@@ -580,26 +575,26 @@ namespace Beyond
{
if (!canPlayCantDoClip) return;
canPlayCantDoClip = false;
DOVirtual.DelayedCall(1f, () => canPlayCantDoClip = true); // Reset flag
DOVirtual.DelayedCall(1f, () => canPlayCantDoClip = true);
var text = "Spell is already active"; // Example message
var text = "Spell is already active";
if (bItemCollectionDisplay.Instance != null)
bItemCollectionDisplay.Instance.FadeText(text, 4, 0.25f);
if (Player.Instance != null)
Player.Instance.PlayICantDoThatYet(); // Assuming this method exists on Player
Player.Instance.PlayICantDoThatYet();
}
private void TryToPlayNoEnoughFaithClip()
{
if (!canPlayNoFaithClip) return;
canPlayNoFaithClip = false;
DOVirtual.DelayedCall(1.5f, () => canPlayNoFaithClip = true); // Reset flag
DOVirtual.DelayedCall(1.5f, () => canPlayNoFaithClip = true);
var text = "Not enough Faith";
if (bItemCollectionDisplay.Instance != null)
bItemCollectionDisplay.Instance.FadeText(text, 4, 0.25f);
if (Player.Instance != null)
Player.Instance.PlayNoFaithClip(); // Assuming this method exists on Player
Player.Instance.PlayNoFaithClip();
}
public EffectDesc GetCurrentlySelectedPower()
@@ -613,7 +608,7 @@ namespace Beyond
}
bItem selectedSpellItem = powersArea.equipSlots[equipAreaSelectedIndex].item;
currentSelectedSpellName = selectedSpellItem.name; // Store for display or debugging
currentSelectedSpellName = selectedSpellItem.name;
currentSpellFaithCost = selectedSpellItem.GetItemAttribute(bItemAttributes.Faith).value;
return m_effects.Find(effect => effect.name == selectedSpellItem.name || effect.secondaryName == selectedSpellItem.name);
@@ -622,30 +617,9 @@ namespace Beyond
public void SelectPowerBasedOnArea(int newIndex)
{
equipAreaSelectedIndex = newIndex;
selectedEffect = GetCurrentlySelectedPower(); // Update current effect based on selection
selectedEffect = GetCurrentlySelectedPower();
}
// OLD rotation methods - can be removed or commented out if new system is preferred
/*
private void LerpRotation()
{
// ... original LerpRotation code using GetNearestEnemy ...
}
private bool IsEnemyInAngleRange(vFSMBehaviourController ai)
{
// ... original IsEnemyInAngleRange code ...
}
private vFSMBehaviourController GetNearestEnemy(ref float minDist)
{
// ... original GetNearestEnemy code ...
}
private void TryToTurnTowordsEnemy() // Replaced by SnapLookTowardsAutoTarget
{
// ... original TryToTurnTowordsEnemy code ...
}
*/
protected virtual void AnimationBehaviour()
{
if (tpInput == null || tpInput.cc == null || tpInput.cc.animator == null || string.IsNullOrEmpty(animationClip))
@@ -654,7 +628,6 @@ namespace Beyond
return;
}
// isPlaying should reflect if the *specific spell animation* is active.
isPlaying = tpInput.cc.animator.GetCurrentAnimatorStateInfo(spellLayerIndex).IsName(animationClip) ||
tpInput.cc.animator.GetNextAnimatorStateInfo(spellLayerIndex).IsName(animationClip);
@@ -673,13 +646,9 @@ namespace Beyond
}
else
{
// If not playing the specific animation clip, ensure triggerOnce is reset
// This handles cases where animation might be interrupted before reaching animationEnd
if (triggerOnce)
{
triggerOnce = false;
// Optionally, invoke OnEndAnimation if it should always fire on exiting the state,
// but current logic only fires it if normalizedTime >= animationEnd.
}
}
}