75 lines
2.8 KiB
C#
75 lines
2.8 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using Invector;
|
|
|
|
namespace Beyond
|
|
{
|
|
[CreateAssetMenu(menuName = "Magic/Spells/Projectile (Fireball)")]
|
|
public class ProjectileSpell : SpellDefinition
|
|
{
|
|
[Header("Projectile Settings")]
|
|
public GameObject projectilePrefab;
|
|
public float spawnDelay = 0.2f;
|
|
public float lifeTime = 10f;
|
|
|
|
[Header("Spawn Adjustments")]
|
|
[Tooltip("Position relative to Player Root. X=Right, Y=Up, Z=Forward.\nExample: (0, 1.5, 1.0) is Chest Height, 1m forward.")]
|
|
public Vector3 spawnOffset = new Vector3(0f, 1.5f, 1.0f);
|
|
|
|
[Tooltip("Offset for aiming logic only. Usually slightly higher than the target's pivot.")]
|
|
public float aimHeightOffset = 0.75f;
|
|
|
|
public override void Cast(MagicAttacks caster, Transform target)
|
|
{
|
|
caster.StartCoroutine(CastRoutine(caster, target));
|
|
}
|
|
|
|
private IEnumerator CastRoutine(MagicAttacks caster, Transform target)
|
|
{
|
|
// 1. Rotate
|
|
yield return caster.RotateTowardsTargetRoutine(target, rotationDuration);
|
|
|
|
// 2. Wait
|
|
float remainingDelay = spawnDelay - rotationDuration;
|
|
if (remainingDelay > 0) yield return new WaitForSeconds(remainingDelay);
|
|
|
|
// 3. Calculate Spawn Position (Relative to Player)
|
|
// TransformPoint converts local (Offset) to world space based on Player position/rotation
|
|
Vector3 spawnPos = caster.transform.TransformPoint(spawnOffset);
|
|
|
|
// 4. Calculate Rotation (Aiming)
|
|
Quaternion spawnRot = caster.transform.rotation; // Default forward
|
|
|
|
if (target != null)
|
|
{
|
|
Vector3 targetPos = target.position;
|
|
targetPos.y += aimHeightOffset;
|
|
Vector3 aimDir = (targetPos - spawnPos).normalized;
|
|
|
|
// Slight arc adjustment
|
|
aimDir.y += 0.1f;
|
|
|
|
if (aimDir.sqrMagnitude > 0.001f)
|
|
spawnRot = Quaternion.LookRotation(aimDir);
|
|
}
|
|
|
|
// 5. Instantiate
|
|
GameObject obj = Instantiate(projectilePrefab, spawnPos, spawnRot);
|
|
|
|
// 6. Ignore Collision with Caster (Crucial!)
|
|
Collider projectileCollider = obj.GetComponentInChildren<Collider>();
|
|
Collider playerCollider = caster.GetComponent<Collider>();
|
|
|
|
if (projectileCollider != null && playerCollider != null)
|
|
{
|
|
Physics.IgnoreCollision(projectileCollider, playerCollider);
|
|
}
|
|
|
|
// 7. Register Events & Modifiers
|
|
caster.RegisterSpellDamageEvents(obj, this);
|
|
caster.ApplyDamageModifiers(obj);
|
|
|
|
Destroy(obj, lifeTime);
|
|
}
|
|
}
|
|
} |