using OctoberStudio.Pool; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace OctoberStudio.Enemy { public class VoidBehavior : EnemyBehavior { private static readonly int TELEPORT_TRIGGER = Animator.StringToHash("Teleport"); private static readonly int IS_CHARGING_BOOL = Animator.StringToHash("Is Charging"); [SerializeField] GameObject blackHolePrefab; [SerializeField] Animator animator; [SerializeField] GameObject projectilePrefab; [SerializeField] float blackHoleDamage = 5f; private PoolComponent blackHolesPool; private List blackHoles = new List(); private PoolComponent projectilesPool; private bool isTeleporting; private Vector2 teleportDestination; private bool IsHolesActive { get; set; } private bool IsCharging { get; set; } private Coroutine teleportCoroutine; private Coroutine behaviorCoroutine; private List shades = new List(); protected override void Awake() { base.Awake(); blackHolesPool = new PoolComponent(blackHolePrefab, 5); projectilesPool = new PoolComponent(projectilePrefab, 5); } public override void Play() { base.Play(); IsMoving = false; behaviorCoroutine = StartCoroutine(BehaviorCoroutine()); teleportCoroutine = StartCoroutine(TeleportCoroutine()); } private IEnumerator TeleportCoroutine() { while (true) { yield return new WaitForSeconds(5); for(int i = 0; i < 50; i++) { var position = StageController.FieldManager.Fence.GetRandomPointInside(1); bool collides = false; foreach(var blackHole in blackHoles) { if (blackHole.Contains(position)){ collides = true; break; } } if (!collides) { isTeleporting = true; teleportDestination = position; animator.SetTrigger(TELEPORT_TRIGGER); break; } } yield return new WaitForSeconds(4); if (IsHolesActive) { IsCharging = true; animator.SetBool(IS_CHARGING_BOOL, true); for(int i = 0; i < 3; i++) { foreach (var blackHole in blackHoles) { blackHole.Charge(projectilesPool); } yield return new WaitForSeconds(0.6f); } animator.SetBool(IS_CHARGING_BOOL, false); IsCharging = false; } } } private IEnumerator BehaviorCoroutine() { while (true) { for (int i = 0; i < 5; i++) { var blackHole = blackHolesPool.GetEntity(); blackHole.Damage = blackHoleDamage * StageController.Stage.EnemyDamage; bool placed = true; int counter = 0; while (true) { var position = StageController.FieldManager.Fence.GetRandomPointInside(1); blackHole.transform.position = position; bool isPlaceAvailable = true; for (int j = 0; j < blackHoles.Count; j++) { if (blackHoles[j].Intersects(blackHole)) { isPlaceAvailable = false; break; } } if (isPlaceAvailable && !blackHole.Contains(transform.position) && !blackHole.Contains(PlayerBehavior.Player.transform.position)) { blackHoles.Add(blackHole); break; } counter++; if (counter == 20) { placed = false; break; } } if (!placed) blackHole.gameObject.SetActive(false); yield return new WaitForSeconds(0.1f); } IsHolesActive = true; for (int i = 0; i < 5; i++) { yield return new WaitForSeconds(2f); var blackHole = blackHoles[i % blackHoles.Count]; var shade = StageController.EnemiesSpawner.Spawn(EnemyType.Shade, blackHole.transform.position, OnShadeDied); shades.Add(shade); } yield return new WaitWhile(() => IsCharging); IsHolesActive = false; for (int i = 0; i < blackHoles.Count; i++) { blackHoles[i].Hide(); } blackHoles.Clear(); yield return new WaitForSeconds(1f); } } private void OnShadeDied(EnemyBehavior shade) { shade.onEnemyDied -= OnShadeDied; shades.Remove(shade); } public void Teleport() { if (isTeleporting) { isTeleporting = false; transform.position = teleportDestination; } } protected override void Die(bool flash) { StopCoroutine(teleportCoroutine); StopCoroutine(behaviorCoroutine); for(int i = 0; i < blackHoles.Count; i++) { blackHoles[i].Clear(); } blackHoles.Clear(); for(int i = 0; i < shades.Count; i++) { shades[i].onEnemyDied -= OnShadeDied; shades[i].Kill(); } shades.Clear(); base.Die(flash); } } }