using System; using System.Collections; using BlueWater.Audios; using BlueWater.Interfaces; using BlueWater.Utility; using UnityEngine; using Random = UnityEngine.Random; namespace BlueWater.Enemies.Bosses.TitanSlime.Skills { public class JumpSlam : BaseSkill { private JumpSlamData _jumpSlamData; private TitanSlime _titanSlime; private AnimationController _animationController; private TitanSlimeState _titanSlimeState; private Rigidbody _userRigidbody; private Collider _targetCollider; private float _colliderRadius; protected override void BasicSetting() { if (!_titanSlime) { _titanSlime = SkillUser.GetComponent(); _animationController = _titanSlime.AnimationController; _titanSlimeState = _titanSlime.TitanSlimeState; _userRigidbody = _titanSlime.Rigidbody; _targetCollider = _titanSlime.Target; _colliderRadius = _titanSlime.CharacterCollider.radius * _titanSlime.transform.localScale.x; } _jumpSlamData = (JumpSlamData)SkillData; HitColliders = new Collider[1]; base.BasicSetting(); } public override void ActivateSkill(params Action[] actions) { Utils.StartUniqueCoroutine(this, ref SkillCoroutineInstance, SkillCoroutine(actions)); } // 유니티 애니메이션 버전 // private IEnumerator SkillCoroutine(params Action[] actions) // { // EnableSkill = false; // _titanSlime.StopMove(); // _animationController.SetAnimationParameter("isJumpSlam", true); // _animationController.SetAnimationParameter("idleIndex", 0); // // var animationStarted = false; // yield return StartCoroutine(_animationController.WaitForAnimationToRun("JumpSlam", // success => animationStarted = success)); // // if (!animationStarted) // { // EndSkill(0, actions[0]); // yield break; // } // // _userRigidbody.useGravity = false; // _animationController.SetCurrentAnimationSpeed(_titanSlimeState.AnimationLength); // // var startPosition = SkillUser.transform.position; // var targetPosition = _targetCollider.transform.position; // var targetDistance = Vector3.Distance(targetPosition, startPosition); // var endPosition = targetDistance <= _titanSlimeState.ViewRange // ? CalculateRandomPosition(targetPosition, 1f) // : CalculateRandomPosition(startPosition, 3f); // // transform.position = endPosition + Vector3.up * _colliderRadius; // transform.localScale = Vector3.one * (_colliderRadius * 2f); // // if (_titanSlimeState.HasRabbit) // { // AudioManager.Instance.PlaySfx("JumpSlam"); // } // // var startIndicatorTime = 1 - SkillData.CastingTime; // var fill = 1 / startIndicatorTime; // var isShowingIndicator = false; // while (_animationController.IsComparingCurrentAnimation("JumpSlam") && // _animationController.GetCurrentAnimationNormalizedTime() <= 1f) // { // var normalizedTime = _animationController.GetCurrentAnimationNormalizedTime(); // if (IsUsingIndicator && Indicator) // { // if (startIndicatorTime <= normalizedTime) // { // if (!isShowingIndicator) // { // ShowIndicator(); // isShowingIndicator = true; // } // var fillValue = Indicator.material.GetFloat(_fillHash) + Time.deltaTime * fill; // Indicator.material.SetFloat(_fillHash, fillValue); // } // } // SkillUser.transform.position = Vector3.Lerp(startPosition, endPosition, normalizedTime); // // yield return null; // } // // HideIndicator(); // SkillUser.transform.position = endPosition; // var randomCooldown = Random.Range(_titanSlimeState.RandomCooldown.x, _titanSlimeState.RandomCooldown.y); // // DoAttack(endPosition); // EndSkill(randomCooldown, actions[0]); // } // // private void EndSkill(float cooldown, Action action) // { // Utils.EndUniqueCoroutine(this, ref SkillCoroutineInstance); // // var randomIdleIndex = Random.Range(1, 3); // _animationController.ResetAnimationSpeed(); // _animationController.SetAnimationParameter("idleIndex", randomIdleIndex); // _animationController.SetAnimationParameter("isJumpSlam", false); // _userRigidbody.useGravity = true; // action?.Invoke(); // // Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(cooldown, EndCooldown)); // } private IEnumerator SkillCoroutine(params Action[] actions) { EnableSkill = false; _titanSlime.StopMove(); _animationController.SetAnimationParameter("isJumpSlam", true); var animationStarted = false; yield return StartCoroutine(_animationController.WaitForAnimationToRun("JumpSlam", success => animationStarted = success)); if (!animationStarted || !SkillUser || !_userRigidbody || !_targetCollider) { EndSkill(0, actions[0]); yield break; } _userRigidbody.useGravity = false; _animationController.SetCurrentAnimationSpeed(_titanSlimeState.AnimationLength); var startPosition = SkillUser.transform.position; var targetPosition = _targetCollider.transform.position; var targetDistance = Vector3.Distance(targetPosition, startPosition); var endPosition = targetDistance <= _titanSlimeState.ViewRange ? CalculateRandomPosition(targetPosition, 1f) : CalculateRandomPosition(startPosition, 3f); transform.position = endPosition + Vector3.up * _colliderRadius; transform.localScale = Vector3.one * (_colliderRadius * 2f); if (_titanSlimeState.HasRabbit) { AudioManager.Instance.PlaySfx("JumpSlam"); } var startIndicatorTime = 1 - SkillData.CastingTime; var fill = 1 / startIndicatorTime; var isShowingIndicator = false; while (_animationController.IsComparingCurrentAnimation("JumpSlam") && _animationController.GetCurrentAnimationNormalizedTime() <= 1f) { var normalizedTime = _animationController.GetCurrentAnimationNormalizedTime(); if (IsUsingIndicator && Indicator) { if (startIndicatorTime <= normalizedTime) { if (!isShowingIndicator) { ShowIndicator(); isShowingIndicator = true; } } var fillValue = Indicator.material.GetFloat(_fillHash) + Time.deltaTime * fill; Indicator.material.SetFloat(_fillHash, fillValue); } var horizontalPosition = Vector3.Lerp(startPosition, endPosition, normalizedTime); var heightFactor = Mathf.Sin(Mathf.PI * normalizedTime); SkillUser.transform.position = new Vector3(horizontalPosition.x, startPosition.y + heightFactor * _jumpSlamData.JumpHeight, horizontalPosition.z); yield return null; } HideIndicator(); var randomCooldown = Random.Range(_titanSlimeState.RandomCooldown.x, _titanSlimeState.RandomCooldown.y); if (!SkillUser) { EndSkill(randomCooldown, actions[0]); yield break; } SkillUser.transform.position = endPosition; if (_titanSlimeState.HasRabbit) { AudioManager.Instance.PlaySfx("JumpSlamDown"); VisualFeedbackManager.Instance.CameraShake(CombatCameraManager.Instance.BaseCombatCamera, _titanSlimeState.JumpCameraShakingPower, _titanSlimeState.JumpCameraShakingDuration); } DoAttack(endPosition); EndSkill(randomCooldown, actions[0]); } private void EndSkill(float cooldown, Action action) { Utils.EndUniqueCoroutine(this, ref SkillCoroutineInstance); var randomIdleIndex = Random.Range(1, 3); _animationController.ResetAnimationSpeed(); _animationController.SetAnimationParameter("isJumpSlam", false); _animationController.SetAnimationParameter("idleIndex", randomIdleIndex); if (_userRigidbody) { _userRigidbody.useGravity = true; } action?.Invoke(); Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(cooldown, EndCooldown)); } private Vector3 CalculateRandomPosition(Vector3 startPosition, float range, int iterationCount = 100) { for (var i = 0; i < iterationCount; i++) { var randomPosition = startPosition + Random.insideUnitSphere * range; randomPosition.y = startPosition.y; if (!_titanSlime.IsPositionMovable(startPosition, randomPosition)) continue; return randomPosition; } Debug.Log($"{SkillUser.name}이 랜덤으로 이동할 위치를 찾지 못했습니다."); return startPosition; } private void DoAttack(Vector3 attackPosition) { var hitCount = Physics.OverlapSphereNonAlloc(attackPosition, _colliderRadius, HitColliders, _jumpSlamData.TargetLayer); for (var i = 0; i < hitCount; i++) { var hitCollider = HitColliders[i]; var targetVector = hitCollider.transform.position - attackPosition; targetVector.y = 0f; var targetDirection = targetVector.normalized; var iDamageable = hitCollider.transform.GetComponentInParent(); if (iDamageable == null || !iDamageable.CanDamage()) continue; iDamageable.TakeDamage(_jumpSlamData.Damage); var iSlowable = hitCollider.transform.GetComponentInParent(); iSlowable?.SlowMoveSpeed(_jumpSlamData.SlowDuration, _jumpSlamData.SlowCoefficient); var iPhysicMovable = hitCollider.GetComponentInParent(); iPhysicMovable?.AddForce(targetDirection * _jumpSlamData.PushPower, ForceMode.Impulse); } } } }