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); } }