using System; using System.Collections; using BlueWater.Interfaces; using BlueWater.Maps; using BlueWater.Utility; using UnityEngine; namespace BlueWater.Enemies.Bosses.SandMole.Skills { public class SpikeBarrage : BaseSkill { private SpikeBarrageData _spikeBarrageData; private AnimationController _animationController; private AiMovement _aiMovement; private Rigidbody _userRigidbody; private Collider _userCollider; private Collider _targetCollider; private SpriteRenderer _userSpriteRenderer; private SandMoleMapController _sandMoleMapController; private Transform _particleInstantiateLocation; private Transform _centerSpawnTransform; private static readonly int _dissolveValueHash = Shader.PropertyToID("_DissolveValue"); protected override void BasicSetting() { _animationController = SkillUser.GetComponent(); _aiMovement = SkillUser.GetComponent(); _userRigidbody = SkillUser.GetComponent(); _userCollider = SkillUser.GetComponent(); _targetCollider = SkillUser.GetComponent().Target; _userSpriteRenderer = SkillUser.GetComponentInChildren(); _sandMoleMapController = MapManager.Instance.SandMoleMapController; _particleInstantiateLocation = _sandMoleMapController.ParticleInstanceLocation; _centerSpawnTransform = _sandMoleMapController.CenterSpawnTransform; _spikeBarrageData = (SpikeBarrageData)SkillData; base.BasicSetting(); } public override void ActivateSkill(params Action[] actions) { Utils.StartUniqueCoroutine(this, ref SkillCoroutineInstance, SkillCoroutine(actions)); } private IEnumerator SkillCoroutine(params Action[] actions) { EnableSkill = false; _aiMovement.StopMove(); _animationController.SetAnimationParameter("skillIndex", (int)SandMoleSkill.SpikeBarrage); var animationStarted = false; yield return StartCoroutine(_animationController.WaitForAnimationToRun("SpikeBarrage", success => animationStarted = success)); if (!animationStarted || !SkillUser) { EndSkill(0, actions[0]); yield break; } _userRigidbody.isKinematic = true; _userSpriteRenderer.material.SetFloat(_dissolveValueHash, 1f); var elapsedTime = 0f; var dissolveTime = _spikeBarrageData.DissolveTime; while (elapsedTime <= dissolveTime) { if (!_userSpriteRenderer) { EndSkill(0, actions[0]); yield break; } var value = Mathf.Lerp(1f, 0f, elapsedTime / dissolveTime); _userSpriteRenderer.material.SetFloat(_dissolveValueHash, value); elapsedTime += Time.deltaTime; yield return null; } _userSpriteRenderer.material.SetFloat(_dissolveValueHash, 0f); _aiMovement.Teleport(SkillUser.transform.position + Vector3.up * 20f); yield return new WaitForSeconds(1f); _aiMovement.Teleport(_centerSpawnTransform.position); _userRigidbody.isKinematic = false; elapsedTime = 0f; dissolveTime = _spikeBarrageData.SpawnDissolveTime; while (elapsedTime <= dissolveTime) { if (!_userSpriteRenderer) { EndSkill(0, actions[0]); yield break; } var value = Mathf.Lerp(0f, 1f, elapsedTime / dissolveTime); _userSpriteRenderer.material.SetFloat(_dissolveValueHash, value); elapsedTime += Time.deltaTime; yield return null; } _userSpriteRenderer.material.SetFloat(_dissolveValueHash, 1f); var startAngle = _spikeBarrageData.StartAngle; var angleStep = _spikeBarrageData.AngleStep; var spikeSpawnPosition = _userCollider.bounds.center; spikeSpawnPosition.y = _targetCollider.bounds.center.y; var spikeInterval = new WaitForSeconds(_spikeBarrageData.SpikeInterval); for (var i = 0; i < _spikeBarrageData.SpikeCount; i++) { var currentAngle = startAngle + angleStep * i; var rotation = Quaternion.Euler(0f, currentAngle, 0f); var spike = Instantiate(_spikeBarrageData.SpikePrefab, spikeSpawnPosition, rotation, _particleInstantiateLocation).GetComponent(); spike.Initialize(_spikeBarrageData.Damage, _spikeBarrageData.TargetLayer); spike.AddForce(spike.transform.forward * _spikeBarrageData.ProjectileSpeed, ForceMode.Impulse); yield return spikeInterval; } EndSkill(SkillData.Cooldown, actions[0]); } private void EndSkill(float cooldown, Action action) { Utils.EndUniqueCoroutine(this, ref SkillCoroutineInstance); _animationController.ResetAnimationSpeed(); _animationController.SetAnimationParameter("skillIndex", (int)SandMoleSkill.None); action?.Invoke(); Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(cooldown, EndCooldown)); } } }