using System.Collections; using System.Collections.Generic; using UnityEngine; public class BasicEnemyNPCController : NPCControllerBase { [Header("Events:")] [SerializeField] protected GameEvent_Float experienceOnDeath; protected DropTable dropTable; protected override void Awake() { dropTable = GetComponentInChildren(); base.Awake(); } protected override void OnDeath() { RPC_OnDeath(dropTable.CalculateLootDrop()); } protected override void RPC_OnDeath(bool lootDropped) { if (isDead) return; //Debug.Log($"{this.gameObject.name} died!"); isDead = true; agent.enabled = false; experienceOnDeath.Raise(health.GetMaxValue() * GameConstants.GameBalancing.HealthIntoExperienceMultiplier); dropTable.DropLoot(lootDropped); animatorController.SetDead(); } protected override void OnNewTargetIdentifiedAndHasTarget() { //someone entered sight, npc already has a target //Debug.Log("New Target available, current target = " + currentTarget.name); } protected override void OnNewTargetIdentifiedAndNoCurrentTarget() { //someone entered sight, npc does not have a target yet //Debug.Log("New Target available, current target = null, updating target with closest"); UpdateCurrentTarget(GetClosestTarget()); } protected override void OnPossibleTargetLostAndHasTargetAndVision() { //someone exited sight, npc already has target and vision } protected override void OnPossibleTargetLostAndHasTargetButNoVision() { //someone exited sight, npc already has target but no vision of it (possibly his target was the one getting out of sight) base.OnPossibleTargetLostAndHasTargetButNoVision(); UpdateCurrentTarget(GetClosestTarget()); } protected override void OnPossibleTargetLostAndHasNoCurrentTargetButHasAvailableTargets() { //someone exited sight, npc has no target yet, there are available targets to pick UpdateCurrentTarget(GetClosestTarget()); } protected override void OnPossibleTargetLostAndHasNoCurrentTargetAndNoAvailableTargets() { //someone exited sight, npc has no target yet, there are NO available targets PatrolNewPosition(); } protected override void ChasingUpdate() { base.ChasingUpdate(); } protected override void PatrollingUpdate() { base.PatrollingUpdate(); } protected int failedTryAttackCounter = 0; protected int failedTryAttackLimitToChangeTarget = 3; protected override void TryAttack() { if (waitingForAttackAnimation) return; if (maintainsDistance) UpdateCurrentTarget(GetClosestTarget()); possibleTargetHealth = currentTarget.GetComponent(); if (possibleTargetHealth.GetCurrentValue() <= 0) { UpdateCurrentTarget(GetClosestTarget()); return; } GetHighestPriorityAvailableAbility(); if (ability == null) { failedTryAttackCounter++; if(failedTryAttackCounter >= failedTryAttackLimitToChangeTarget && possibleTargets.Count > 1) { failedTryAttackCounter = 0; UpdateCurrentTarget(GetClosestTarget()); Debug.Log("RESETTING TARGET AFTER 3 FAIL ATTACK ATTEMPTS"); } //Debug.Log("No abilities available for current conditional state"); SetupAgentStats(currentTarget.transform.position, true); SetAgentMoving(true); return; } //Debug.Log(this.name + " Ability with highest priority = " + ability.name); waitingForAttackAnimation = true; ForceFaceTarget(); SetAgentMoving(false); animatorController.SetTriggerBasedOnAbility(ability.animationType); } protected virtual void GetHighestPriorityAvailableAbility() { ability = abilityPriorityManager.GetHighestPriorityAvailableAbility(); } public override void OnAttackAnimationEventTriggered() { //Debug.Log(this.name + " Controller on attack animation event triggered, executing ability = "); if(ability is AreaOfEffectOverTimeAbility && !((AreaOfEffectOverTimeAbility)ability).spawnUnderUser) { if (currentTarget != null) ability.Execute(myTag, currentTarget.transform); else ability.Execute(myTag, this.transform.position + this.transform.forward); } else if (ability is AreaOfEffectAbility && !((AreaOfEffectAbility)ability).spawnUnderUser) { if (currentTarget != null) ability.Execute(myTag, currentTarget.transform); else ability.Execute(myTag, this.transform.position + this.transform.forward); } else { ability.Execute(myTag); } if (ability.cooldown > 0) abilityCooldownTracker.StartAbilityCooldown(ability); ResetCounterOnAttackPerformed(); waitingForAttackAnimation = false; SetAgentMoving(true); //Debug.Log("Attack cycle done"); } }