Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IFighterCallback
{
void OnDeath();
}
// Generic subclass for any Fighter on the field, whether it's an Enemy or the AntiPlayer.
// Contains stats management such as health, attacks, damage, death, etc.
public abstract class Fighter : MonoBehaviour
{
[SerializeField] int baseHealth = 100;
[SerializeField, Tooltip("Attack every x ms")] int baseAttackSpeed = 1000;
[SerializeField] int baseAttackDamage = 10;
[SerializeField] int baseArmor = 1;
public List<IFighterCallback> callbacks = new List<IFighterCallback>();
protected int currentHealth = 100;
protected Animator animator;
protected bool alive { get => currentHealth > 0; }
protected abstract void Attack();
float timeSinceLastAttack = 0f;
protected virtual void Awake()
{
animator = GetComponent<Animator>();
var enemyStats = StatsManager.instance.GetEnemyStats();
currentHealth = Mathf.RoundToInt(baseHealth * enemyStats.healthMultiplier);
}
protected virtual void Update()
{
if (alive)
{
timeSinceLastAttack += Time.deltaTime;
var timeUntilNextAttack = baseAttackSpeed - timeSinceLastAttack;
if (timeUntilNextAttack <= 0)
{
Attack();
// TODO delegate to subclass? Some attack animations take time to charge up.
animator.SetTrigger("Attack");
timeSinceLastAttack = -timeUntilNextAttack; // To account for overshoot
}
}
}
public void DealDamage(int dmg)
{
var enemyStats = StatsManager.instance.GetEnemyStats();
var actualDamage = Mathf.Max(0, Mathf.RoundToInt(dmg - baseArmor * enemyStats.armorMultiplier));
currentHealth = Mathf.Max(currentHealth - actualDamage, 0);
if (currentHealth == 0)
{
animator.SetTrigger("Death");
callbacks.ForEach(c => c.OnDeath());
// TODO (Depending on the death animation) only destroy on round end so that corpses stay on the ground
// Destroy(gameObject);
}
else
{
animator.SetTrigger("Hurt");
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("AntiPlayer"))
{
var enemyStats = StatsManager.instance.GetEnemyStats();
var damageToDeal = Mathf.RoundToInt(baseAttackDamage * enemyStats.damageMultiplier);
other.GetComponent<Fighter>().DealDamage(damageToDeal);
}
}
}