using System; using System.Linq; using Cirno.Scripts.Components.FSM.Enemy; using Cirno.Scripts.Resources; using Cirno.Scripts.Resources.Loot; using Cirno.Scripts.Utils; using Godot; namespace Cirno.Scripts.Actors; [Tool] public partial class RogueliteEnemySpawner : Marker2D, IActivable { private EnemyResource _enemy; [Export] public EnemyResource Enemy { get => _enemy; set { _enemy = value; if (Engine.IsEditorHint()) { QueueRedraw(); } } } private bool _autoSpawn = false; [Export] public bool AutoSpawn { get => _autoSpawn; set { _autoSpawn = value; if (Engine.IsEditorHint()) { QueueRedraw(); } } } [Export] public int Wave { get; private set; } = 0; public bool Spawned { get; private set; } = false; [Export] public Path2D Path { get; private set; } [ExportToolButton("Update Icon")] public Callable RedrawButton => Callable.From(Redraw); private EnemyFSMProxy _spawnedEnemy; public override void _Draw() { if (!Engine.IsEditorHint()) return; if (Enemy is null) return; if (Enemy.IconSprite is null) return; var modulate = AutoSpawn ? new Color(1.0f, 1.0f, 1.0f, 1.0f) : new Color(1.0f, 1.0f, 1.0f, 0.5f); DrawTexture(Enemy.IconSprite, - new Vector2(_enemy.IconSprite.GetWidth() / 2f, _enemy.IconSprite.GetHeight() / 2f), modulate); } private void Redraw() { QueueRedraw(); } public override void _Ready() { if (Engine.IsEditorHint()) return; if (!AutoSpawn) return; Spawn(); } public EnemyFSMProxy Spawn() { if (Engine.IsEditorHint()) return null; if (Spawned) return _spawnedEnemy; var enemyScene = GD.Load(Enemy.PrefabPath); _spawnedEnemy = this.CreateSibling(enemyScene); _spawnedEnemy.Init(Enemy); Spawned = true; _spawnedEnemy.Death += SpawnedEnemyOnDeath; return _spawnedEnemy; } public EnemyFSMProxy Spawn(RogueliteMapTheme mapTheme) { if (Engine.IsEditorHint()) return null; if (Spawned) return _spawnedEnemy; var spawnedEnemy = Spawn(); spawnedEnemy.OverrideLoot = true; spawnedEnemy.ExtraLoot.Add(new LootDrop() { Item = mapTheme.EnemiesLootTable.Items.ToList().Shuffle().First(), Chance = mapTheme.EnemyDropChance }); spawnedEnemy.ExtraLoot.Add(new LootDrop() { Item = mapTheme.PointItemResource, Chance = 100 }); return spawnedEnemy; } private void SpawnedEnemyOnDeath(EnemyFSMProxy enemy) { _spawnedEnemy.Death -= SpawnedEnemyOnDeath; _spawnedEnemy = null; Spawned = false; } public bool Activate(ActivationType activationType = ActivationType.Toggle) { switch (activationType) { case ActivationType.Toggle: Spawn(); break; case ActivationType.Enable: break; case ActivationType.Disable: break; case ActivationType.Use: break; case ActivationType.Destroy: break; case ActivationType.Open: break; case ActivationType.Close: break; default: throw new ArgumentOutOfRangeException(nameof(activationType), activationType, null); } return true; } public void Toggle() { this.Activate(); } }