using System; using System.Collections.Generic; using System.ComponentModel; using Godot; using Godot.Bridge; using Godot.NativeInterop; [ScriptPath("res://Scripts/Puzzles/CapacitorShot.cs")] public partial class CapacitorShot : Node2D { [Signal] public delegate void OnCompletionEventHandler(); [Export(PropertyHint.None, "")] private PackedScene entityBase; [Export(PropertyHint.None, "")] private Area2D[] areas; [Export(PropertyHint.None, "")] private Node2D target; [Export(PropertyHint.None, "")] private Node2D[] activate; [Export(PropertyHint.None, "")] private float[] travelTime = new float[3] { 300f, 225f, 150f }; [Export(PropertyHint.None, "")] private Vector2 pushDir = Vector2.Down; [Export(PropertyHint.None, "")] private StringName mapFlag = "None"; public Entity entity; private bool hit; private bool done; private float time; private float delay; private int current; private VisibleOnScreenNotifier2D screenTest; public const uint layer = 128u; public override void _Ready() { for (int i = 0; i < areas.Length; i++) { areas[i].CollisionLayer = 128u; areas[i].CollisionMask = 128u; } } public override void _Process(double delta) { if (delay > 0f) { delay -= Main.deltaTime; } if (entity == null) { entity = entityBase.Instantiate(PackedScene.GenEditState.Disabled); AddChild(entity, forceReadableName: false, InternalMode.Disabled); entity.GlobalPosition = base.GlobalPosition; time = 0f; entity.AddChild(screenTest = new VisibleOnScreenNotifier2D(), forceReadableName: false, InternalMode.Disabled); entity.trigger.CollisionLayer = 128u; entity.trigger.CollisionMask = 128u; entity.trigger.AreaEntered += BulletHit; entity.trigger.BodyEntered += HitWall; CollisionShape2D collider = entity.collider; float[] array = travelTime; collider.Disabled = array != null && array.Length > 1; float[] array2 = travelTime; if (array2 == null || array2.Length <= 1) { entity.SetDeferred("startPos", target.GlobalPosition); } return; } if (hit) { if (!screenTest.IsOnScreen()) { Kill(); } else { entity.GlobalPosition += pushDir * 2.25f; } return; } float[] array3 = travelTime; if (array3 != null && array3.Length > 1) { time += Main.deltaTime; if (time >= travelTime[current]) { entity.QueueFree(); entity = null; } else { entity.GlobalPosition = base.GlobalPosition.Lerp(target.GlobalPosition, time / travelTime[current]); } } else if (time < 30f) { time += Main.deltaTime; entity.GlobalPosition = base.GlobalPosition.Lerp(target.GlobalPosition, time / 30f); } } private void HitWall(Node other) { if (other is CollisionObject2D collisionObject2D && (collisionObject2D.CollisionLayer & 0x80) != 0) { if (hit) { CameraController.Shake(20f); Main.Particle("BadExplosion", entity.GlobalPosition, 1, null, localSpace: false); Kill(); } else { entity.StopMoving(); entity.GlobalPosition += collisionObject2D.GlobalPosition.DirectionTo(entity.GlobalPosition).Snapped(Vector2.One) * 2f; } } } private void Kill() { entity.QueueFree(); entity = null; hit = false; delay = 10f; } private void BulletHit(Node other) { if (done || !IsProcessing()) { return; } if (other.HasMeta(Enemy.waterTag)) { Main.Particle("WaterBurst", other.GetParent().GlobalPosition, 1, null, localSpace: false); other.GetParent().QueueFree(); entity.anim.Play("Hurt"); entity.ProcessMode = ProcessModeEnum.Always; hit = true; Audio.PlaySound("snd_bomb.wav"); } else { if (other != areas[current]) { return; } entity.GlobalPosition = areas[current].GlobalPosition + new Vector2(0f, 4f); Main.Particle("Sparks", areas[current].GlobalPosition, 1, null, localSpace: false); entity.anim.Play("Elec"); Audio.PlaySound("snd_grab.wav"); Audio.PlaySound("snd_electric_talk.wav", 1f, 0.9f).Bus = "Reverb"; Main.SetActive(activate[current], state: true); current++; entity = null; hit = false; if (current >= areas.Length) { if (mapFlag != (StringName)"None") { Room.current.tempFlags.Add(mapFlag); } EmitSignal(SignalName.OnCompletion); SetDeferred("process_mode", 4); done = true; } delay = 10f; } } }