using System.Collections.Generic; using Godot; using Mr.BrickAdventures.Autoloads; using Mr.BrickAdventures.scripts.Resources; namespace Mr.BrickAdventures.scripts.components; [GlobalClass] public partial class PlayerController : CharacterBody2D { [Export] private Node MovementAbilitiesContainer { get; set; } [Export] public MovementPreset DefaultPreset { get; set; } [Signal] public delegate void JumpInitiatedEventHandler(); [Signal] public delegate void MovementAbilitiesChangedEventHandler(); public Vector2 LastDirection { get; private set; } = Vector2.Right; public Vector2 PreviousVelocity { get; private set; } = Vector2.Zero; private List _abilities = []; private PlayerInputHandler _inputHandler; public IReadOnlyList GetActiveAbilities() => _abilities; public override void _Ready() { SkillManager.Instance?.RegisterPlayer(this); // Wire HealthComponent signals to global EventBus events var health = GetNodeOrNull("HealthComponent"); if (health != null) { health.Death += () => EventBus.EmitPlayerDied(GlobalPosition); health.HealthChanged += (delta, total) => { if (delta < 0f) EventBus.EmitPlayerDamaged(Mathf.Abs(delta), total, GlobalPosition); else EventBus.EmitPlayerHealed(delta, total, GlobalPosition); }; } _inputHandler = GetNode("PlayerInputHandler"); if (DefaultPreset != null) ApplyPreset(DefaultPreset); EmitSignalMovementAbilitiesChanged(); EventBus.EmitPlayerSpawned(this); } public override void _PhysicsProcess(double delta) { var velocity = Velocity; foreach (var ability in _abilities) { velocity = ability.ProcessMovement(velocity, delta); } if (_inputHandler.MoveDirection.X != 0) { LastDirection = new Vector2(_inputHandler.MoveDirection.X > 0 ? 1 : -1, 0); } PreviousVelocity = Velocity; Velocity = velocity; MoveAndSlide(); } public void ApplyPreset(MovementPreset preset) { if (preset == null) return; ClearMovementAbilities(); Velocity = Vector2.Zero; foreach (var scene in preset.Abilities) { if (scene != null) AddAbility(scene.Instantiate()); } EmitSignalMovementAbilitiesChanged(); } public void AddAbility(MovementAbility ability) { MovementAbilitiesContainer.AddChild(ability); ability.Initialize(this); _abilities.Add(ability); } public void ClearMovementAbilities() { foreach (var ability in _abilities) { ability.QueueFree(); } _abilities.Clear(); } public void RemoveAbility() where T : MovementAbility { for (var i = _abilities.Count - 1; i >= 0; i--) { if (_abilities[i] is T) { var ability = _abilities[i]; _abilities.RemoveAt(i); ability.QueueFree(); break; } } } }