CapersProject/Assets/02.Scripts/Skill/Enemy/Boss/TitanSlime/JumpSlam.cs
2024-06-04 03:26:03 +09:00

165 lines
7.0 KiB
C#

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<TitanSlime>();
_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<IDamageable>();
if (iDamageable == null || !iDamageable.CanDamage()) continue;
iDamageable.TakeDamage(_jumpSlamData.Damage);
var iSlowable = hitCollider.transform.GetComponentInParent<ISlowable>();
iSlowable?.SlowMoveSpeed(_jumpSlamData.SlowDuration, _jumpSlamData.SlowCoefficient);
var iPhysicMovable = hitCollider.GetComponentInParent<IPhysicMovable>();
iPhysicMovable?.AddForce(targetDirection * _jumpSlamData.PushPower, ForceMode.Impulse);
}
}
}
}