godot-4.5 (#5)
Reviewed-on: #5
This commit was merged in pull request #5.
This commit is contained in:
46
scripts/components/CleanupOnCollisionComponent.cs
Normal file
46
scripts/components/CleanupOnCollisionComponent.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class CleanupOnCollisionComponent : Node
|
||||
{
|
||||
[Export(PropertyHint.Range, "0, 5, 0.1")] public float CleanupDelay { get; set; } = 0.5f;
|
||||
|
||||
private RigidBody2D _body;
|
||||
private CleanupComponent _cleanupComponent;
|
||||
private bool _isCleaningUp = false;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_body = Owner as RigidBody2D;
|
||||
if (_body == null)
|
||||
{
|
||||
GD.PrintErr("CleanupOnCollisionComponent must be attached to a RigidBody2D.");
|
||||
SetProcess(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_cleanupComponent = Owner.GetNode<CleanupComponent>("CleanupComponent");
|
||||
if (_cleanupComponent == null)
|
||||
{
|
||||
GD.PrintErr("CleanupOnCollisionComponent requires a CleanupComponent on the same node.");
|
||||
SetProcess(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_body.BodyEntered += (_) => OnBodyEntered();
|
||||
}
|
||||
|
||||
private async void OnBodyEntered()
|
||||
{
|
||||
if (_isCleaningUp) return;
|
||||
|
||||
_isCleaningUp = true;
|
||||
|
||||
await ToSignal(GetTree().CreateTimer(CleanupDelay), Timer.SignalName.Timeout);
|
||||
|
||||
_cleanupComponent?.CleanUp();
|
||||
}
|
||||
|
||||
}
|
||||
1
scripts/components/CleanupOnCollisionComponent.cs.uid
Normal file
1
scripts/components/CleanupOnCollisionComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://chusyr5vwgwf0
|
||||
@@ -9,14 +9,20 @@ namespace Mr.BrickAdventures.scripts.components;
|
||||
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; }
|
||||
|
||||
[Export] public AudioStreamPlayer2D Sfx { get; set; }
|
||||
|
||||
[Signal] public delegate void CollectedEventHandler(float amount, CollectableType type, Node2D body);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for checking if collection should be allowed.
|
||||
/// Return false to prevent collection.
|
||||
/// </summary>
|
||||
public Func<Node2D, bool> CanCollect { get; set; }
|
||||
|
||||
private FloatingTextManager _floatingTextManager;
|
||||
|
||||
public override void _Ready()
|
||||
@@ -25,10 +31,10 @@ public partial class CollectableComponent : Node
|
||||
Area2D.BodyEntered += OnArea2DBodyEntered;
|
||||
else
|
||||
GD.PushError("Collectable node missing Area2D node.");
|
||||
|
||||
|
||||
if (Owner.HasNode("FadeAwayComponent"))
|
||||
_hasFadeAway = true;
|
||||
|
||||
|
||||
_floatingTextManager = GetNode<FloatingTextManager>("/root/FloatingTextManager");
|
||||
}
|
||||
|
||||
@@ -38,6 +44,9 @@ public partial class CollectableComponent : Node
|
||||
{
|
||||
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)
|
||||
@@ -53,13 +62,13 @@ public partial class CollectableComponent : Node
|
||||
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();
|
||||
|
||||
47
scripts/components/FallOnDetectionComponent.cs
Normal file
47
scripts/components/FallOnDetectionComponent.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class FallOnDetectionComponent : Node2D
|
||||
{
|
||||
[Export] public Area2D DetectionArea { get; set; }
|
||||
[Export] public RigidBody2D TargetBody { get; set; }
|
||||
[Export] public float FallDelay { get; set; } = 0.2f;
|
||||
|
||||
private bool _hasTriggered = false;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
if (DetectionArea == null)
|
||||
{
|
||||
GD.PrintErr("FallOnDetectionComponent: DetectionArea is not set.");
|
||||
SetProcess(false);
|
||||
return;
|
||||
}
|
||||
if (TargetBody == null)
|
||||
{
|
||||
GD.PrintErr("FallOnDetectionComponent: TargetBody is not set.");
|
||||
SetProcess(false);
|
||||
return;
|
||||
}
|
||||
|
||||
DetectionArea.BodyEntered += OnBodyEntered;
|
||||
}
|
||||
|
||||
private async void OnBodyEntered(Node2D body)
|
||||
{
|
||||
if (_hasTriggered) return;
|
||||
_hasTriggered = true;
|
||||
|
||||
if (FallDelay > 0)
|
||||
{
|
||||
await ToSignal(GetTree().CreateTimer(FallDelay), Timer.SignalName.Timeout);
|
||||
}
|
||||
|
||||
if (IsInstanceValid(TargetBody))
|
||||
{
|
||||
TargetBody.GravityScale = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
scripts/components/FallOnDetectionComponent.cs.uid
Normal file
1
scripts/components/FallOnDetectionComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://co05ugnvx0v3e
|
||||
@@ -16,16 +16,27 @@ public partial class HealComponent : Node
|
||||
GD.PushError("HealComponent: Collectable is not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Register check to prevent collecting when at full health
|
||||
Collectable.CanCollect = CanCollectHealth;
|
||||
Collectable.Collected += OnCollected;
|
||||
}
|
||||
|
||||
private bool CanCollectHealth(Node2D body)
|
||||
{
|
||||
var healthComponent = body.GetNodeOrNull<HealthComponent>("HealthComponent");
|
||||
if (healthComponent == null) return true; // Allow collection if no health component
|
||||
|
||||
// Prevent collection if already at full health
|
||||
return healthComponent.Health < healthComponent.MaxHealth;
|
||||
}
|
||||
|
||||
private void OnCollected(float amount, CollectableType type, Node2D body)
|
||||
{
|
||||
if (type != CollectableType.Health) return;
|
||||
|
||||
if (Collectable == null) return;
|
||||
|
||||
|
||||
var healthComponent = body.GetNodeOrNull<HealthComponent>("HealthComponent");
|
||||
if (healthComponent == null) return;
|
||||
|
||||
@@ -34,14 +45,14 @@ public partial class HealComponent : Node
|
||||
{
|
||||
PlayHealFx();
|
||||
}
|
||||
|
||||
|
||||
Owner.QueueFree();
|
||||
}
|
||||
|
||||
private void PlayHealFx()
|
||||
{
|
||||
if (HealFx == null) return;
|
||||
|
||||
|
||||
HealFx.Restart();
|
||||
HealFx.Emitting = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user