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 count = new Dictionary { { 2, 3 }, { 3, 2 }, { 4, 1 } }; private List balls = new List(); 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 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]; } } }