using System; using System.Collections; using System.Collections.Generic; using System.Linq; using BlueWater.Maps; using BlueWater.Utility; using UnityEngine; using Random = UnityEngine.Random; namespace BlueWater.Enemies.Bosses.SandMole.Skills { public class GateOfSpikes : BaseSkill { private GateOfSpikesData _gateOfSpikesData; private SandMole _sandMole; private AnimationController _animationController; private Collider _userCollider; private Collider _targetCollider; private Transform _particleInstantiateLocation; private List _spikes; protected override void BasicSetting() { if (!_sandMole) { _sandMole = SkillUser.GetComponent(); _animationController = _sandMole.AnimationController; _userCollider = _sandMole.CharacterCollider; _targetCollider = _sandMole.Target; _particleInstantiateLocation = MapManager.Instance.SandMoleMapController.ParticleInstanceLocation; } _gateOfSpikesData = (GateOfSpikesData)SkillData; _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; _sandMole.StopMove(); _animationController.SetAnimationParameter("skillIndex", (int)SandMoleSkill.GateOfSpikes); var animationStarted = false; yield return StartCoroutine(_animationController.WaitForAnimationToRun("GateOfSpikes", success => animationStarted = success)); if (!animationStarted || !SkillUser || !_userCollider) { EndSkill(0, actions[0]); yield break; } IsUsingSkill = true; _animationController.ResetAnimationSpeed(); var startPosition = SkillUser.transform.position; var targetCenterPosition = _targetCollider.transform.position; startPosition.y = targetCenterPosition.y; var targetVector = targetCenterPosition - startPosition; var targetDirection = targetVector.normalized; _sandMole.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); 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); _animationController.SetAnimationParameter("skillIndex", (int)SandMoleSkill.None); action?.Invoke(); Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(cooldown, EndCooldown)); } } }