cirnogodot/Scenes/Barrel.cs
2025-02-21 16:27:57 +01:00

147 lines
3.3 KiB
C#

using Godot;
using System;
using System.Diagnostics;
using Cirno.Scripts;
using Cirno.Scripts.Resources;
public partial class Barrel : Area2D, IDestructible
{
[Export] public float Health = 1f;
[Export] public float ExplosionRadius = 1;
[Export] public float ExplosionDamage = 1;
[Export] public PackedScene DebrisScene { get; set; }
[Export] public PackedScene ExplosionParticles { get; set; }
[Export] public BulletResource ExplosionData { get; set; }
[Export] public BulletOwner BulletGroup { get; set; } = BulletOwner.None;
[ExportCategory("On Death Activation")]
[Export]
public ActivationType ActivationType { get; private set; } = ActivationType.Toggle;
[Export]
public Node2D Target { get; private set;}
[Signal]
public delegate void ExplodedEventHandler();
private GameManager _gameManager;
private float _currentHealth = 0f;
private bool _isDestroyed = false;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_gameManager = this.GetGameManager();
_currentHealth = Health;
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
}
private void Explode()
{
//ApplyExplosionDamage();
EmitSignal(SignalName.Exploded, this, _currentHealth);
ActivateOnDeath();
CreateExplosion();
CreateParticles();
CreateDebris();
QueueFree();
}
private void ActivateOnDeath()
{
if (Target is IActivable node)
{
node.Activate(ActivationType);
}
}
private void CreateExplosion()
{
if (ExplosionData == null) return;
var explosion = this.CreateSibling<Bullet>(ExplosionData.BulletScene);
explosion.Speed = 0;
explosion.Initialize(ExplosionData.MakeBullet(this.GlobalPosition), _gameManager);
}
private void ApplyExplosionDamage()
{
var spaceState = GetWorld2D().DirectSpaceState;
var query = new PhysicsShapeQueryParameters2D();
var shape = new CircleShape2D { Radius = ExplosionRadius };
query.SetShape(shape);
query.Transform = new Transform2D(0, GlobalPosition);
query.CollideWithBodies = false;
query.CollideWithAreas = true;
//query.CollisionMask = ;
var results = spaceState.IntersectShape(query);
GD.Print($"Shapes in range: {results.Count}");
foreach (var result in results)
{
if (result.TryGetValue("collider", out var colliderObj))
{
var collider = colliderObj.As<Node2D>();
if (collider.GetParent<Area2D>() is IDestructible destructible)
{
GD.Print($"HITTING {collider.Name}");
destructible.Hit(ExplosionDamage);
}
else {
GD.Print($"Collider {collider.Name} was not idestructible");
}
}
}
}
private void CreateDebris()
{
this.CreateSibling<Barrel>(DebrisScene);
}
private void CreateParticles()
{
if (ExplosionParticles == null) {
return;
}
var particle = this.CreateSibling<GpuParticles2D>(ExplosionParticles);
if (particle == null) return;
particle.Emitting = true;
}
public void Hit(float damage, DamageType damageType = DamageType.Neutral)
{
if (_isDestroyed) return;
_currentHealth -= damage;
if (_currentHealth > 0) return;
_isDestroyed = true;
Explode();
}
public bool IsDestroyed()
{
return _isDestroyed;
}
}