OldBlueWater/BlueWater/Assets/02.Scripts/NewSkill/Rhinoceros/MeteorSwing.cs

164 lines
6.7 KiB
C#

using System;
using System.Collections;
using BlueWaterProject;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering.Universal;
// ReSharper disable once CheckNamespace
namespace RhinocerosSkill
{
public class MeteorSwing : BaseSkill
{
[Title("추가 옵션")]
[SerializeField] private bool isDrawingGizmo = true;
[SerializeField] private float angle = 180f;
[Title("발사체 옵션")]
[SerializeField] private GameObject projectilePrefab;
[SerializeField] private int projectileNumber = 5;
[SerializeField] private float projectileDamage = 10f;
[SerializeField] private float projectileAngle = 90f;
[SerializeField] private float projectileSpeed = 500f;
private Transform particleInstantiateLocation;
private Collider[] hitColliders;
private bool isUsingSkill;
private void OnDrawGizmos()
{
if (!isDrawingGizmo || !isUsingSkill) return;
Gizmos.color = Color.red;
var skillPosition = transform.position;
Gizmos.DrawWireSphere(skillPosition, SkillData.Range);
if (SkillInputData != null && SkillInputData.TargetCollider != null)
{
var skillPlayerPosition = SkillInputData.PlayerRb.position;
var forward = transform.forward;
var leftBoundary = Quaternion.Euler(0, -angle / 2, 0) * forward;
var rightBoundary = Quaternion.Euler(0, angle / 2, 0) * forward;
Gizmos.color = Color.yellow;
Gizmos.DrawLine(skillPlayerPosition, skillPlayerPosition + leftBoundary * SkillData.Range);
Gizmos.DrawLine(skillPlayerPosition, skillPlayerPosition + rightBoundary * SkillData.Range);
}
}
protected override void BasicSetting()
{
if (isUsingIndicator && indicator)
{
indicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
indicator.material = new Material(indicator.material);
indicator.material.SetFloat(FillHash, 0f);
indicator.material.SetFloat("Angle", angle);
}
hitColliders = new Collider[5];
}
public override void ActivateSkill(params Action[] actions)
{
enableSkill = false;
StartCoroutine(SkillCoroutine(actions));
}
private IEnumerator SkillCoroutine(params Action[] actions)
{
var iAnimationStateController = SkillInputData.IAnimationStateController;
iAnimationStateController.SetAnimationParameter(RhinocerosAnimationParameter.SKILL_INDEX, 2);
var animationStarted = false;
yield return StartCoroutine(iAnimationStateController.WaitForAnimationToRun(RhinocerosAnimationName.METEOR_SWING,
success => animationStarted = success));
if (!animationStarted)
{
EndSkill(0, actions[0]);
yield break;
}
isUsingSkill = true;
var startPosition = SkillInputData.Transform.position;
var targetPosition = SkillInputData.TargetCollider.transform.position;
var targetToVector = targetPosition - startPosition;
targetToVector.y = 0f;
var targetToDirection = targetToVector.normalized;
transform.position = startPosition;
var yAngle = Mathf.Atan2(targetToDirection.x, targetToDirection.z) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, yAngle, 0);
transform.localScale = Vector3.one * (SkillData.Range * 2f);
actions[1].Invoke();
ShowIndicator();
var elapsedTime = 0f;
var fill = 1 / SkillData.CastingTime;
while (elapsedTime < SkillData.CastingTime)
{
elapsedTime += Time.deltaTime;
if (isUsingIndicator && indicator)
{
var fillValue = indicator.material.GetFloat(FillHash) + Time.deltaTime * fill;
indicator.material.SetFloat(FillHash, fillValue);
}
yield return null;
}
var hitCount = Physics.OverlapSphereNonAlloc(transform.position, SkillData.Range, hitColliders, SkillInputData.TargetLayer);
for (var i = 0; i < hitCount; i++)
{
var hitToVector = hitColliders[i].transform.position - transform.position;
hitToVector.y = 0f;
var attackDirection = hitToVector.normalized;
var angleToTarget = Vector3.Angle(attackDirection, targetToDirection);
if (angleToTarget <= angle * 0.5f)
{
var iDamageable = hitColliders[i].GetComponent<IDamageable>();
iDamageable?.TakeDamage(SkillData.Damage);
var combatStatus = hitColliders[i].transform.GetComponent<CombatStatus>();
if (combatStatus != null)
{
combatStatus.Stun(0.1f);
combatStatus.GetComponent<Rigidbody>().AddForce(attackDirection * 15f, ForceMode.Impulse);
}
}
}
HideIndicator();
var startAngle = yAngle - projectileAngle * 0.5f;
var angleStep = projectileAngle / (projectileNumber - 1);
particleInstantiateLocation ??= FindAnyObjectByType<RhinocerosBossMapController>().ParticleInstantiateLocation;
for (var i = 0; i < projectileNumber; i++)
{
var currentAngle = startAngle + angleStep * i;
var rotation = Quaternion.Euler(0, currentAngle, 0);
var projectile = Instantiate(projectilePrefab, transform.position + Vector3.up, rotation, particleInstantiateLocation);
var particleWeapon = projectile.GetComponent<ParticleWeapon>();
particleWeapon.SetPower(projectileDamage);
particleWeapon.Rb.AddForce(particleWeapon.transform.forward * projectileSpeed);
}
EndSkill(SkillData.Cooldown, actions[0]);
}
private void EndSkill(float cooldown, Action action)
{
isUsingSkill = false;
SkillInputData.IAnimationStateController.SetAnimationParameter(RhinocerosAnimationParameter.SKILL_INDEX, -1);
StartCoroutine(Utils.CoolDown(cooldown, () => enableSkill = true));
action?.Invoke();
}
}
}