using UnityEngine; using Saltosion.OneWeapon.Enemies; using Saltosion.OneWeapon.Effects; using Saltosion.OneWeapon.Player; namespace Saltosion.OneWeapon.AI.Behaviours { [RequireComponent(typeof(Follow), typeof(Enemy), typeof(Explodable))] public class ExplodeFollowed : AIBehaviour { public float StartExplodingRadius; public float ExplodeOnImpactRadius; public float ExplosionRadius; public float FuseDuration; [Tooltip("The amount of damage when barely in the explosion radius")] public float MinDamage; [Tooltip("The amount of damage when in impact radius")] public float MaxDamage; [Header("Graphics")] public SpriteRenderer SpriteRenderer; public Transform ExplosionAnimationTransform; public float ExplosionAnimationDuration; public float BlinkingRate; private Enemy Enemy; private Follow Follow; private Explodable Explodable; private float OriginalFollowPositionUpdateFrequency; private bool Exploding = false; private float FuseStartTime; private bool ExplosionStarted = false; private float ExplosionProgress = 0.0f; private void Start() { Enemy = GetComponent(); Follow = GetComponent(); Explodable = GetComponent(); OriginalFollowPositionUpdateFrequency = Follow.TargetPositionUpdateFrequency; } public override bool CanBehave() { return true; } public override void Execute() { float Distance = Follow.Target != null ? (Follow.Target.position - transform.position).magnitude : float.PositiveInfinity; bool ImpactExplode = Distance <= ExplodeOnImpactRadius; bool TimeExplode = Exploding && Time.time - FuseStartTime >= FuseDuration; if (!ExplosionStarted && (ImpactExplode || TimeExplode)) { ExplosionStarted = true; CurrentStatus = "BOOM"; } else if (Distance <= StartExplodingRadius && !Exploding) { Exploding = true; FuseStartTime = Time.time; Follow.SetUpdateFrequency(OriginalFollowPositionUpdateFrequency / 3f); CurrentStatus = "CloseEnoughNow"; } else if (Exploding) { CurrentStatus = "Exploding: " + (Time.time - FuseStartTime).ToString("0.0") + " > " + FuseDuration.ToString("0.0"); } else { CurrentStatus = "NotCloseEnough"; } // Animation if (ExplosionStarted) { if (ExplosionProgress >= 1.0f) { Explode(Distance); } else { ExplosionProgress += Time.deltaTime / ExplosionAnimationDuration; float AnimMidpoint = 0.5f; if (ExplosionProgress < AnimMidpoint) { float MinifyProgress = ExplosionProgress / AnimMidpoint; ExplosionAnimationTransform.localScale = new Vector3(1, 1, 1) * (1.0f - MinifyProgress * 0.5f); } else { float ExpansionProgress = (ExplosionProgress - AnimMidpoint) / (1.0f - AnimMidpoint); ExplosionAnimationTransform.localScale = new Vector3(1, 1, 1) * (0.5f + ExpansionProgress); } } } if (Exploding) { float Intensity = Mathf.Sin(Time.time * Mathf.PI * 2.0f * BlinkingRate) * 0.5f + 0.5f; SpriteRenderer.material.SetFloat("_Intensity", Intensity); } else { SpriteRenderer.material.SetFloat("_Intensity", 0.0f); } } private void OnDrawGizmosSelected() { Gizmos.color = new Color(1.0f, 0.2f, 0.2f, 0.8f); Gizmos.DrawWireSphere(transform.position, ExplodeOnImpactRadius); Gizmos.color = new Color(1.0f, 0.0f, 0.0f, 1.0f); Gizmos.DrawWireSphere(transform.position, ExplosionRadius); Gizmos.color = new Color(1.0f, 0.5f, 0.5f, 0.5f); Gizmos.DrawWireSphere(transform.position, StartExplodingRadius); } private void Explode(float distance) { Collider2D[] NearbyColliders = Physics2D.OverlapCircleAll(transform.position, ExplosionRadius); foreach (Collider2D Collider in NearbyColliders) { PlayerFun PlayerFun = Collider.GetComponent(); Health Health = Collider.GetComponent(); if (PlayerFun != null) { PlayerFun.TakeExplosionDamage(); } if (Health != null) { float ScaledDistance = Mathf.Clamp((distance - ExplodeOnImpactRadius) / (ExplosionRadius - ExplodeOnImpactRadius), 0, 1); float Damage = MinDamage + (MaxDamage - MinDamage) * (1.0f - ScaledDistance); Vector2 Direction = (Collider.transform.position - transform.position).normalized; Health.Damage(Damage, Direction, false); } } Explodable.Explode(true); } } }