using System.Collections.Generic; using Cthangover.Core.Battle; using Cthangover.Core.Settings; using Cthangover.Core.UI.Theming; using Godot; namespace Cthangover.TurnBattle { /// /// In-battle speed toggle bar (x1/x4/x8). Directly sets /// Godot.Engine.TimeScale to globally accelerate the entire game loop — /// not just animations. Persists the choice to GameData.Settings /// so it survives scene reloads. restores 1x /// without saving and is the part the core scene consumes through /// when battle ends. /// public partial class BattleSpeedControl : Control, IBattleSpeedControl { private readonly Dictionary _buttons = new(); private int _activeSpeed; /// /// Builds the speed bar in the constructor. Godot never runs a /// _Ready override declared in a mod assembly, so the buttons and the /// saved-speed restore must happen here. Anchors are used instead of a /// viewport-size lookup because the viewport is unavailable before the node /// enters the tree. /// public BattleSpeedControl() { CthangoverTheme.Apply(this); var speeds = new[] { 1, 4, 8 }; var hbox = new HBoxContainer { Name = "SpeedButtons" }; hbox.Alignment = BoxContainer.AlignmentMode.Begin; foreach (var speed in speeds) { var btn = new Button { Text = $"x{speed}", CustomMinimumSize = new Vector2(48, 32) }; btn.Pressed += () => OnSpeedSelected(speed); hbox.AddChild(btn); _buttons[speed] = btn; } AddChild(hbox); AnchorLeft = 1f; AnchorRight = 1f; AnchorTop = 0f; AnchorBottom = 0f; OffsetLeft = -200f; OffsetRight = -20f; OffsetTop = 20f; OffsetBottom = 52f; ApplySavedSpeed(); } /// /// Restores the speed from . /// Called on _Ready to reapply the saved preference. /// public void ApplySavedSpeed() { var speed = GameData.Instance.Settings.BattleSpeed; if (speed < 1 || speed > 8) speed = 1; _activeSpeed = speed; Godot.Engine.TimeScale = speed; UpdateHighlight(); } /// /// Resets to 1.0x without /// persisting to settings. Used when battle ends so the lobby /// and menus run at normal speed regardless of the player's /// in-battle preference. /// public void ResetToNormal() { Godot.Engine.TimeScale = 1.0f; } private void OnSpeedSelected(int speed) { _activeSpeed = speed; Godot.Engine.TimeScale = speed; var settings = GameData.Instance.Settings; settings.BattleSpeed = speed; settings.Save(); UpdateHighlight(); } private void UpdateHighlight() { foreach (var kv in _buttons) { var isActive = kv.Key == _activeSpeed; kv.Value.Modulate = isActive ? UiTokens.Success : UiTokens.White; } } } }