using Godot; public partial class CorruptionArea : Node3D { public override void _Ready() { _disc = GetNode("Disc"); if (_disc == null) { GD.PushWarning("CorruptionArea: Could not find child MeshInstance3D named 'Disc'."); return; } _baseScale = _disc.Scale; ApplyRadius(); _shaderMaterial = (ShaderMaterial)_disc.GetActiveMaterial(0).Duplicate(); _disc.MaterialOverride = _shaderMaterial; } public override void _Process(double delta) { if (_shaderMaterial == null) return; var t = Time.GetTicksMsec() / 1000.0f; var pulse = 1.0f + Mathf.Sin(t * PulseSpeed) * PulseAmount; _shaderMaterial.SetShaderParameter("u_pulse", pulse); _shaderMaterial.SetShaderParameter("base_color", Color); } /// /// Call this if you change Radius at runtime. /// public void ApplyRadius() { if (_disc == null) return; var r = Mathf.Max(Radius, 0.01f); // PlaneMesh is 2x2 units, so scale XZ by radius to get the desired world radius. _disc.Scale = new(_baseScale.X * r, _baseScale.Y, _baseScale.Z * r); } public void SetRadius(float radius) { Radius = radius; ApplyRadius(); } [Export] public float Radius { get; set; } = 1.0f; // World-space radius in XZ units. [Export] public float PulseSpeed { get; set; } = 1.5f; [Export] public float PulseAmount { get; set; } = 0.25f; [Export] public Color Color { get; set; } = new(0.6f, 0.1f, 0.8f, 0.45f); private Vector3 _baseScale = Vector3.One; private MeshInstance3D _disc; private ShaderMaterial _shaderMaterial; }