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

611 lines
13 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using Godot;
using Godot.Bridge;
using Godot.NativeInterop;
[ScriptPath("res://Scripts/Events/BearFortDuoMinigame.cs")]
public partial class BearFortDuoMinigame : EventCaller
{
public partial class Balls
{
public Sprite2D obj;
public BearFortDuoMinigame parent;
public Vector2 target;
public Vector2 mid;
public Vector2 start;
public float time;
private Area2D area;
private bool delete;
private float current;
public void Start()
{
BearFortDuoMinigame bearFortDuoMinigame = parent;
Sprite2D obj = new Sprite2D
{
Texture = parent.ball.Texture,
Position = parent.baller.Position + new Vector2(20f, -50f)
};
Sprite2D node = obj;
this.obj = obj;
bearFortDuoMinigame.AddChild(node, forceReadableName: false, InternalMode.Disabled);
time = Main.RandomRange(180, 300);
start = this.obj.GlobalPosition;
if (Main.RandomRange(0, 10) < 2)
{
target = new Vector2(parent.kanako.GlobalPosition.X, 30f);
}
else
{
target = new Vector2(Main.RandomRange(-170, -72), 30f);
}
mid = new Vector2(target.X, -550f);
this.obj.AddChild(area = new Area2D
{
CollisionLayer = 4u,
CollisionMask = 4u
}, forceReadableName: false, InternalMode.Disabled);
area.AddChild(new CollisionShape2D
{
Shape = new CircleShape2D()
}, forceReadableName: false, InternalMode.Disabled);
area.SetMeta(parent.ballTag, this.obj);
}
public void Delete()
{
delete = true;
current = 0f;
area.SetDeferred("monitorable", false);
area.SetDeferred("monitoring", false);
}
public void Update()
{
if (delete)
{
if (current < 30f)
{
current += Main.deltaTime;
obj.Modulate = Main.colorWhite.Lerp(Main.colorClear, current / 30f);
obj.Scale = Vector2.One.Lerp(Vector2.One * 1.2f, current / 30f);
}
else
{
parent.balls.Remove(this);
obj.QueueFree();
}
}
else
{
obj.GlobalPosition = Common.Beizier(start, mid, target, current / time);
current += Main.deltaTime;
obj.RotationDegrees += Main.deltaTime;
if (current >= time)
{
Delete();
}
}
}
}
[Export(PropertyHint.None, "")]
private RichTextLabel indicator;
[Export(PropertyHint.None, "")]
private RichTextLabel help;
[Export(PropertyHint.None, "")]
private Sprite2D ball;
[Export(PropertyHint.None, "")]
private Sprite2D shootLine;
[Export(PropertyHint.None, "")]
private Entity baller;
[Export(PropertyHint.None, "")]
private Node2D[] kPoints;
[Export(PropertyHint.None, "")]
private Node2D[] cPoints;
[Export(PropertyHint.None, "")]
private Area2D[] collider;
[Export(PropertyHint.None, "")]
private Node2D ballerMove;
[Export(PropertyHint.None, "")]
private Node2D camPos;
[Export(PropertyHint.None, "")]
private Node2D pencil;
[Export(PropertyHint.None, "")]
private Node2D bridge;
[Export(PropertyHint.None, "")]
private Node2D penceller;
[Export(PropertyHint.None, "")]
private Node2D bridgeBlocker;
public Entity player;
public Entity kanako;
private int state = -1;
private int lives;
private int score;
private float cd;
private float iframes;
private float pencilCD;
private Coroutine shoot;
private Coroutine tossing;
private Vector2 ballerpos;
private int[] pos = new int[2];
private static readonly Dictionary<int, int> count = new Dictionary<int, int>
{
{ 2, 3 },
{ 3, 2 },
{ 4, 1 }
};
private List<Balls> balls = new List<Balls>();
public const float height = -300f;
private readonly Vector2 colOffset = new Vector2(0f, -20f);
public readonly StringName ballTag = "BBall";
public void StartEvent()
{
Main.inEvent = Coroutine.Start(BBallTalk());
}
public IEnumerator BBallTalk()
{
if (SaveFile.HasFlag(SaveFile.Flags.BBallPity2) && !SaveFile.HasFlag(SaveFile.Flags.BBallPitied))
{
SaveFile.AddFlag(SaveFile.Flags.BBallPitied);
Room.current.eventPointers[0].QueueFree();
TextSystem.GetText("BBallPity");
SaveFile.AddFlag(SaveFile.Flags.BearFortLeftMinigame);
while (TextSystem.instance.Visible)
{
yield return null;
}
Coroutine w = Coroutine.Start(BridgeOpen());
while (!w.done)
{
yield return null;
}
yield break;
}
if (!SaveFile.HasFlag(SaveFile.Flags.BBallTalk1))
{
TextSystem.GetText("BearFortBBall1");
while (TextSystem.instance.Visible)
{
yield return null;
}
if (!SaveFile.HasFlag(SaveFile.Flags.WeirdStart) && TextSystem.lastPrompt == 0)
{
yield break;
}
}
else if (!SaveFile.HasFlag(SaveFile.Flags.BBallTalk2))
{
TextSystem.GetText("BBallTalk1.5");
while (TextSystem.instance.Visible)
{
yield return null;
}
if (TextSystem.lastPrompt == 0)
{
yield break;
}
}
else
{
if (SaveFile.HasFlag(SaveFile.Flags.BearFortLeftMinigame))
{
TextSystem.GetText("BBallAfter");
while (TextSystem.instance.Visible)
{
yield return null;
}
yield break;
}
TextSystem.GetText("BBallRepeat");
while (TextSystem.instance.Visible)
{
yield return null;
}
if (TextSystem.lastPrompt == 1)
{
yield break;
}
}
StartGame();
}
private void StartGame()
{
SaveFile.AddFlag(SaveFile.Flags.BBallPlayedOnce);
SaveFile.AddFlag(SaveFile.Flags.BBallTalk2);
state = 0;
pos[0] = 1;
score = 0;
lives = 3;
pencilCD = 150f;
help.Text = "[center][color=gray]" + Texts.FindDiag("BBallInstructions")[0].text;
pos[1] = 1;
ballerpos = baller.GlobalPosition;
player = Player.instance;
kanako = Player.instance.followers[0];
kanako.anim.Play(SaveFile.HasFlag(SaveFile.Flags.WeirdStart) ? "Stand" : "Surprise");
kanako.sprite.FlipH = true;
player.sprite.FlipH = true;
baller.sprite.FlipH = true;
baller.anim.Play("Idle");
player.anim.Play("BattleIdle");
CameraController.instance.follow = null;
kanako.doTrail = true;
player.doTrail = true;
Audio.PlaySound("snd_weaponpull.wav");
}
public override void _Process(double delta)
{
if (cd > 0f)
{
cd -= Main.deltaTime;
}
if (iframes > 0f)
{
iframes -= Main.deltaTime;
}
switch (state)
{
case 0:
Audio.ChangeMusic(null);
cd = 60f;
state = 1;
break;
case 1:
if (cd <= 0f)
{
help.Visible = true;
Room.current.DoMusic(1);
IndicatorCD();
}
break;
case 2:
case 3:
case 4:
case 5:
if (cd <= 0f)
{
IndicatorCD();
}
break;
case 6:
{
if (!Audio.music.Playing)
{
Main.inEvent = Coroutine.Start(End(score >= 10));
return;
}
if (pencilCD > 0f)
{
pencilCD -= Main.deltaTime;
if (pencil.Visible)
{
pencil.GlobalPosition += Vector2.Right * Main.deltaTime * 2f;
}
}
else
{
Audio.PlaySound("snd_arrow.wav");
Main.SetActive(pencil, state: true);
pencil.GlobalPosition = new Vector2(-300f, player.GlobalPosition.Y - 16f);
pencilCD = Main.RandomRange(180, 250);
}
if (help.Visible)
{
help.Visible = false;
shootLine.Visible = true;
}
if (shoot == null || shoot.done)
{
if (Input.IsActionJustPressed(Main.keys[4]))
{
shoot = Coroutine.Start(Shoot());
}
if (Input.IsActionJustPressed(Main.keys[0]))
{
if (pos[0] > 0)
{
pos[0]--;
}
}
else if (Input.IsActionJustPressed(Main.keys[1]) && pos[0] < 2)
{
pos[0]++;
}
}
if (Input.IsActionJustPressed(Main.keys[2]))
{
if (pos[1] > 0)
{
pos[1]--;
}
}
else if (Input.IsActionJustPressed(Main.keys[3]) && pos[1] < 2)
{
pos[1]++;
}
if (cd <= 0f && (tossing == null || tossing.done))
{
tossing = Coroutine.Start(TossBall());
}
for (int num = balls.Count - 1; num >= 0; num--)
{
balls[num].Update();
}
break;
}
}
if (state > -1)
{
Player.instance.canInput = false;
CameraController.instance.GlobalPosition = CameraController.instance.GlobalPosition.Lerp(camPos.GlobalPosition, 0.2f * Main.deltaTime);
kanako.GlobalPosition = kanako.GlobalPosition.Lerp(kPoints[pos[1]].GlobalPosition, 0.2f * Main.deltaTime);
player.GlobalPosition = player.GlobalPosition.Lerp(cPoints[pos[0]].GlobalPosition, 0.2f * Main.deltaTime);
baller.GlobalPosition = baller.GlobalPosition.Lerp(ballerMove.GlobalPosition, 0.2f * Main.deltaTime);
collider[0].GlobalPosition = kanako.GlobalPosition + colOffset;
collider[1].GlobalPosition = player.GlobalPosition + colOffset;
shootLine.GlobalPosition = new Vector2(shootLine.GlobalPosition.X, player.GlobalPosition.Y - 16f);
}
}
private IEnumerator Shoot()
{
bool hit = false;
player.anim.Play("AttackReady");
for (float a = 0f; a < 7f; a += Main.deltaTime)
{
yield return null;
}
for (int i = 0; i < balls.Count; i++)
{
if (balls[i].obj.GlobalPosition.X > -170f && Mathf.Abs(balls[i].obj.GlobalPosition.Y - shootLine.GlobalPosition.Y) < 17f)
{
Audio.PlaySound("snd_bomb.wav");
balls[i].Delete();
score++;
indicator.Text = score.ToString().PadLeft(2, '0');
hit = true;
break;
}
}
if (!hit)
{
Audio.PlaySound("snd_curtgunshot.ogg");
BattleDR.ShowFloatingText("MISS", player.GlobalPosition);
}
for (float a = 0f; a < 25f; a += Main.deltaTime)
{
yield return null;
}
player.anim.Play("BattleIdle");
}
private IEnumerator End(bool won = false)
{
Main.SetActive(pencil, state: false);
shootLine.Visible = false;
Coroutine coroutine = tossing;
if (coroutine != null && !coroutine.done)
{
Coroutine.Stop(tossing);
}
Coroutine coroutine2 = shoot;
if (coroutine2 != null && !coroutine2.done)
{
Coroutine.Stop(shoot);
}
Audio.ChangeMusic(null);
state = -1;
for (int num = balls.Count - 1; num >= 0; num--)
{
balls[num].Delete();
}
if (won)
{
Audio.PlaySound("snd_won.wav");
}
else
{
Audio.PlaySound("snd_error.wav");
}
baller.anim.Play("Idle");
while (balls.Count > 0)
{
for (int num2 = balls.Count - 1; num2 >= 0; num2--)
{
balls[num2].Update();
}
yield return null;
}
player.LookAt(baller.GlobalPosition);
player.UpdateAnim(force: true);
kanako.LookAt(baller.GlobalPosition);
kanako.UpdateAnim(force: true);
if (won)
{
TextSystem.GetText("BBallWon");
SaveFile.AddFlag(SaveFile.Flags.BearFortLeftMinigame);
while (TextSystem.instance.Visible)
{
yield return null;
}
Coroutine w = Coroutine.Start(BridgeOpen());
while (w.done)
{
yield return null;
}
}
else
{
SaveFile.AddFlag(SaveFile.Flags.BBallKanakoTalk1);
if (!SaveFile.HasFlag(SaveFile.Flags.BBallPity1))
{
TextSystem.GetText("BBallLost");
SaveFile.AddFlag(SaveFile.Flags.BBallPity1);
}
else if (!SaveFile.HasFlag(SaveFile.Flags.BBallPity2))
{
TextSystem.GetText("BBallLost2");
SaveFile.AddFlag(SaveFile.Flags.BBallPity2);
}
while (TextSystem.instance.Visible)
{
yield return null;
}
}
Coroutine c = Coroutine.Start(CameraController.PanToObj(kanako));
while (!c.done)
{
baller.GlobalPosition = baller.GlobalPosition.Lerp(ballerpos, 0.1f * Main.deltaTime);
yield return null;
}
if (won)
{
penceller.GlobalPosition = new Vector2(-300f, -100f);
}
indicator.Text = "";
Room.current.DoMusic();
baller.Position = ballerpos;
}
private IEnumerator BridgeOpen()
{
Audio.PlaySound("snd_shadowpendant_ch1.wav");
Main.SetActive(bridge, state: true);
for (float a = 0f; a < 60f; a += Main.deltaTime)
{
bridge.Modulate = Main.colorClear.Lerp(Main.colorWhite, a / 60f);
yield return null;
}
bridgeBlocker.QueueFree();
SaveFile.AddFlag(SaveFile.Flags.BBallKanakoTalk1);
SaveFile.AddFlag(SaveFile.Flags.BBallKanakoTalk2);
}
public void KanakoHit(Node other)
{
if ((!other.HasMeta(ballTag) && other.GetParent() != pencil) || !(iframes <= 0f))
{
return;
}
iframes = 30f;
Audio.PlaySound("snd_hurt1.wav");
CameraController.Shake(10f);
bool flag = false;
for (int i = 0; i < balls.Count; i++)
{
if (other.GetParent() == balls[i].obj)
{
balls[i].Delete();
flag = true;
break;
}
}
if (flag)
{
BattleDR.ShowFloatingText("-1", kanako.GlobalPosition);
kanako.Shake(10f, 1f);
}
else
{
BattleDR.ShowFloatingText("-1", player.GlobalPosition);
player.Shake(10f, 1f);
}
lives--;
if (score > 0)
{
score--;
indicator.Text = score.ToString().PadLeft(2, '0');
}
}
public IEnumerator TossBall()
{
cd = Main.RandomRange(80, 120);
baller.anim.Play("TossReady");
baller.Shake(Main.RandomRange(20, 40), 1f);
while (baller.shake > 0f)
{
yield return null;
}
baller.anim.Play("TossDo");
balls.Add(new Balls
{
parent = this
});
List<Balls> list = balls;
list[list.Count - 1].Start();
for (float a = 0f; a < 30f; a += Main.deltaTime)
{
yield return null;
}
baller.anim.Play("Idle");
}
private void IndicatorCD()
{
player.doTrail = false;
kanako.doTrail = false;
state++;
if (state == 5)
{
cd = 60f;
indicator.Text = "GO";
}
else if (state == 6)
{
indicator.Text = "00";
}
else
{
cd = 60f;
indicator.Text = "0" + count[state];
}
}
}