using System.Linq; using Godot; using MaxEffort.Code.Core; using MaxEffort.Code.Data; namespace MaxEffort.Code.Systems; [GlobalClass] public partial class HazardSystem : Node { [Export] private Godot.Collections.Array _possibleHazards; [Export] private Godot.Collections.Array _spawnLocations; [Export] private PackedScene _hazardPrefab; // The visual object to spawn [Export] private float _checkInterval = 1.0f; // How often to try spawning private float _currentFocus = 0f; private double _timer = 0; private RandomNumberGenerator _rng = new(); public override void _Ready() { EventBus.OnFocusChanged += OnFocusChanged; EventBus.OnHazardResolved += OnHazardResolved; } public override void _ExitTree() { EventBus.OnFocusChanged -= OnFocusChanged; EventBus.OnHazardResolved -= OnHazardResolved; } public override void _Process(double delta) { _timer += delta; if (_timer >= _checkInterval) { _timer = 0; TrySpawnHazard(); } } public void SetAvailableHazards(Godot.Collections.Array hazards) { if (_possibleHazards == null) _possibleHazards = []; _possibleHazards.Clear(); foreach(var h in hazards) _possibleHazards.Add(h); } public void ClearHazards() { if (_spawnLocations == null) return; // Loop through all locations and destroy active hazards foreach (var loc in _spawnLocations) { foreach (Node child in loc.GetChildren()) { child.QueueFree(); } } _timer = 0; } private void OnFocusChanged(float focus) { _currentFocus = focus; } private void TrySpawnHazard() { if (_currentFocus < 0.2f) return; var spawnChance = _currentFocus * 0.5f; if (_rng.Randf() < spawnChance) { SpawnRandomHazard(); } } private void SpawnRandomHazard() { if (_possibleHazards.Count == 0 || _hazardPrefab == null || _spawnLocations.Count == 0) return; var emptyLocations = _spawnLocations.Where(loc => loc.GetChildCount() == 0).ToArray(); if (emptyLocations.Length == 0) return; var targetLoc = emptyLocations[_rng.Randi() % emptyLocations.Length]; var validHazards = _possibleHazards .Where(h => h.MinFocusToSpawn <= _currentFocus) .ToArray(); if (validHazards.Length == 0) return; var selected = validHazards[_rng.Randi() % validHazards.Length]; if (_hazardPrefab.Instantiate() is HazardController instance) { instance.Position = Vector2.Zero; targetLoc.AddChild(instance); instance.Initialize(selected); EventBus.PublishHazardSpawned(selected.Type); } } private void OnHazardResolved(HazardType type) { GD.Print($"Resolved {type}!"); } }