using System; using Core.Extensions; using UnityEngine; using System.Collections.Generic; using Random = UnityEngine.Random; public class Enemy : Entity { [System.Serializable] public class Ability { public EnemyAbility ability; public float currentCooldown; } public static event Action OnDamaged; [Header("Targetting")] public Entity closestTarget; public float engagementRange; public bool detectedPlayer = false; [Header("Direction")] public float acceleration; public Transform[] possibleDirections; public float forwardPercent; public float strafePercent; private float xSign = -1f; private float ySign = 1f; [System.Serializable] public class UpgradeDrop { public AbilityUpgrade droppedUpgrade; public float chance; } [Header("Drops")] public List possibleDrops = new(); [SerializeField] private UpgradePickup pickupObject; [Header("Abilities")] [SerializeField] private Ability[] allAbilities; private void Start() { if (Random.Range(0f, 2f) > 1f) { xSign = -xSign; ySign = -ySign; } } private void Update() { if (detectedPlayer) { Ability foundAbility = null; foreach (Ability availableAbility in allAbilities) { if (foundAbility == null && availableAbility.currentCooldown <= 0) { foundAbility = availableAbility; } else if (availableAbility.currentCooldown > 0) { availableAbility.currentCooldown -= Time.deltaTime; } } if (foundAbility != null) { foundAbility.ability.UseAbility(closestTarget, this); foundAbility.currentCooldown = foundAbility.ability.cooldown; } } } protected override void FixedUpdate() { if (!detectedPlayer && Vector3.Distance(transform.position, closestTarget.transform.position) < engagementRange) { detectedPlayer = true; } if (stalled || !closestTarget || !detectedPlayer) { rb.VelocityTowards(Vector2.zero.ScaleToMagnitude(speed), acceleration); } else { Vector2 directionToTarget = (closestTarget.transform.position - transform.position).normalized; Vector2 directionToMove = directionToTarget; float currentHighestScore = float.NegativeInfinity; Vector2 strafeDirection = new Vector3(directionToTarget.y * ySign, directionToTarget.x * xSign); foreach (Transform direction in possibleDirections) { Vector3 directionToPoint = (direction.position - transform.position).normalized; float forwardScore = Vector3.Dot(directionToPoint, directionToTarget); float strafeScore = Vector3.Dot(directionToPoint, strafeDirection); float finalScore = (forwardScore * forwardPercent) + (strafeScore * strafePercent); //Debug.Log($"Forward: {forwardScore} Strafe: {strafeScore} Final: {finalScore}"); if (finalScore > currentHighestScore) { //Debug.Log($"{finalScore} is higher than current score: {currentHighestScore}"); currentHighestScore = finalScore; directionToMove = directionToPoint; } } rb.VelocityTowards(directionToMove.ScaleToMagnitude(speed), acceleration); FlipSprite(directionToMove); } } protected override void OnKillEffects() { Destroy(gameObject); foreach (UpgradeDrop drop in possibleDrops) { DropUpgrade(drop); } } public override void TakeDamage(float damage, Entity origin) { base.TakeDamage(damage, origin); OnDamaged?.Invoke(); } protected virtual void DropUpgrade(UpgradeDrop drop) { float random = Random.Range(0, 100); { if (random < drop.chance) //just so it matches up with the number. 80 chance means 80 percent? idk but less than 80 lol { UpgradePickup newPickup = Instantiate(pickupObject, transform.position, Quaternion.identity); newPickup.upgradeDropped = drop.droppedUpgrade; } } } }