CapersProject/Assets/02.Scripts/Skill/Enemy/Boss/Rhinoceros/SkyFallSmash.cs

230 lines
8.9 KiB
C#

using System;
using System.Collections;
using BlueWater.Audios;
using BlueWater.Interfaces;
using BlueWater.Utility;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace BlueWater.Enemies.Bosses.Rhinoceros.Skills
{
public class SkyFallSmash : BaseSkill
{
[Title("추가 옵션")]
[SerializeField]
private DecalProjector _stunIndicator;
private SkyFallSmashData _skyFallSmashData;
private Rhinoceros _rhinoceros;
private AnimationController _animationController;
private Collider _targetCollider;
private static readonly int _colorHash = Shader.PropertyToID("_Color");
protected override void BasicSetting()
{
if (!_rhinoceros)
{
_rhinoceros = SkillUser.GetComponent<Rhinoceros>();
_animationController = _rhinoceros.AnimationController;
_targetCollider = _rhinoceros.Target;
}
_skyFallSmashData = (SkyFallSmashData)SkillData;
HitColliders = new Collider[4];
if (IsUsingIndicator)
{
if (Indicator)
{
Indicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
Indicator.material = new Material(Indicator.material);
Indicator.material.SetFloat(_fillHash, 0f);
}
if (_stunIndicator)
{
_stunIndicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
_stunIndicator.material = new Material(_stunIndicator.material);
_stunIndicator.material.SetColor(_colorHash, _skyFallSmashData.StunColor);
_stunIndicator.material.SetFloat(_fillHash, 0f);
}
}
}
protected override void ShowIndicator()
{
if (IsUsingIndicator)
{
if (Indicator)
{
Indicator.material.SetFloat(_fillHash, 0);
Indicator.enabled = true;
}
if (_stunIndicator)
{
_stunIndicator.material.SetFloat(_fillHash, 0);
_stunIndicator.enabled = true;
}
}
}
protected override void HideIndicator()
{
if (IsUsingIndicator)
{
if (Indicator)
{
Indicator.enabled = false;
Indicator.material.SetFloat(_fillHash, 0);
}
if (_stunIndicator)
{
_stunIndicator.enabled = false;
_stunIndicator.material.SetFloat(_fillHash, 0);
}
}
}
public override void ActivateSkill(params Action[] actions)
{
Utils.StartUniqueCoroutine(this, ref SkillCoroutineInstance, SkillCoroutine(actions));
}
private IEnumerator SkillCoroutine(params Action[] actions)
{
EnableSkill = false;
_rhinoceros.StopMove();
_animationController.SetAnimationParameter("skillIndex", (int)RhinocerosSkill.SkyFallSmash);
var animationStarted = false;
yield return StartCoroutine(_animationController.WaitForAnimationToRun("SkyFallJump",
success => animationStarted = success));
if (!animationStarted)
{
EndSkill(0, actions[0]);
yield break;
}
_rhinoceros.Rigidbody.isKinematic = true;
while (_animationController.IsComparingCurrentAnimation("SkyFallJump")
&& _animationController.GetCurrentAnimationNormalizedTime() <= 1f)
{
yield return null;
}
var elapsedTime = 0f;
var startPosition = SkillUser.transform.position;
var endPosition = startPosition + Vector3.up * _skyFallSmashData.JumpHeight;
while (elapsedTime <= _skyFallSmashData.JumpTime)
{
elapsedTime += Time.deltaTime;
SkillUser.transform.position = Vector3.Lerp(startPosition, endPosition, elapsedTime / _skyFallSmashData.JumpTime);
yield return null;
}
SkillUser.transform.position = endPosition;
yield return new WaitForSeconds(_skyFallSmashData.WaitTime);
var targetPosition = _targetCollider.transform.position;
transform.position = targetPosition + Vector3.up * SkillData.Radius;
transform.localScale = Vector3.one * (SkillData.Radius * 2f);
_stunIndicator.transform.localScale = Vector3.one * (_skyFallSmashData.StunRadiusCoefficient * 2f);
startPosition = targetPosition + Vector3.up * _skyFallSmashData.JumpHeight;
endPosition = targetPosition;
ShowIndicator();
elapsedTime = 0f;
var fill = 1 / SkillData.CastingTime;
while (elapsedTime <= SkillData.CastingTime)
{
elapsedTime += Time.deltaTime;
if (IsUsingIndicator)
{
var fillValue = Indicator.material.GetFloat(_fillHash) + Time.deltaTime * fill;
if (Indicator)
{
Indicator.material.SetFloat(_fillHash, fillValue);
}
if (_stunIndicator)
{
_stunIndicator.material.SetFloat(_fillHash, fillValue);
}
}
yield return null;
}
elapsedTime = 0f;
while (elapsedTime <= _skyFallSmashData.FallTime)
{
elapsedTime += Time.deltaTime;
SkillUser.transform.position = Vector3.Lerp(startPosition, endPosition, elapsedTime / _skyFallSmashData.FallTime);
yield return null;
}
HideIndicator();
SkillUser.transform.position = endPosition;
_rhinoceros.Rigidbody.isKinematic = false;
AudioManager.Instance.PlaySfx("SkyFallSmash");
VisualFeedbackManager.Instance.CameraShake(CombatCameraManager.Instance.BaseCombatCamera,
_skyFallSmashData.CameraShakingPower, _skyFallSmashData.CameraShakingDuration);
var centerPosition = transform.position;
var hitCount = Physics.OverlapSphereNonAlloc(centerPosition, SkillData.Radius, HitColliders, _skyFallSmashData.TargetLayer, QueryTriggerInteraction.Collide);
var stunRange = SkillData.Radius * _skyFallSmashData.StunRadiusCoefficient;
var stunHitCount = Physics.OverlapSphereNonAlloc(centerPosition, stunRange, HitColliders, _skyFallSmashData.TargetLayer, QueryTriggerInteraction.Collide);
for (var i = 0; i < hitCount; i++)
{
var iDamageable = HitColliders[i].GetComponentInParent<IDamageable>();
if (iDamageable == null || !iDamageable.CanDamage()) continue;
iDamageable.TakeDamage(SkillData.Damage);
}
for (var i = 0; i < stunHitCount; i++)
{
var hitCollider = HitColliders[i];
var iStunnable = hitCollider.transform.GetComponentInParent<IStunnable>();
if (iStunnable != null && iStunnable.CanStun())
{
iStunnable.Stun(_skyFallSmashData.StunDuration);
var iPhysicMovable = hitCollider.GetComponentInParent<IPhysicMovable>();
var hitVector = hitCollider.transform.position - transform.position;
hitVector.y = 0f;
var hitDirection = hitVector.normalized;
hitDirection = hitDirection == Vector3.zero ? Vector3.right : hitDirection;
var hitDistance = hitVector.magnitude;
var powerCoefficient = stunRange - hitDistance;
var addForcePower = powerCoefficient / stunRange * _skyFallSmashData.PushPowerCoefficient;
iPhysicMovable.SetPush(hitDirection, addForcePower);
}
}
EndSkill(SkillData.Cooldown, actions[0]);
}
private void EndSkill(float cooldown, Action action)
{
Utils.EndUniqueCoroutine(this, ref SkillCoroutineInstance);
_animationController.SetAnimationParameter("skillIndex", (int)RhinocerosSkill.None);
action?.Invoke();
Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(cooldown, EndCooldown));
}
}
}