TowerDefenseGame/Assets/Scripts/Runtime/AI/EnemyManager/Gobler.cs
Nico 24b9ece93d Create interfaces for IAttacker and IDamageable
Utilize interfaces to create new Enemy class inheriting them and further developing on them also encapsulating more enemy type functions
2025-07-25 15:40:43 -07:00

182 lines
5.1 KiB
C#

using AI.Base;
using NUnit.Framework.Internal.Execution;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using UnityEditor.Build;
using UnityEngine;
using UnityEngine.AI;
using static EnemySpawnerData;
using static UnityEngine.RuleTile.TilingRuleOutput;
public class Gobler : Enemy {
public Gobler(GameObject owner) : base(owner) {
BaseDamage = 10;
AttackPreparationTime = 1;
AttackCooldownDuration = 1;
BaseHealth = 100;
CurrentHealth = BaseHealth;
IsKnockable = true;
SetState(State.GoToCrystal);
SubscribeToEvent();
}
protected override void SetPriorityState() {
if (CurrentState == State.PrepareAttack) return;
if (CurrentState == State.FinalizeAttack) return;
if (CurrentState == State.ChasePlayer) return;
if (CurrentState == State.TakeDamage) return;
if (CurrentState == State.Die) return;
if (DistFromPlayer > ChaseDistance) return;
SetState(State.ChasePlayer);
}
protected override void DoUpdate() {
switch (CurrentState) {
case State.None:
SetState(State.GoToCrystal);
break;
case State.GoToCrystal:
if (CanAttackCrystal)
SetState(State.PrepareAttack);
break;
case State.ChasePlayer:
if (CanAttackPlayer)
SetState(State.PrepareAttack);
else if (DistFromPlayer > ChaseDistance + ChaseDistanceBuffer)
SetState(State.None);
else
PathAgent.SetDestination(PlayerPos);
break;
case State.TakeDamage:
if (IsInvincible) {
var velocity = DirectionOfDamage * Knockback * 10 * InvincibilityLeft;
//var isWalkable = NavMeshUtils.IsWalkable(MyPos, DirectionOfDamage);
//Rigidbody.linearVelocity = isWalkable ? velocity : Vector2.zero;
Rigidbody.linearVelocity = velocity;
MaterialColorOverlay.SetFloat("_FlashAmount", InvincibilityLeft);
}
if (!IsFrameFrozen) SetState(State.None);
break;
case State.PrepareAttack:
MaterialColorOverlay.SetFloat("_FlashAmount", AttackPreparationTimeElapsedNormalized);
if (!IsFrameFrozen) SetState(State.FinalizeAttack);
break;
}
}
protected override void SetState(State newState) {
CurrentState = newState;
switch (CurrentState) {
case State.None:
if (AggroOnPlayer) TextPopUp.SpawnFloatingText("?", Color.red);
PathAgent.isStopped = false;
AggroOnCrystal = false;
AggroOnPlayer = false;
break;
case State.GoToCrystal:
AggroOnCrystal = true;
PathAgent.SetDestination(CrystalPos);
break;
case State.ChasePlayer:
AggroOnPlayer = true;
TextPopUp.SpawnFloatingText("!", Color.red);
break;
case State.TakeDamage:
PathAgent.isStopped = true;
TextPopUp.SpawnFloatingText(DamageTaken.ToString(), Color.red, 3);
MaterialColorOverlay.SetColor("_FlashColor", Color.white);
break;
case State.PrepareAttack:
PathAgent.isStopped = true;
StartAttackPreparation();
MaterialColorOverlay.SetColor("_FlashColor", Color.purple);
break;
case State.FinalizeAttack:
Collider2D[] hits = Physics2D.OverlapCircleAll(MyPos + Vector2.down, 4);
foreach (var hit in hits) {
if (!hit.CompareTag("PlayerHurtBox") || !hit.CompareTag("SuperSpecialGem")) continue;
Debug.Log($"{hit.tag} hit");
//GameObject parent = hit.transform.parent?.gameObject;
//Vector2 knockbakDirection = ActiveClass.HitBoxDraw.Directional ? PrevDirection : parent.transform.position - transform.position;
//EnemySpawnerData.EnemyMap[parent].Damage(ActiveClass.HitBoxDraw.Damage, knockbakDirection, ActiveClass.HitBoxDraw.Knockback);
}
StartAttackCooldown();
SetState(AggroOnPlayer ? State.ChasePlayer : State.GoToCrystal);
break;
case State.Die:
SpawnableEnemyInfo.DestroyEnemy(Owner, Enemies.Gobler);
SetState(State.None);
break;
}
if (PrevState != CurrentState) PrevState = CurrentState;
}
protected override void OnDrawGizmos() {
if (Owner == null) return;
DrawChaseDistance();
DrawAttackDistance();
DrawAttackReach();
}
private void DrawWireSphere(Color color, Vector2 center, float radius) => EnemyManagers[Enemies.Gobler].DrawWireSphere(color, center, radius);
private void DrawChaseDistance() {
DrawWireSphere(Color.green, MyPos, ChaseDistance);
}
private void DrawAttackDistance() {
if (CurrentState != State.PrepareAttack) return;
Collider2D[] hits = Physics2D.OverlapCircleAll(MyPos + Vector2.down, 4);
Vector2 center = MyPos + Vector2.down;
DrawWireSphere(Color.salmon, center, 4);
}
private void DrawAttackReach() {
//if (CurrentState != (IState)AttackState) return;
//Gizmos.color = Color.red;
Vector2 direction2D = (PlayerPos - MyPos).normalized;
Vector2 point2D = MyPos + direction2D * AttackDistance;
//Gizmos.DrawWireSphere(point2D, AttackMaskDiameter);
DrawWireSphere(Color.red, point2D, AttackMaskDiameter);
}
}