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 CapsuleCollider _userCollider; private Collider _targetCollider; private LayerMask _targetLayer; private float _colliderRadius; protected override void BasicSetting() { if (!_titanSlime) { _titanSlime = SkillUser.GetComponent(); _animationController = _titanSlime.AnimationController; _titanSlimeState = _titanSlime.TitanSlimeState; _userRigidbody = _titanSlime.Rigidbody; _userCollider = _titanSlime.CharacterCollider; _targetCollider = _titanSlime.Target; _targetLayer = _titanSlime.TargetLayer; _colliderRadius = _userCollider.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); 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); ShowIndicator(); if (_titanSlimeState.HasRabbit) { AudioManager.Instance.PlaySfx("JumpSlam"); } var fill = 1 / _titanSlimeState.AnimationLength; while (_animationController.IsComparingCurrentAnimation("JumpSlam") && _animationController.GetCurrentAnimationNormalizedTime() <= 1f) { if (IsUsingIndicator && Indicator) { var fillValue = Indicator.material.GetFloat(_fillHash) + Time.deltaTime * fill; Indicator.material.SetFloat(_fillHash, fillValue); } var normalizedTime = _animationController.GetCurrentAnimationNormalizedTime(); 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(); 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); _animationController.ResetAnimationSpeed(); _animationController.SetAnimationParameter("isJumpSlam", false); _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) { if (_titanSlimeState.HasRabbit) { VisualFeedbackManager.Instance.CameraShake(CombatCameraManager.Instance.BaseCombatCamera, _titanSlimeState.JumpCameraShakingPower, _titanSlimeState.JumpCameraShakingDuration); } var hitCount = Physics.OverlapSphereNonAlloc(attackPosition, _colliderRadius, HitColliders, _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); } } } }