using Gamesmiths.Forge.Abilities; using Gamesmiths.Forge.Core; using Gamesmiths.Forge.Effects; using Gamesmiths.Forge.Godot.Resources; using Gamesmiths.Forge.Godot.Resources.Abilities; using Godot; using Movementtests.interfaces; using Movementtests.tools; namespace Movementtests.forge.abilities; public record OnProjectileSpawned(Vector3 Direction, float SpeedMultiplier, Vector3? SpawnOffset = null, uint? CollisionOverride = null); public class SpawnProjectileBehavior(PackedScene projectileScene) : IAbilityBehavior { public void OnStarted(AbilityBehaviorContext context, OnProjectileSpawned data) { if (context.Source is not Node3D source || projectileScene.Instantiate() is not Projectile projectile) { context.InstanceHandle.End(); return; } source.GetTree().GetCurrentScene().AddChild(projectile); // Computing projectile properties var offset = data.SpawnOffset ?? Vector3.Zero; var startPos = source is ITargetable targetable ? targetable.GetTargetGlobalPosition() : source.GlobalPosition; var target = context.Target as Node3D; var magnitude = context.Magnitude != 0 ? context.Magnitude : 1; var impulse = data.Direction * data.SpeedMultiplier * magnitude; var collisionOverride = data.CollisionOverride ?? projectile.CollisionMask; GD.Print(impulse); // Setting up projectile projectile.GlobalPosition = startPos + offset; projectile.Target = target; projectile.ImpulseDirection = impulse; projectile.CollisionMask = collisionOverride; if (projectile is ISpawnable spawnable) spawnable.Init(); context.AbilityHandle.CommitAbility(); context.InstanceHandle.End(); } public void OnEnded(AbilityBehaviorContext context) { } } [Tool] [GlobalClass] public partial class ForgeSpawnProjectileBehavior : ForgeAbilityBehavior { [Export] public required PackedScene Projectile { get; set; } public override IAbilityBehavior GetBehavior() => new SpawnProjectileBehavior(Projectile); }