using OTG.Lab06.Abilities; using OTG.Lab06.Core; using UnityEngine; namespace OTG.Lab06.Effects { [RequireComponent(typeof(Collider))] public sealed class FireballEffect : AbilityEffect { [SerializeField] private float speed = 18f; [SerializeField] private float lifeTime = 4f; [SerializeField] private LayerMask hitMask = ~0; private AbilityCastContext context; private Vector3 direction; private float remainingLife; private bool activated; public override void Activate(AbilityCastContext context) { this.context = context; direction = context.Forward; remainingLife = Mathf.Min(lifeTime, Mathf.Max(0.5f, context.Ability.castRange / Mathf.Max(1f, speed))); activated = true; transform.position = context.Origin + direction * 0.9f; transform.rotation = Quaternion.LookRotation(direction, Vector3.up); } private void Awake() { Collider ownCollider = GetComponent(); ownCollider.isTrigger = true; } private void Update() { if (!activated) { return; } float step = speed * Time.deltaTime; if (Physics.Raycast(transform.position, direction, out RaycastHit hit, step, hitMask, QueryTriggerInteraction.Ignore)) { ApplyHit(hit.collider); return; } transform.position += direction * step; remainingLife -= Time.deltaTime; if (remainingLife <= 0f) { Destroy(gameObject); } } private void OnTriggerEnter(Collider other) { if (!activated || other.transform == context.Caster) { return; } ApplyHit(other); } private void ApplyHit(Collider hitCollider) { if (hitCollider.transform == context.Caster || hitCollider.GetComponentInParent() != null) { return; } IDamageable damageable = hitCollider.GetComponentInParent(); if (damageable != null && damageable.IsAlive) { damageable.TakeDamage(context.Ability.damage); } Destroy(gameObject); } } }