using System; using System.Collections; using System.Collections.Generic; using System.Linq; using BlueWater.Audios; using BlueWater.Interfaces; using BlueWater.Maps; using BlueWater.Players; using BlueWater.Utility; using UnityEngine; using Random = UnityEngine.Random; namespace BlueWater.Enemies.Bosses.SandMole.Skills { public class GateOfSpikes : BaseSkill { private GateOfSpikesData _gateOfSpikesData; private SpineController _spineController; private Collider _userCollider; private Collider _targetCollider; private ICurrentDirection _currentDirection; private Transform _particleInstantiateLocation; private List _spikes; protected override void BasicSetting() { _gateOfSpikesData = (GateOfSpikesData)SkillData; _spineController = SkillUser.GetComponent(); _userCollider = SkillUser.GetComponent(); _targetCollider = SkillUser.GetComponent().Target; _currentDirection = SkillUser.GetComponent(); _particleInstantiateLocation = MapManager.Instance.SandMoleMapController.ParticleInstanceLocation; _spikes = new List(_gateOfSpikesData.SpikeCount); base.BasicSetting(); } public override void ActivateSkill(params Action[] actions) { Utils.StartUniqueCoroutine(this, ref SkillCoroutineInstance, SkillCoroutine(actions)); } private IEnumerator SkillCoroutine(params Action[] actions) { EnableSkill = false; _spineController.SetSkin(SandMoleSkin.Normal.ToString()); var roarTrack = _spineController.PlayAnimation(SandMoleAnimation.Roar.ToString(), false); if (roarTrack == null) { EndSkill(0, actions[0]); yield break; } yield return new WaitUntil(() => roarTrack.IsComplete); _spineController.SetSkin(SandMoleSkin.Normal.ToString()); _spineController.PlayAnimation(SandMoleAnimation.Idle.ToString(), true); IsUsingSkill = true; AudioManager.Instance.PlaySfx("GateOfSpikes"); var startPosition = SkillUser.transform.position; var targetCenterPosition = _targetCollider.transform.position; startPosition.y = targetCenterPosition.y; var targetVector = targetCenterPosition - startPosition; var targetDirection = targetVector.normalized; _currentDirection.CurrentDirection = targetDirection; var spikeSpawnPosition = _userCollider.bounds.center; var validAttackPositions = new List(); while (validAttackPositions.Count < _gateOfSpikesData.SpikeCount) { var randomCircle = Random.insideUnitCircle * _gateOfSpikesData.Radius; var randomPosition = targetCenterPosition + new Vector3(randomCircle.x, 0, randomCircle.y); if (!IsPositionValid(randomPosition)) continue; validAttackPositions.Add(randomPosition); _spikes.Add(randomPosition); var spike = Instantiate(_gateOfSpikesData.SpikePrefab, spikeSpawnPosition, Quaternion.identity, _particleInstantiateLocation).GetComponent(); spike.GetComponentInChildren().Initialize(_gateOfSpikesData.Damage, _gateOfSpikesData.TargetLayer, false); spike.Initialize(randomPosition); } EndSkill(SkillData.Cooldown, actions[0]); } private bool IsPositionValid(Vector3 position) { var isGrounded = Physics.Raycast(position + Vector3.up, Vector3.down, 5f, _gateOfSpikesData.GroundLayer); return isGrounded && _spikes.All(element => !(Vector3.Distance(position, element) < _gateOfSpikesData.MinDistanceBetweenAttacks)); } private void EndSkill(float cooldown, Action action) { Utils.EndUniqueCoroutine(this, ref SkillCoroutineInstance); _spineController.SetSkin(SandMoleSkin.Normal.ToString()); _spineController.PlayAnimation(SandMoleAnimation.Idle.ToString(), true); action?.Invoke(); Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(cooldown, EndCooldown)); } } }