using System; using System.Collections; using BlueWaterProject; using Sirenix.OdinInspector; using UnityEngine; // ReSharper disable once CheckNamespace namespace RhinocerosSkill { public class BoolCharge : BaseSkill { [Title("추가 옵션")] [SerializeField] private bool isDrawingGizmo = true; [SerializeField] private float width = 3f; [SerializeField] private float rushSpeed = 15f; [SerializeField] private float rushOffset = 3f; private RaycastHit[] hits; private bool isUsingSkill; private void OnDrawGizmos() { if (!isDrawingGizmo || !isUsingSkill) return; if (SkillInputData.PlayerCollider is CapsuleCollider capsuleCollider) { var capsuleRadius = capsuleCollider.radius; var point1 = SkillInputData.PlayerRb.position + Vector3.up * capsuleRadius; Gizmos.color = Color.red; Gizmos.DrawWireSphere(point1, capsuleRadius); } } protected override void BasicSetting() { base.BasicSetting(); hits = new RaycastHit[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, 0); var animationStarted = false; yield return StartCoroutine(iAnimationStateController.WaitForAnimationToRun(RhinocerosAnimationName.BULL_CHARGE, success => animationStarted = success)); if (!animationStarted) { EndSkill(0, actions[0]); yield break; } iAnimationStateController.ResetAnimationSpeed(); isUsingSkill = true; var isAttacked = false; var startPosition = SkillInputData.PlayerRb.position; var vectorToTarget = SkillInputData.TargetCollider.transform.position - startPosition; vectorToTarget.y = 0f; var targetDirection = vectorToTarget.normalized; var targetDistance = vectorToTarget.magnitude + rushOffset; //var endPosition = startPosition + targetDirection * targetDistance; transform.position = startPosition + Vector3.up * 3f; transform.localScale = new Vector3(width, 6f, targetDistance * 2); var angle = Mathf.Atan2(targetDirection.x, targetDirection.z) * Mathf.Rad2Deg; transform.rotation = Quaternion.Euler(0, angle, 0); 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; } HideIndicator(); var timeToReachTarget = targetDistance / rushSpeed; var capsuleCollider = (CapsuleCollider)SkillInputData.PlayerCollider; var capsuleRadius = capsuleCollider.radius; elapsedTime = 0f; while (elapsedTime <= timeToReachTarget) { elapsedTime += Time.deltaTime; SkillInputData.PlayerRb.velocity = targetDirection * rushSpeed; var playerPosition = SkillInputData.PlayerRb.position; var point1 = playerPosition + Vector3.up * capsuleRadius; var point2 = playerPosition + Vector3.up * (capsuleCollider.height - capsuleRadius); var hitCount = Physics.CapsuleCastNonAlloc(point1, point2, capsuleRadius, targetDirection, hits, 0f, SkillInputData.TargetLayer, QueryTriggerInteraction.Ignore); for (var i = 0; i < hitCount; i++) { if (!isAttacked) { var iDamageable = hits[i].transform.GetComponent(); iDamageable?.TakeDamage(SkillData.Damage); isAttacked = true; var combatStatus = hits[i].transform.GetComponent(); if (combatStatus != null) { var targetToVector = hits[i].transform.position - SkillInputData.Transform.position; targetToVector.y = 0f; var hitDirection = targetToVector.normalized; var cross = Vector3.Cross(hitDirection, transform.forward); var addForceDirection = cross.y >= 0f ? Quaternion.Euler(0, -90, 0) * transform.forward : Quaternion.Euler(0, 90, 0) * transform.forward; combatStatus.Stun(0.05f); combatStatus.GetComponent().AddForce(addForceDirection * 30f, ForceMode.Impulse); } } } yield return null; } SkillInputData.PlayerRb.velocity = Vector3.zero; 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(); } } }