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

144 lines
3.2 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using Godot;
using Godot.Bridge;
using Godot.NativeInterop;
[ScriptPath("res://Scripts/Puzzles/Sukoban.cs")]
public partial class Sukoban : Node2D
{
[Signal]
public delegate void OnCompletionEventHandler();
[Export(PropertyHint.None, "")]
private Entity entity;
[Export(PropertyHint.None, "")]
private CratePush[] crates;
[Export(PropertyHint.None, "")]
private PuzzleButton[] buttons;
[Export(PropertyHint.None, "")]
private RichTextLabel help;
[Export(PropertyHint.None, "")]
private SaveFile.Flags flag;
[Export(PropertyHint.None, "")]
private StringName mapFlag = "None";
[Export(PropertyHint.None, "")]
private CapacitorShot entityFrom;
[Export(PropertyHint.None, "")]
private bool noFlag;
private Vector2 startCam;
private Entity caller;
public static Sukoban instance;
public override void _Process(double delta)
{
if (entityFrom != null && !GodotObject.IsInstanceValid(entity) && GodotObject.IsInstanceValid(entityFrom.entity))
{
entity = entityFrom.entity;
}
if (instance == null || Main.inEvent != null)
{
return;
}
RichTextLabel richTextLabel = help;
if (richTextLabel != null && richTextLabel.Text.Length < 1)
{
help.Text = "[center][color=gray]" + Texts.common[54];
}
if (Input.IsActionJustPressed(Main.keys[6]))
{
Audio.PlaySound(Audio.commonSounds[0]);
Stop();
return;
}
PuzzleButton[] array = buttons;
if (array == null || array.Length == 0)
{
return;
}
for (int i = 0; i < buttons.Length; i++)
{
if (!buttons[i].active)
{
return;
}
}
Stop(panCamera: false);
if (flag > SaveFile.Flags.IsInDW && !noFlag)
{
SaveFile.AddFlag(flag);
}
EmitSignal(SignalName.OnCompletion);
}
public void Stop(bool panCamera = true)
{
instance = null;
if (help != null)
{
help.Text = "";
}
Vector2 globalPosition = CameraController.instance.GlobalPosition;
CameraController.instance.follow = null;
Player.instance.lockMenu = false;
if (caller == null)
{
caller = Player.instance;
}
if (panCamera)
{
Main.inEvent = Coroutine.Start(CameraController.PanToObj(globalPosition, caller, 100f, fixedRate: false));
}
Player.AssumeControl(caller, playParticle: false, updateCamera: false);
}
private void Reset()
{
entity.GlobalPosition = entity.startPos;
for (int i = 0; i < crates.Length; i++)
{
crates[i].GlobalPosition = crates[i].start;
}
}
public void Start()
{
caller = Player.instance.controlling;
if (SaveFile.HasFlag(flag) || Room.current.tempFlags.Contains(mapFlag))
{
TextSystem.GetText("SukobanDone");
return;
}
Reset();
startCam = CameraController.instance.GlobalPosition;
Party.StopMoving();
if (Player.instance.controlling == Player.instance)
{
Party.LookAt(Vector2.Up);
}
else
{
Player.instance.controlling.LookAt(Vector2.Up);
}
instance = this;
Audio.PlaySound("snd_puzzle_start.wav");
CameraController.instance.follow = null;
Player.instance.lockMenu = true;
Main.inEvent = Coroutine.Start(CameraController.Pan(startCam, base.GlobalPosition, 100f, fixedRate: false));
Player.AssumeControl(entity, playParticle: false, updateCamera: false);
}
}