2025-05-03 20:36:17 +08:00

641 lines
19 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 class CapacitorShot : Node2D
{
[Signal]
public delegate void OnCompletionEventHandler();
public new class MethodName : Node2D.MethodName
{
public new static readonly StringName _Ready = "_Ready";
public new static readonly StringName _Process = "_Process";
public static readonly StringName HitWall = "HitWall";
public static readonly StringName Kill = "Kill";
public static readonly StringName BulletHit = "BulletHit";
}
public new class PropertyName : Node2D.PropertyName
{
public static readonly StringName entityBase = "entityBase";
public static readonly StringName areas = "areas";
public static readonly StringName target = "target";
public static readonly StringName activate = "activate";
public static readonly StringName travelTime = "travelTime";
public static readonly StringName pushDir = "pushDir";
public static readonly StringName mapFlag = "mapFlag";
public static readonly StringName entity = "entity";
public static readonly StringName hit = "hit";
public static readonly StringName done = "done";
public static readonly StringName time = "time";
public static readonly StringName delay = "delay";
public static readonly StringName current = "current";
public static readonly StringName screenTest = "screenTest";
}
public new class SignalName : Node2D.SignalName
{
public static readonly StringName OnCompletion = "OnCompletion";
}
[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;
private OnCompletionEventHandler backing_OnCompletion;
public event OnCompletionEventHandler OnCompletion
{
add
{
backing_OnCompletion = (OnCompletionEventHandler)Delegate.Combine(backing_OnCompletion, value);
}
remove
{
backing_OnCompletion = (OnCompletionEventHandler)Delegate.Remove(backing_OnCompletion, value);
}
}
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;
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
internal static List<MethodInfo> GetGodotMethodList()
{
return new List<MethodInfo>(5)
{
new MethodInfo(MethodName._Ready, new PropertyInfo(Variant.Type.Nil, "", PropertyHint.None, "", PropertyUsageFlags.Default, exported: false), MethodFlags.Normal, null, null),
new MethodInfo(MethodName._Process, new PropertyInfo(Variant.Type.Nil, "", PropertyHint.None, "", PropertyUsageFlags.Default, exported: false), MethodFlags.Normal, new List<PropertyInfo>
{
new PropertyInfo(Variant.Type.Float, "delta", PropertyHint.None, "", PropertyUsageFlags.Default, exported: false)
}, null),
new MethodInfo(MethodName.HitWall, new PropertyInfo(Variant.Type.Nil, "", PropertyHint.None, "", PropertyUsageFlags.Default, exported: false), MethodFlags.Normal, new List<PropertyInfo>
{
new PropertyInfo(Variant.Type.Object, "other", PropertyHint.None, "", PropertyUsageFlags.Default, new StringName("Node"), exported: false)
}, null),
new MethodInfo(MethodName.Kill, new PropertyInfo(Variant.Type.Nil, "", PropertyHint.None, "", PropertyUsageFlags.Default, exported: false), MethodFlags.Normal, null, null),
new MethodInfo(MethodName.BulletHit, new PropertyInfo(Variant.Type.Nil, "", PropertyHint.None, "", PropertyUsageFlags.Default, exported: false), MethodFlags.Normal, new List<PropertyInfo>
{
new PropertyInfo(Variant.Type.Object, "other", PropertyHint.None, "", PropertyUsageFlags.Default, new StringName("Node"), exported: false)
}, null)
};
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override bool InvokeGodotClassMethod(in godot_string_name method, NativeVariantPtrArgs args, out godot_variant ret)
{
if (method == MethodName._Ready && args.Count == 0)
{
_Ready();
ret = default(godot_variant);
return true;
}
if (method == MethodName._Process && args.Count == 1)
{
_Process(VariantUtils.ConvertTo<double>(in args[0]));
ret = default(godot_variant);
return true;
}
if (method == MethodName.HitWall && args.Count == 1)
{
HitWall(VariantUtils.ConvertTo<Node>(in args[0]));
ret = default(godot_variant);
return true;
}
if (method == MethodName.Kill && args.Count == 0)
{
Kill();
ret = default(godot_variant);
return true;
}
if (method == MethodName.BulletHit && args.Count == 1)
{
BulletHit(VariantUtils.ConvertTo<Node>(in args[0]));
ret = default(godot_variant);
return true;
}
return base.InvokeGodotClassMethod(in method, args, out ret);
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override bool HasGodotClassMethod(in godot_string_name method)
{
if (method == MethodName._Ready)
{
return true;
}
if (method == MethodName._Process)
{
return true;
}
if (method == MethodName.HitWall)
{
return true;
}
if (method == MethodName.Kill)
{
return true;
}
if (method == MethodName.BulletHit)
{
return true;
}
return base.HasGodotClassMethod(in method);
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
{
if (name == PropertyName.entityBase)
{
entityBase = VariantUtils.ConvertTo<PackedScene>(in value);
return true;
}
if (name == PropertyName.areas)
{
areas = VariantUtils.ConvertToSystemArrayOfGodotObject<Area2D>(in value);
return true;
}
if (name == PropertyName.target)
{
target = VariantUtils.ConvertTo<Node2D>(in value);
return true;
}
if (name == PropertyName.activate)
{
activate = VariantUtils.ConvertToSystemArrayOfGodotObject<Node2D>(in value);
return true;
}
if (name == PropertyName.travelTime)
{
travelTime = VariantUtils.ConvertTo<float[]>(in value);
return true;
}
if (name == PropertyName.pushDir)
{
pushDir = VariantUtils.ConvertTo<Vector2>(in value);
return true;
}
if (name == PropertyName.mapFlag)
{
mapFlag = VariantUtils.ConvertTo<StringName>(in value);
return true;
}
if (name == PropertyName.entity)
{
entity = VariantUtils.ConvertTo<Entity>(in value);
return true;
}
if (name == PropertyName.hit)
{
hit = VariantUtils.ConvertTo<bool>(in value);
return true;
}
if (name == PropertyName.done)
{
done = VariantUtils.ConvertTo<bool>(in value);
return true;
}
if (name == PropertyName.time)
{
time = VariantUtils.ConvertTo<float>(in value);
return true;
}
if (name == PropertyName.delay)
{
delay = VariantUtils.ConvertTo<float>(in value);
return true;
}
if (name == PropertyName.current)
{
current = VariantUtils.ConvertTo<int>(in value);
return true;
}
if (name == PropertyName.screenTest)
{
screenTest = VariantUtils.ConvertTo<VisibleOnScreenNotifier2D>(in value);
return true;
}
return base.SetGodotClassPropertyValue(in name, in value);
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
{
if (name == PropertyName.entityBase)
{
value = VariantUtils.CreateFrom(in entityBase);
return true;
}
if (name == PropertyName.areas)
{
GodotObject[] array = areas;
value = VariantUtils.CreateFromSystemArrayOfGodotObject(array);
return true;
}
if (name == PropertyName.target)
{
value = VariantUtils.CreateFrom(in target);
return true;
}
if (name == PropertyName.activate)
{
GodotObject[] array = activate;
value = VariantUtils.CreateFromSystemArrayOfGodotObject(array);
return true;
}
if (name == PropertyName.travelTime)
{
value = VariantUtils.CreateFrom(in travelTime);
return true;
}
if (name == PropertyName.pushDir)
{
value = VariantUtils.CreateFrom(in pushDir);
return true;
}
if (name == PropertyName.mapFlag)
{
value = VariantUtils.CreateFrom(in mapFlag);
return true;
}
if (name == PropertyName.entity)
{
value = VariantUtils.CreateFrom(in entity);
return true;
}
if (name == PropertyName.hit)
{
value = VariantUtils.CreateFrom(in hit);
return true;
}
if (name == PropertyName.done)
{
value = VariantUtils.CreateFrom(in done);
return true;
}
if (name == PropertyName.time)
{
value = VariantUtils.CreateFrom(in time);
return true;
}
if (name == PropertyName.delay)
{
value = VariantUtils.CreateFrom(in delay);
return true;
}
if (name == PropertyName.current)
{
value = VariantUtils.CreateFrom(in current);
return true;
}
if (name == PropertyName.screenTest)
{
value = VariantUtils.CreateFrom(in screenTest);
return true;
}
return base.GetGodotClassPropertyValue(in name, out value);
}
[EditorBrowsable(EditorBrowsableState.Never)]
internal static List<PropertyInfo> GetGodotPropertyList()
{
return new List<PropertyInfo>
{
new PropertyInfo(Variant.Type.Object, PropertyName.entityBase, PropertyHint.ResourceType, "PackedScene", PropertyUsageFlags.Default | PropertyUsageFlags.ScriptVariable, exported: true),
new PropertyInfo(Variant.Type.Array, PropertyName.areas, PropertyHint.TypeString, "24/34:Area2D", PropertyUsageFlags.Default | PropertyUsageFlags.ScriptVariable, exported: true),
new PropertyInfo(Variant.Type.Object, PropertyName.target, PropertyHint.NodeType, "Node2D", PropertyUsageFlags.Default | PropertyUsageFlags.ScriptVariable, exported: true),
new PropertyInfo(Variant.Type.Array, PropertyName.activate, PropertyHint.TypeString, "24/34:Node2D", PropertyUsageFlags.Default | PropertyUsageFlags.ScriptVariable, exported: true),
new PropertyInfo(Variant.Type.PackedFloat32Array, PropertyName.travelTime, PropertyHint.None, "", PropertyUsageFlags.Default | PropertyUsageFlags.ScriptVariable, exported: true),
new PropertyInfo(Variant.Type.Vector2, PropertyName.pushDir, PropertyHint.None, "", PropertyUsageFlags.Default | PropertyUsageFlags.ScriptVariable, exported: true),
new PropertyInfo(Variant.Type.StringName, PropertyName.mapFlag, PropertyHint.None, "", PropertyUsageFlags.Default | PropertyUsageFlags.ScriptVariable, exported: true),
new PropertyInfo(Variant.Type.Object, PropertyName.entity, PropertyHint.None, "", PropertyUsageFlags.ScriptVariable, exported: false),
new PropertyInfo(Variant.Type.Bool, PropertyName.hit, PropertyHint.None, "", PropertyUsageFlags.ScriptVariable, exported: false),
new PropertyInfo(Variant.Type.Bool, PropertyName.done, PropertyHint.None, "", PropertyUsageFlags.ScriptVariable, exported: false),
new PropertyInfo(Variant.Type.Float, PropertyName.time, PropertyHint.None, "", PropertyUsageFlags.ScriptVariable, exported: false),
new PropertyInfo(Variant.Type.Float, PropertyName.delay, PropertyHint.None, "", PropertyUsageFlags.ScriptVariable, exported: false),
new PropertyInfo(Variant.Type.Int, PropertyName.current, PropertyHint.None, "", PropertyUsageFlags.ScriptVariable, exported: false),
new PropertyInfo(Variant.Type.Object, PropertyName.screenTest, PropertyHint.None, "", PropertyUsageFlags.ScriptVariable, exported: false)
};
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void SaveGodotObjectData(GodotSerializationInfo info)
{
base.SaveGodotObjectData(info);
info.AddProperty(PropertyName.entityBase, Variant.From(in entityBase));
StringName name = PropertyName.areas;
GodotObject[] array = areas;
info.AddProperty(name, Variant.CreateFrom(array));
info.AddProperty(PropertyName.target, Variant.From(in target));
StringName name2 = PropertyName.activate;
array = activate;
info.AddProperty(name2, Variant.CreateFrom(array));
info.AddProperty(PropertyName.travelTime, Variant.From(in travelTime));
info.AddProperty(PropertyName.pushDir, Variant.From(in pushDir));
info.AddProperty(PropertyName.mapFlag, Variant.From(in mapFlag));
info.AddProperty(PropertyName.entity, Variant.From(in entity));
info.AddProperty(PropertyName.hit, Variant.From(in hit));
info.AddProperty(PropertyName.done, Variant.From(in done));
info.AddProperty(PropertyName.time, Variant.From(in time));
info.AddProperty(PropertyName.delay, Variant.From(in delay));
info.AddProperty(PropertyName.current, Variant.From(in current));
info.AddProperty(PropertyName.screenTest, Variant.From(in screenTest));
info.AddSignalEventDelegate(SignalName.OnCompletion, backing_OnCompletion);
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void RestoreGodotObjectData(GodotSerializationInfo info)
{
base.RestoreGodotObjectData(info);
if (info.TryGetProperty(PropertyName.entityBase, out var value))
{
entityBase = value.As<PackedScene>();
}
if (info.TryGetProperty(PropertyName.areas, out var value2))
{
areas = value2.AsGodotObjectArray<Area2D>();
}
if (info.TryGetProperty(PropertyName.target, out var value3))
{
target = value3.As<Node2D>();
}
if (info.TryGetProperty(PropertyName.activate, out var value4))
{
activate = value4.AsGodotObjectArray<Node2D>();
}
if (info.TryGetProperty(PropertyName.travelTime, out var value5))
{
travelTime = value5.As<float[]>();
}
if (info.TryGetProperty(PropertyName.pushDir, out var value6))
{
pushDir = value6.As<Vector2>();
}
if (info.TryGetProperty(PropertyName.mapFlag, out var value7))
{
mapFlag = value7.As<StringName>();
}
if (info.TryGetProperty(PropertyName.entity, out var value8))
{
entity = value8.As<Entity>();
}
if (info.TryGetProperty(PropertyName.hit, out var value9))
{
hit = value9.As<bool>();
}
if (info.TryGetProperty(PropertyName.done, out var value10))
{
done = value10.As<bool>();
}
if (info.TryGetProperty(PropertyName.time, out var value11))
{
time = value11.As<float>();
}
if (info.TryGetProperty(PropertyName.delay, out var value12))
{
delay = value12.As<float>();
}
if (info.TryGetProperty(PropertyName.current, out var value13))
{
current = value13.As<int>();
}
if (info.TryGetProperty(PropertyName.screenTest, out var value14))
{
screenTest = value14.As<VisibleOnScreenNotifier2D>();
}
if (info.TryGetSignalEventDelegate<OnCompletionEventHandler>(SignalName.OnCompletion, out var value15))
{
backing_OnCompletion = value15;
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
internal static List<MethodInfo> GetGodotSignalList()
{
return new List<MethodInfo>(1)
{
new MethodInfo(SignalName.OnCompletion, new PropertyInfo(Variant.Type.Nil, "", PropertyHint.None, "", PropertyUsageFlags.Default, exported: false), MethodFlags.Normal, null, null)
};
}
protected void EmitSignalOnCompletion()
{
EmitSignal(SignalName.OnCompletion);
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void RaiseGodotClassSignalCallbacks(in godot_string_name signal, NativeVariantPtrArgs args)
{
if (signal == SignalName.OnCompletion && args.Count == 0)
{
backing_OnCompletion?.Invoke();
}
else
{
base.RaiseGodotClassSignalCallbacks(in signal, args);
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override bool HasGodotClassSignal(in godot_string_name signal)
{
if (signal == SignalName.OnCompletion)
{
return true;
}
return base.HasGodotClassSignal(in signal);
}
}