202 lines
5.7 KiB
C#
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);
|
|
}
|
|
} |