CapersProject/Assets/02.Scripts/Skill/Enemy/Boss/Rhinoceros/MeteorSwing.cs
Nam Tae Gun 51798c3346 #16 SandMole(모래 두더지) 보스 추가 중
+ AiMovement 클래스 재생성 및 초기화 방식 변경
+ AnimationController 클래스 초기화 방식 변경
+ MapManager, MapController 로직 수정
+ BaseBoss 프리팹 수정
+ SandMole 보스에 맞게 맵 추가
+ 임시 SandMole, GhostBarrel 이미지 추가
+ 기존 GroundGreen, GroundRed 스프라이트 정사각형으로 변경, 수정에 따라 BaseMapController Ground, Wall 수정
+ 코뿔소 맵 투명화 Props 추가

Closes #12
2024-06-14 01:46:37 +09:00

166 lines
7.1 KiB
C#

using System;
using System.Collections;
using BlueWater.Interfaces;
using BlueWater.Maps;
using BlueWater.Utility;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace BlueWater.Enemies.Bosses.Rhinoceros.Skills
{
public class MeteorSwing : BaseSkill
{
[Title("추가 옵션")]
[SerializeField]
private bool _isDrawingGizmo = true;
private MeteorSwingData _meteorSwingData;
private Rhinoceros _rhinoceros;
private AnimationController _animationController;
private Collider _targetCollider;
private LayerMask _targetLayer;
private Transform _particleInstantiateLocation;
private static readonly int _angleHash = Shader.PropertyToID("_Angle");
private void OnDrawGizmos()
{
if (!_isDrawingGizmo || !IsUsingSkill) return;
var startPosition = SkillUser.transform.position;
var targetDirection = transform.forward;
var leftBoundary = Quaternion.Euler(0, -_meteorSwingData.AttackAngle / 2, 0) * targetDirection;
var rightBoundary = Quaternion.Euler(0, _meteorSwingData.AttackAngle / 2, 0) * targetDirection;
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(startPosition, SkillData.Radius);
Gizmos.color = Color.yellow;
Gizmos.DrawLine(startPosition, startPosition + leftBoundary * SkillData.Radius);
Gizmos.DrawLine(startPosition, startPosition + rightBoundary * SkillData.Radius);
}
protected override void BasicSetting()
{
if (!_rhinoceros)
{
_rhinoceros = SkillUser.GetComponent<Rhinoceros>();
_animationController = _rhinoceros.AnimationController;
_targetCollider = _rhinoceros.Target;
_targetLayer = _rhinoceros.TargetLayer;
_particleInstantiateLocation = _rhinoceros.BossMapController.ParticleInstantiateLocation;
}
_meteorSwingData = (MeteorSwingData)SkillData;
HitColliders = new Collider[4];
if (IsUsingIndicator && Indicator)
{
Indicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
Indicator.material = new Material(Indicator.material);
Indicator.material.SetFloat(_fillHash, 0f);
Indicator.material.SetFloat(_angleHash, _meteorSwingData.AttackAngle);
}
}
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.MeteorSwing);
var animationStarted = false;
yield return StartCoroutine(_animationController.WaitForAnimationToRun("MeteorSwing",
success => animationStarted = success));
if (!animationStarted)
{
EndSkill(0, actions[0]);
yield break;
}
IsUsingSkill = true;
var startPosition = SkillUser.transform.position;
var targetPosition = _targetCollider.transform.position;
var targetVector = targetPosition - startPosition;
targetVector.y = 0f;
var targetDirection = targetVector.normalized;
transform.position = startPosition + Vector3.up * SkillData.Radius;
var yAngle = Mathf.Atan2(targetDirection.x, targetDirection.z) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, yAngle, 0);
transform.localScale = Vector3.one * (SkillData.Radius * 2f);
_rhinoceros.CurrentDirection = targetDirection;
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.Radius, HitColliders, _targetLayer, QueryTriggerInteraction.Collide);
for (var i = 0; i < hitCount; i++)
{
var hitCollider = HitColliders[i];
var hitVector = hitCollider.transform.position - SkillUser.transform.position;
hitVector.y = 0f;
var attackDirection = hitVector.normalized;
var targetAngle = Vector3.Angle(attackDirection, targetDirection);
if (targetAngle > _meteorSwingData.AttackAngle * 0.5f) continue;
var iDamageable = hitCollider.GetComponentInParent<IDamageable>();
if (iDamageable == null || !iDamageable.CanDamage()) continue;
iDamageable.TakeDamage(SkillData.Damage);
var iStunnable = hitCollider.transform.GetComponentInParent<IStunnable>();
iStunnable?.Stun(_meteorSwingData.StunDuration);
var iPhysicMovable = hitCollider.GetComponentInParent<IPhysicMovable>();
iPhysicMovable?.AddForce(attackDirection * _meteorSwingData.PushPower, ForceMode.Impulse);
}
HideIndicator();
var startAngle = yAngle - _meteorSwingData.ProjectileAngle * 0.5f;
var angleStep = _meteorSwingData.ProjectileAngle / (_meteorSwingData.ProjectileCount - 1);
for (var i = 0; i < _meteorSwingData.ProjectileCount; i++)
{
var currentAngle = startAngle + angleStep * i;
var rotation = Quaternion.Euler(0, currentAngle, 0);
var projectile = Instantiate(_meteorSwingData.ProjectilePrefab,
startPosition + Vector3.up, rotation, _particleInstantiateLocation).GetComponent<ParticleWeapon>();
projectile.Initialize(_meteorSwingData.ProjectileDamage, _targetLayer);
projectile.AddForce(projectile.transform.forward * _meteorSwingData.ProjectileSpeed, ForceMode.Impulse);
}
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();
IsUsingSkill = false;
Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(cooldown, EndCooldown));
}
}
}