BloodAndGore/Assets/Scripts/AI/Behaviours/ExplodeFollowed.cs

115 lines
5.1 KiB
C#

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<Enemy>();
Follow = GetComponent<Follow>();
Explodable = GetComponent<Explodable>();
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<PlayerFun>();
Health Health = Collider.GetComponent<Health>();
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);
}
}
}