TowerDefenseGame/Assets/Scripts/Runtime/AI/EnemyManager/Gobler.cs
Nico a74d9fc9ab Add menu
Add scene transition feature
2025-07-29 23:05:46 -07:00

202 lines
5.7 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 = 0.5f;
AttackCooldownDuration = 1;
BaseHealth = 100;
CurrentHealth = BaseHealth;
InvincibilityDuration = 0.11f;
FrameFreezeDuration = 0.3f;
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) {
if (AggroOnPlayer) TextPopUp.SpawnFloatingText("?", Color.red);
AggroOnPlayer = false;
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 / InvincibilityDuration);
} else {
MaterialColorOverlay.SetFloat("_FlashAmount", 0);
Rigidbody.linearVelocity = Vector2.zero;
}
if (!IsFrameFrozen) SetState(State.None);
break;
case State.PrepareAttack:
MaterialColorOverlay.SetFloat("_FlashAmount", AttackPreparationTimeElapsedNormalized);
if (AttackIsReady) SetState(State.FinalizeAttack);
break;
case State.FinalizeAttack:
SetState(AggroOnPlayer ? State.ChasePlayer : State.GoToCrystal);
break;
}
}
protected override void DoSetState(State newState) {
Debug.Log($"New State: {newState.ToString()}");
CurrentState = newState;
switch (newState) {
case State.None:
PathAgent.isStopped = true;
break;
case State.GoToCrystal:
AggroOnCrystal = true;
PathAgent.isStopped = false;
PathAgent.SetDestination(CrystalPos);
break;
case State.ChasePlayer:
if (!AggroOnPlayer) TextPopUp.SpawnFloatingText("!", Color.red);
PathAgent.isStopped = false;
AggroOnPlayer = true;
break;
case State.TakeDamage:
AggroOnCrystal = false;
AggroOnPlayer = false;
PathAgent.isStopped = true;
TextPopUp.SpawnFloatingText(DamageTaken.ToString(), Color.white, 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"))
Player.Combat.Damage(BaseDamage, PlayerPos - MyPos, 20);
else if (hit.CompareTag("SuperSpecialGem"))
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);
}
MaterialColorOverlay.SetFloat("_FlashAmount", 0);
StartAttackCooldown();
break;
case State.Die:
SpawnableEnemyInfo.DestroyEnemy(Owner, Enemies.Gobler);
SetState(State.None);
break;
}
if (PrevState != CurrentState) PrevState = CurrentState;
Debug.Log($"State Done: {newState.ToString()}");
}
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);
}
}