using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// GAME 1303 Tier 2 — A bullet, arrow, fireball, or spit-glob.
///
/// SETUP (make this a prefab)
/// - Sprite + Rigidbody2D (Gravity Scale 0 for straight shots, >0 for lobbed arrows)
/// + Collider2D (Is Trigger ON) + this script.
/// - Team is set by whoever fires it (ProjectileShooter does this).
/// - Hits: Hurtboxes on the other team take Damage; hitting Ground layer destroys it.
/// - Pierce: 0 = destroyed on first hit; 2 = passes through two enemies first.
///
/// Sorcerer's elemental bolts, Blaster's shots, MythoClash's hydra spit and
/// Stardust's buster all use the same script with different sprites/speeds.
/// </summary>
[RequireComponent(typeof(Rigidbody2D), typeof(Collider2D))]
public class Projectile : MonoBehaviour
{
public int damage = 1;
public float speed = 12f;
public float lifetime = 3f;
[Tooltip("How many hurtboxes it can pass through before dying.")]
public int pierce = 0;
public float knockbackForce = 3f;
public float knockbackUpward = 1f;
[Tooltip("Layers that stop the projectile (walls, ground).")]
public LayerMask blockingLayers;
[Tooltip("Rotate sprite to face travel direction (arrows). Off for round bullets.")]
public bool faceDirection = true;
[Header("Effects")]
public GameObject impactEffectPrefab;
public UnityEvent<Hurtbox> OnHit; // ComboCounter.RegisterHit for player shots
[HideInInspector] public Team team = Team.Player;
[HideInInspector] public ComboCounter comboSource; // set by shooter if player
private Rigidbody2D rb;
private int hitsLeft;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
GetComponent<Collider2D>().isTrigger = true;
}
/// <summary>Called by ProjectileShooter right after Instantiate.</summary>
public void Launch(Vector2 direction, Team owner, ComboCounter combo = null)
{
team = owner;
comboSource = combo;
hitsLeft = pierce + 1;
rb.linearVelocity = direction.normalized * speed;
if (faceDirection)
transform.rotation = Quaternion.Euler(0f, 0f, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg);
Destroy(gameObject, lifetime);
}
void OnTriggerEnter2D(Collider2D other)
{
// Wall?
if ((blockingLayers.value & (1 << other.gameObject.layer)) != 0)
{
Impact();
return;
}
Hurtbox hb = other.GetComponent<Hurtbox>();
if (hb == null) return;
if (hb.team == team) return; // don't hit friends
if (hb.team == Team.Neutral || hb.team != team)
{
int dmg = damage;
if (comboSource != null) dmg = Mathf.RoundToInt(damage * comboSource.DamageMultiplier);
if (hb.ReceiveHit(dmg, transform.position, knockbackForce, knockbackUpward))
{
OnHit?.Invoke(hb);
comboSource?.RegisterHit();
hitsLeft--;
if (hitsLeft <= 0) Impact();
}
}
}
void Impact()
{
if (impactEffectPrefab != null)
Instantiate(impactEffectPrefab, transform.position, Quaternion.identity);
Destroy(gameObject);
}
}