using Godot; using GodotHostTest.Interfaces; using OwofGames.AetherBind; using R3; namespace GodotHostTest.Game.Target; public partial class Target : Node2D, ITarget { private readonly Subject _hit = new(); private readonly Subject _timedOut = new(); [Export] public required Area2D CollisionArea; [Export] public required Sprite2D Image; [Export] public required Timer TimeOutTimer; [Export] private PackedScene _explosionPackedScene = null!; [Inject] private ILevel _level = null!; [Inject] private ITargetCollector _targetCollector = null!; public Observable TimedOut => _timedOut.AsObservable(); public Observable Hit => _hit.AsObservable(); public void Enable() { Image.Visible = true; CollisionArea.Monitoring = true; CollisionArea.Monitorable = true; TimeOutTimer.Start(_level.SpawnDuration.TotalSeconds); } private void Disable() { Image.Visible = false; // can't set monitoring/monitorable when inside collision code, like during OnHit, so let's call them deferred CollisionArea.SetDeferred(Area2D.PropertyName.Monitoring, false); CollisionArea.SetDeferred(Area2D.PropertyName.Monitorable, false); TimeOutTimer.Stop(); } public override void _Ready() { _targetCollector.NewTarget(this); } protected override void Dispose(bool disposing) { base.Dispose(disposing); _timedOut.Dispose(); _hit.Dispose(); } private void OnAreaEntered(Area2D _) { Disable(); _hit.OnNext(Unit.Default); var explosion = (GpuParticles2D)_explosionPackedScene.Instantiate(); explosion.GlobalPosition = GlobalPosition; explosion.Emitting = true; GetTree().CurrentScene.AddChild(explosion); } private void OnTimeout() { Disable(); _timedOut.OnNext(Unit.Default); } }