229 lines
6.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KnightOnHorse : Ally
{
[SerializeField]
private int _chargeAttackDamage;
[SerializeField]
private int _chargeCooldown;
[SerializeField]
private int _maxChargeHitCount;
[SerializeField]
private int _maxChargeDistance;
[SerializeField]
private float _fadeDistance;
[SerializeField]
private GameObject _detection;
[SerializeField]
private GameObject _chargeDetection;
[SerializeField]
private GameObject _root;
// scripts
private Root _rootScript;
private Detection _detectionScript;
// attack variables
private int _originalAttackDamage;
// movement variables
private Vector3 _originalPos;
private Vector2 _movementVector = Vector2.zero;
// charge variables
private bool _isCharging;
private float _timeSinceLastCharge;
private List<Entity> _opponentsHit = new List<Entity>();
// fading variables
private float _fadeProgress;
private bool _isFading;
private int _fadeState;
public override void Start()
{
base.Start();
_rootScript = _root.GetComponent<Root>();
_detectionScript = _detection.GetComponent<Detection>();
// keep originals to go back to them eventually
_originalAttackDamage = AttackDamage;
_originalPos = transform.position;
// makes sure the entity charges on creation
_timeSinceLastCharge = _chargeCooldown + 1;
}
public override void Update()
{
Debug.Log(AttackDamage);
// fade if charge done
if (_isFading)
{
HandleFading();
return;
}
// check if charge is ready
if (_timeSinceLastCharge > _chargeCooldown && !_isCharging)
{
AttackDamage = _chargeAttackDamage;
SweepAttack();
_isCharging = true;
Animation.ToggleChargeAnim(true);
}
if (_isCharging)
{
// sweep attack if an enemy slips behind the tip's hitbox
SweepAttack();
// toggle charge detection
_chargeDetection.SetActive(true);
// movement
HandleMovement();
// attack
if (IsEnemyDetected && !_opponentsHit.Contains(Enemy))
{
AttackEnemyRiding();
}
// reset
if (transform.position.x - _originalPos.x >= _maxChargeDistance || _opponentsHit.Count >= _maxChargeHitCount)
{
// charge state
_isCharging = false;
_timeSinceLastCharge = 0;
_opponentsHit.Clear();
// detection state
IsEnemyDetected = false;
Enemy = null;
_chargeDetection.SetActive(false);
// attack damage
AttackDamage = _originalAttackDamage;
// start fading
_isFading = true;
}
}
else
{
// charge cooldown
_timeSinceLastCharge += Time.deltaTime;
// regular attack
if (IsEnemyDetected)
{
AttackEnemy();
}
}
}
private void HandleMovement()
{
_movementVector.x = Time.deltaTime * Speed;
transform.position += (Vector3)_movementVector;
}
private void AttackEnemy()
{
//Attack Cooldown
if (AttackSpeedWait > AttackInterval)
{
Animation.PlayAttackAnim();
AttackSpeedWait = 0f;
}
AttackSpeedWait += Time.deltaTime;
}
private void AttackEnemyRiding()
{
// call root attack cause no specific animation
_rootScript.Attack();
_opponentsHit.Add(Enemy);
}
/*
* Attacks all enemies already in the default detection box during charge.
* Charge uses a different detection (at the tip) due to Enemy being the first opponent to enter the hitbox.
* Therefore enemies would only get hit when the previous Enemy exits the hitbox, which is at the handle instead of the tip.
* To cover for the enemies behind the charge detection which is at the tip, we hit them all as the charge starts
* and during in case something goes wrong and a monster slips through the charge hitbox.
*/
private void SweepAttack()
{
foreach (Entity entity in _detectionScript.DetectedEntities)
{
if (!_opponentsHit.Contains(entity))
{
Enemy = entity;
AttackEnemyRiding();
}
}
}
private void HandleFading()
{
if (_fadeState == 0 && _fadeProgress < _fadeDistance)
{
HandleMovement();
//fade out
_fadeProgress += _movementVector.x / _fadeDistance;
foreach (SpriteRenderer spriteRenderer in SpriteRenderers)
{
spriteRenderer.color = new Color(1.0f, 1.0f, 1.0f, 1.0f - _fadeProgress);
}
}
else if (_fadeState == 0 && _fadeProgress > _fadeDistance)
{
// teleport behind original position to fade in
transform.position = new Vector3(_originalPos.x - _fadeDistance, _originalPos.y, _originalPos.z);
_fadeState = 1;
}
else if (_fadeState == 1 && _fadeProgress < _fadeDistance * 2)
{
HandleMovement();
// fade in
_fadeProgress += _movementVector.x / _fadeDistance;
foreach (SpriteRenderer spriteRenderer in SpriteRenderers)
{
spriteRenderer.color = new Color(1.0f, 1.0f, 1.0f, _fadeProgress - _fadeDistance);
}
}
else
{
// disable fading
_isFading = false;
_fadeProgress = 0;
_fadeState = 0;
foreach (SpriteRenderer spriteRenderer in SpriteRenderers)
{
spriteRenderer.color = new Color(1.0f, 1.0f, 1.0f, 1.0f);
}
// reset position
_movementVector.x = 0;
transform.position = _originalPos;
// toggle detection
_detection.SetActive(true);
_chargeDetection.SetActive(false);
// toggle animation
Animation.ToggleChargeAnim(false);
}
}
}