// Player.cs - Complete working version using Godot; using System; using System.Collections.Generic; namespace TextRPG.PlayerSystem { public partial class Player : Node { // ---------- Singleton Pattern ---------- private static Player _instance; public static Player Instance => _instance; // ---------- Signals ---------- [Signal] public delegate void HealthChangedEventHandler(int currentHealth, int maxHealth); [Signal] public delegate void PlayerDiedEventHandler(); [Signal] public delegate void InventoryChangedEventHandler(); // ---------- Attributes ---------- public int MaxHealth { get; set; } = 100; private int _currentHealth; public int CurrentHealth { get => _currentHealth; set { int newHealth = Math.Clamp(value, 0, MaxHealth); if (_currentHealth != newHealth) { _currentHealth = newHealth; EmitSignal(SignalName.HealthChanged, _currentHealth, MaxHealth); if (_currentHealth <= 0) EmitSignal(SignalName.PlayerDied); } } } public int Strength { get; set; } = 10; public int Dexterity { get; set; } = 10; public int Intelligence { get; set; } = 10; // ---------- Inventory ---------- public List Inventory { get; private set; } = new List(); // ---------- Lifecycle ---------- public override void _EnterTree() { if (_instance != null) { GD.Print("Duplicate Player instance detected. Removing."); QueueFree(); } else { _instance = this; GD.Print("Player singleton initialized."); } } public override void _Ready() { _currentHealth = MaxHealth; } // ---------- Public Methods ---------- public void TakeDamage(int amount) { CurrentHealth -= amount; } public void Heal(int amount) { CurrentHealth += amount; } public void AddItem(Item item) { Inventory.Add(item); EmitSignal(SignalName.InventoryChanged); } public bool RemoveItem(Item item) { bool removed = Inventory.Remove(item); if (removed) EmitSignal(SignalName.InventoryChanged); return removed; } public bool HasItem(string itemName) { return Inventory.Exists(i => i.Name.Equals(itemName, StringComparison.OrdinalIgnoreCase)); } public Item GetItem(string itemName) { return Inventory.Find(i => i.Name.Equals(itemName, StringComparison.OrdinalIgnoreCase)); } public string GetStatusString() { return $"Health: {CurrentHealth}/{MaxHealth}\n" + $"Strength: {Strength} Dexterity: {Dexterity} Intelligence: {Intelligence}\n" + $"Inventory: {Inventory.Count} items"; } public string GetInventoryString() { if (Inventory.Count == 0) return "Your inventory is empty."; var lines = new List { "=== Inventory ===" }; foreach (var item in Inventory) lines.Add($"- {item.Name}: {item.Description}"); return string.Join("\n", lines); } } }