201 lines
6.1 KiB
C#

using OctoberStudio.Easing;
using OctoberStudio.Extensions;
using OctoberStudio.Pool;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace OctoberStudio.Enemy
{
public class QueenWaspBehavior : EnemyBehavior
{
private static readonly int IS_CHARGING_HASH = Animator.StringToHash("IsCharging");
private static readonly int IS_SHOOTING_HASH = Animator.StringToHash("IsShooting");
private Coroutine behaviorCoroutine;
[SerializeField] Animator animator;
[SerializeField] Vector2 fenceOffset;
[Header("Charge")]
[SerializeField] SpriteRenderer chargeSprite;
[SerializeField] float chargeSpriteDistance;
[SerializeField] float chargeWarningDuration;
[SerializeField] float chargeMovementDuration;
[SerializeField] float chargeMovementSpeed;
[SerializeField] int chargesCount;
[Header("Shooting")]
[SerializeField] ParticleSystem shootParticle;
[SerializeField] int minesAmount;
[SerializeField] int attacksCount;
[SerializeField] float timeBetweenAttacks;
[SerializeField] GameObject minePrefab;
[SerializeField] Transform mineSpawnPosition;
[SerializeField] float mineDamageMultiplier;
[Header("Following")]
[SerializeField] float followingPlayerDuration;
private int placedMines = 0;
private PoolComponent<HoneyMineBehavior> minesPool;
private List<HoneyMineBehavior> activeMines = new List<HoneyMineBehavior>();
protected override void Awake()
{
base.Awake();
minesPool = new PoolComponent<HoneyMineBehavior>(minePrefab, 10);
}
public override void Play()
{
base.Play();
behaviorCoroutine = StartCoroutine(BehaviorCoroutine());
}
private IEnumerator BehaviorCoroutine()
{
while (IsAlive)
{
yield return MoveToPlayer();
for(int i = 0; i < chargesCount; i++)
{
yield return Charge();
}
yield return MoveToPlayer();
yield return PlaceMines();
}
}
private IEnumerator MoveToPlayer()
{
IsMoving = true;
yield return new WaitForSeconds(followingPlayerDuration);
IsMoving = false;
}
private IEnumerator Charge()
{
float time = 0;
chargeSprite.gameObject.SetActive(true);
var movementDirection = Vector2.up;
while (time < chargeWarningDuration)
{
time += Time.deltaTime;
movementDirection = (PlayerBehavior.Player.transform.position - chargeSprite.transform.position).normalized;
chargeSprite.transform.rotation = Quaternion.FromToRotation(Vector2.up, movementDirection);
chargeSprite.size = chargeSprite.size.SetY(time / chargeWarningDuration * chargeSpriteDistance);
if (!scaleCoroutine.ExistsAndActive())
{
var scale = transform.localScale;
if (movementDirection.x > 0 && scale.x < 0 || movementDirection.x < 0 && scale.x > 0)
{
scale.x *= -1;
transform.localScale = scale;
}
}
yield return null;
}
chargeSprite.gameObject.SetActive(false);
animator.SetBool(IS_CHARGING_HASH, true);
time = 0;
while (time < chargeMovementDuration)
{
var position = transform.position.XY() + Time.deltaTime * movementDirection * chargeMovementSpeed;
if (StageController.FieldManager.ValidatePosition(position, fenceOffset))
{
transform.position = position;
}
time += Time.deltaTime;
yield return null;
}
animator.SetBool(IS_CHARGING_HASH, false);
}
private IEnumerator PlaceMines()
{
for (int i = 0; i < attacksCount; i++)
{
placedMines = 0;
animator.SetBool(IS_SHOOTING_HASH, true);
while (placedMines < minesAmount)
{
yield return null;
}
animator.SetBool(IS_SHOOTING_HASH, false);
yield return new WaitForSeconds(timeBetweenAttacks);
}
if (!scaleCoroutine.ExistsAndActive())
{
var scale = transform.localScale;
var movementDirection = (PlayerBehavior.CenterPosition - transform.position.XY()).normalized;
if (movementDirection.x > 0 && scale.x < 0 || movementDirection.x < 0 && scale.x > 0)
{
scale.x *= -1;
transform.localScale = scale;
}
}
}
public void Shoot()
{
if(shootParticle != null) shootParticle.Play();
placedMines++;
var mine = minesPool.GetEntity();
var direction = Vector3.right * transform.localScale.x;
var landingPosition = PlayerBehavior.CenterPosition;
mine.Damage = StageController.Stage.EnemyDamage * mineDamageMultiplier;
mine.Spawn(mineSpawnPosition.position, direction, landingPosition);
mine.onExploded += OnMineExploded;
activeMines.Add(mine);
}
private void OnMineExploded(HoneyMineBehavior mine)
{
mine.onExploded -= OnMineExploded;
}
protected override void Die(bool flash)
{
StopCoroutine(behaviorCoroutine);
for(int i = 0; i < activeMines.Count; i++)
{
activeMines[i].Clear();
activeMines[i].onExploded -= OnMineExploded;
}
activeMines.Clear();
chargeSprite.gameObject.SetActive(false);
base.Die(flash);
}
}
}