2025-05-13 19:22:01 +08:00

192 lines
4.3 KiB
C#

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<Entity>(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<Node2D>().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;
}
}
}