using System; using Godot; using Mr.BrickAdventures; using Mr.BrickAdventures.Autoloads; using Mr.BrickAdventures.scripts.Resources; namespace Mr.BrickAdventures.scripts.components; [GlobalClass] public partial class CollectableComponent : Node { private bool _hasFadeAway = false; [Export] public Area2D Area2D { get; set; } [Export] public CollisionShape2D CollisionShape { get; set; } [Export] public CollectableResource Data { get; set; } [Export] public AudioStreamPlayer2D Sfx { get; set; } [Signal] public delegate void CollectedEventHandler(float amount, CollectableType type, Node2D body); /// /// Delegate for checking if collection should be allowed. /// Return false to prevent collection. /// public Func CanCollect { get; set; } public override void _Ready() { if (Area2D != null) Area2D.BodyEntered += OnArea2DBodyEntered; else GD.PushError("Collectable node missing Area2D node."); if (Owner.HasNode("FadeAwayComponent")) _hasFadeAway = true; } private async void OnArea2DBodyEntered(Node2D body) { try { if (!body.HasNode("CanPickUpComponent")) return; // Allow components to veto collection (e.g., full health for potions) if (CanCollect != null && !CanCollect(body)) return; if (Owner is Node2D ownerNode) { switch (Data.Type) { case CollectableType.Coin: FloatingTextManager.Instance?.ShowCoin((int)Data.Amount, ownerNode.GlobalPosition); EventBus.EmitCoinCollected((int)Data.Amount, ownerNode.GlobalPosition); break; case CollectableType.Health: FloatingTextManager.Instance?.ShowMessage("Healed!", ownerNode.GlobalPosition); EventBus.EmitItemCollected(Data.Type, Data.Amount, ownerNode.GlobalPosition); break; case CollectableType.Kid: FloatingTextManager.Instance?.ShowMessage("Rescued!", ownerNode.GlobalPosition); EventBus.EmitChildRescued(ownerNode.GlobalPosition); break; case CollectableType.Skill: if (Data.Skill != null) { FloatingTextManager.Instance?.ShowMessage($"{Data.Skill.Name} Unlocked!", ownerNode.GlobalPosition); EventBus.EmitSkillCollected(Data.Skill, ownerNode.GlobalPosition); } break; default: EventBus.EmitItemCollected(Data.Type, Data.Amount, ownerNode.GlobalPosition); break; } } EmitSignalCollected(Data.Amount, Data.Type, body); CollisionShape?.CallDeferred("set_disabled", true); Sfx?.Play(); if (_hasFadeAway) return; if (Sfx != null) await ToSignal(Sfx, AudioStreamPlayer2D.SignalName.Finished); Owner.QueueFree(); } catch (Exception e) { GD.PushError($"Error in CollectableComponent.OnArea2DBodyEntered: {e.Message}"); } } }