269 lines
12 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
} |