using Cirno.Scripts.AttackPatterns; using Cirno.Scripts.Utils; using Godot; namespace Cirno.Scripts.Resources.BulletScripts; [GlobalClass] [Tool] public partial class SimpleMovementPattern3D : AttackPattern { [Export] private Vector2 relativeTargetPosition; [Export] private float moveDuration = 2f; [Export] public bool RelativeToPlayer { get; private set; } [Export] private Tween.TransitionType transitionType = Tween.TransitionType.Linear; [Export] private Tween.EaseType easeType = Tween.EaseType.InOut; public override IPatternMachine MakeMachine(Node parent) { return new SimpleMovementPatternMachine(this, parent); } public class SimpleMovementPatternMachine(SimpleMovementPattern3D pattern, Node parent) : IPatternMachine { public Node Parent => parent; private Tween tween; private bool isComplete = false; protected IScriptHost3D Boss; public void Start() { if (parent is not IScriptHost3D boss) return; Boss = boss; tween = Parent.CreateTween(); isComplete = false; // Vector2 targetPosition = (Boss?.HomePosition.ToVector2() ?? boss.ParentObject.GlobalPosition.ToVector2()) + pattern.relativeTargetPosition; var offset = pattern.relativeTargetPosition; var targetPosition = (Boss?.HomePosition.ToVector2() ?? boss.ParentObject.GlobalPosition.ToVector2()); if (pattern.RelativeToPlayer && GameController.Instance.PlayerPosition.HasValue) { var bossPos2D = boss.ParentObject.GlobalPosition.ToVector2(); var playerPos2D = GameController.Instance.PlayerPosition.Value.ToVector2(); var toPlayer = (playerPos2D - bossPos2D).Normalized(); var left = new Vector2(-toPlayer.Y, toPlayer.X); // Perpendicular toPlayer (left) // Transform the relative offset into the rotated coordinate space Vector2 transformedOffset = toPlayer * offset.Y + left * offset.X; targetPosition += transformedOffset; } else { // Apply default offset from home targetPosition += offset; } var targetPosition3D = targetPosition.ToVector3(boss.ParentObject.GlobalPosition.Y); boss.ChangeSpriteDirection(-(boss.ParentObject.GlobalPosition.ToVector2() - targetPosition)); tween.TweenProperty(boss.ParentObject, "global_position", targetPosition3D, pattern.moveDuration) .SetTrans(pattern.transitionType) .SetEase(pattern.easeType) .Finished += () => { isComplete = true; boss.ChangeSpriteDirection(Vector2.Zero); }; } public void UpdatePattern(double delta) { } public bool IsComplete() { return isComplete; } } }