TowerDefenseGame/Assets/Scripts/Runtime/Core/Combat/EnemyCombat.cs
Nico 62b981f440 Add knockbock gaurd against being pushed out of bounds
Further develop on attacking and taking damage states
2025-07-25 17:52:08 -07:00

143 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;
using UnityEngine.AI;
using static EnemySpawnerData;
[SerializeField]
public class Enemy : AttackerAndDamageable {
[Header("Mechanics Attributes")]
[SerializeField] public float ChaseDistance = 10f;
[SerializeField] public float ChaseDistanceBuffer = 1f;
[SerializeField] public float AttackDistance = 1.5f;
[SerializeField] public float AttackMaskDiameter = 1f;
[Header("Enemy Attributes")]
[SerializeField] public float Attack = 10f;
[SerializeField] public float Speed = 5f;
[SerializeField] public float Health = 10f;
[SerializeField] public float Energy = 10f;
protected FloatingTextSpawner TextPopUp;
protected Player Player { get { return Player.Instance; } }
protected Transform PlayerTransform { get { return Player.transform; } }
protected Vector2 PlayerPos { get { return PlayerTransform.position; } }
protected Vector2 CrystalPos { get { return GameManager.Crystal.transform.position; } }
protected GameObject Owner;
protected Rigidbody2D Rigidbody;
protected Transform MyTransform { get { return Owner.transform; } }
protected Vector2 MyPos { get { return MyTransform.position; } set { MyTransform.position = value; } }
protected NavMeshAgent PathAgent;
protected Material MaterialColorOverlay;
protected bool IsUpdating;
protected bool IsSettingNewState;
public float DistFromPlayer { get; protected set; }
public float DistFromCrystal { get; protected set; }
protected bool CanAttackPlayer => DistFromPlayer <= AttackDistance && CanAttack;
protected bool CanAttackCrystal => DistFromCrystal <= AttackDistance && CanAttack;
public bool AggroOnPlayer { get; protected set; }
public bool AggroOnCrystal { get; protected set; }
public State CurrentState;
public State PrevState;
public enum State {
None,
GoToCrystal,
AttackCrystal,
ChasePlayer,
AttackPlayer,
PrepareAttack,
FinalizeAttack,
TakeDamage,
Die
}
public Enemy(GameObject owner) {
Owner = owner;
PathAgent = Owner.GetComponent<NavMeshAgent>();
PathAgent.updatePosition = false;
PathAgent.updateRotation = false;
PathAgent.updateUpAxis = false;
PathAgent.speed = Speed;
IsUpdating = false;
IsSettingNewState = false;
TextPopUp = new FloatingTextSpawner(Owner.transform, 1);
OnTakeDamage += (damage, direction) => { QueueUpdate(); SetState(State.TakeDamage); IsUpdating = false; };
OnDeath += () => { QueueUpdate(); SetState(State.Die); UnsubscribeToEvent(); IsUpdating = false; };
Rigidbody = Owner.GetComponent<Rigidbody2D>();
foreach (var material in Owner.GetComponentsInChildren<SpriteRenderer>().Select(x => x.material).ToList()) {
switch (material.name.Split(' ')[0]) {
case "DamageFlashMat": MaterialColorOverlay = material; break;
}
}
}
private Action cachedUpdate;
protected void SubscribeToEvent() {
cachedUpdate = () => {
if (PathAgent == null || Owner == null) return;
PathAgentHandler.UpdatePositionIso(PathAgent, Owner.transform);
Update();
};
EnemyManagers[Enemies.Gobler].UpdateTick += cachedUpdate;
EnemyManagers[Enemies.Gobler].GizmoTick += OnDrawGizmos;
}
protected void UnsubscribeToEvent() {
EnemyManagers[Enemies.Gobler].UpdateTick -= cachedUpdate;
EnemyManagers[Enemies.Gobler].GizmoTick -= OnDrawGizmos;
}
protected virtual void SetPriorityState() { }
protected void QueueUpdate() {
while (IsUpdating) System.Threading.Thread.Sleep(100);
IsUpdating = true;
}
protected virtual void DoUpdate() { }
protected void Update() {
if (Owner == null) return;
if (GameManager.Crystal == null) return;
if (IsSettingNewState) return;
if (IsUpdating) return;
IsUpdating = true;
DistFromPlayer = Vector2.Distance(MyPos, PlayerPos);
DistFromCrystal = Vector2.Distance(MyPos, CrystalPos);
SetPriorityState();
DoUpdate();
IsUpdating = false;
}
protected void SetState(State newState) {
IsSettingNewState = true;
DoSetState(newState);
IsSettingNewState = false;
}
protected virtual void DoSetState(State newState) { }
protected virtual void OnDrawGizmos() { }
}