CapersProject/Assets/02.Scripts/Skill/Enemy/Boss/TitanSlime/JumpSlam.cs

269 lines
12 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 Collider _targetCollider;
private float _colliderRadius;
protected override void BasicSetting()
{
if (!_titanSlime)
{
_titanSlime = SkillUser.GetComponent<TitanSlime>();
_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 = 1000)
{
var nearestNodeInfo = AstarPath.active.GetNearest(startPosition);
if (nearestNodeInfo.node is not { Walkable: true })
{
startPosition = nearestNodeInfo.position;
}
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;
}
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<IDamageable>();
if (iDamageable == null || !iDamageable.CanDamage()) continue;
iDamageable.TakeDamage(_jumpSlamData.Damage);
var iSlowable = hitCollider.transform.GetComponentInParent<ISlowable>();
iSlowable?.TrySlowMoveSpeed(_jumpSlamData.SlowDuration, _jumpSlamData.SlowCoefficient);
var iPhysicMovable = hitCollider.GetComponentInParent<IPhysicMovable>();
iPhysicMovable?.SetPush(targetDirection, _jumpSlamData.PushPower);
}
}
}
}