using UnityEngine; public class ProjectileExecutionBehavior : RuntimeBehavior { [Header("Projectile Settings")] public GameObject projectilePrefab; public float projectileSpeed = 15f; public float lifeSpan = 1.5f; public bool canPierce = false; public bool canHitSelf = false; [Header("Movement Behaviour")] public AnimationCurve speedOverLifetime = AnimationCurve.Linear(0, 1, 1, 1); public bool useSpeedCurve = false; public bool enableCurving = false; public Vector3 curveAxis = Vector3.up; public float curveStrength = 1f; public float curveAmplitude = 45f; public bool enableRicochet = false; public int maxRicochets = 1; public float ricochetSpread = 10f; public ProjectileExecutionBehavior() { Trigger = BehaviorTrigger.Execute; // This replaces your Execute() override BehaviorName = "Projectile Execution"; } public override void Execute(RuntimeAbilityInstance ability, Taggable user, Transform target, Vector3 point) { // This is your old ProjectileAbility.Execute() logic! // Get spawn location var spawnController = user.GetComponentInChildren(); Vector3 spawnPos = spawnController?.transform.position ?? user.transform.position; Quaternion spawnRot = spawnController?.transform.rotation ?? user.transform.rotation; // Spawn projectile var projectileGO = Object.Instantiate(projectilePrefab, spawnPos, spawnRot); // Setup projectile var networkedProjectile = projectileGO.GetComponent(); if (networkedProjectile != null) { SetupProjectileInstance(ability, networkedProjectile, user); networkedProjectile.Init(); } } protected virtual void SetupProjectileInstance(RuntimeAbilityInstance ability, NetworkedProjectile networkedProjectile, Taggable user) { networkedProjectile.speed = projectileSpeed; networkedProjectile.ownerTag = user; networkedProjectile.ability = ability.SourceAbility; networkedProjectile.lifeSpan = lifeSpan; networkedProjectile.canPierce = canPierce; networkedProjectile.canHitSelf = canHitSelf; networkedProjectile.speedOverLifetime = speedOverLifetime; networkedProjectile.useSpeedCurve = useSpeedCurve; networkedProjectile.enableCurving = enableCurving; networkedProjectile.curveAxis = curveAxis; networkedProjectile.curveStrength = curveStrength; networkedProjectile.curveAmplitude = curveAmplitude; networkedProjectile.enableRicochet = enableRicochet; networkedProjectile.maxRicochets = maxRicochets; networkedProjectile.ricochetSpread = ricochetSpread; } public override RuntimeBehavior Clone() { return new ProjectileExecutionBehavior { // Basic settings projectilePrefab = this.projectilePrefab, projectileSpeed = this.projectileSpeed, lifeSpan = this.lifeSpan, canPierce = this.canPierce, canHitSelf = this.canHitSelf, // Movement behavior speedOverLifetime = this.speedOverLifetime, useSpeedCurve = this.useSpeedCurve, enableCurving = this.enableCurving, curveAxis = this.curveAxis, curveStrength = this.curveStrength, curveAmplitude = this.curveAmplitude, enableRicochet = this.enableRicochet, maxRicochets = this.maxRicochets, ricochetSpread = this.ricochetSpread }; } // ======================================================================== // FACTORY METHODS - Easy Creation of Common Projectile Types // ======================================================================== /// /// Create a simple straight projectile /// public static ProjectileExecutionBehavior CreateSimple(GameObject prefab, float speed = 15f, float lifeSpan = 5f) { return new ProjectileExecutionBehavior { projectilePrefab = prefab, projectileSpeed = speed, lifeSpan = lifeSpan }; } /// /// Create a piercing projectile /// public static ProjectileExecutionBehavior CreatePiercing(GameObject prefab, float speed = 15f, float lifeSpan = 5f) { return new ProjectileExecutionBehavior { projectilePrefab = prefab, projectileSpeed = speed, lifeSpan = lifeSpan, canPierce = true }; } /// /// Create a curved projectile (like magic missile) /// public static ProjectileExecutionBehavior CreateCurved(GameObject prefab, float speed = 12f, float curveStrength = 2f) { return new ProjectileExecutionBehavior { projectilePrefab = prefab, projectileSpeed = speed, enableCurving = true, curveStrength = curveStrength, curveAmplitude = 30f }; } /// /// Create a ricochet projectile /// public static ProjectileExecutionBehavior CreateRicochet(GameObject prefab, int maxBounces = 3, float speed = 15f) { return new ProjectileExecutionBehavior { projectilePrefab = prefab, projectileSpeed = speed, enableRicochet = true, maxRicochets = maxBounces, ricochetSpread = 15f }; } /// /// Create a projectile with speed curve (accelerating/decelerating) /// public static ProjectileExecutionBehavior CreateWithSpeedCurve(GameObject prefab, AnimationCurve curve, float baseSpeed = 15f) { return new ProjectileExecutionBehavior { projectilePrefab = prefab, projectileSpeed = baseSpeed, useSpeedCurve = true, speedOverLifetime = curve }; } public static ProjectileExecutionBehavior CreateIceshardLikeWithCurve(GameObject prefab, float baseSpeed = 15f) { return new ProjectileExecutionBehavior { projectilePrefab = prefab, projectileSpeed = baseSpeed, useSpeedCurve = true, lifeSpan = 1f, speedOverLifetime = GameConstants.BehaviorUtils.GetIceshardProjectileCurve() }; } }