diff --git a/src/TrackerCouncil.Smz3.Data/Options/GeneralOptions.cs b/src/TrackerCouncil.Smz3.Data/Options/GeneralOptions.cs index 4e0097a94..7d4e27c09 100644 --- a/src/TrackerCouncil.Smz3.Data/Options/GeneralOptions.cs +++ b/src/TrackerCouncil.Smz3.Data/Options/GeneralOptions.cs @@ -22,6 +22,8 @@ public class GeneralOptions : INotifyPropertyChanged private string? _twitchChannel; private string? _twitchId; + public bool HasOpenedSetupWindow { get; set; } + public string? Z3RomPath { get; set; } public string? SMRomPath { get; set; } diff --git a/src/TrackerCouncil.Smz3.Data/Options/RandomizerOptions.cs b/src/TrackerCouncil.Smz3.Data/Options/RandomizerOptions.cs index 8a16c271a..c91ec0eb7 100644 --- a/src/TrackerCouncil.Smz3.Data/Options/RandomizerOptions.cs +++ b/src/TrackerCouncil.Smz3.Data/Options/RandomizerOptions.cs @@ -98,6 +98,8 @@ public static RandomizerOptions Load(string loadPath, string savePath, bool isYa var options = serializer.Deserialize(fileText); options.FilePath = savePath; + var settingsUpdated = false; + // Update from AutoTracker connector settings to SnesConnector settings if (options.GeneralOptions.AutoTrackerDefaultConnectionType != EmulatorConnectorType.None) { @@ -108,6 +110,7 @@ public static RandomizerOptions Load(string loadPath, string savePath, bool isYa options.GeneralOptions.SnesConnectorSettings.Usb2SnesAddress = options.GeneralOptions.AutoTrackerQUsb2SnesIp ?? ""; options.GeneralOptions.AutoTrackerDefaultConnectionType = EmulatorConnectorType.None; + settingsUpdated = true; } if (options.GeneralOptions.MsuTrackDisplayStyle != null) @@ -122,6 +125,7 @@ public static RandomizerOptions Load(string loadPath, string savePath, bool isYa _ => TrackDisplayFormat.Vertical }; options.GeneralOptions.MsuTrackDisplayStyle = null; + settingsUpdated = true; } // Update AutoTrackerChangeMap to AutoMapUpdateBehavior @@ -130,6 +134,7 @@ public static RandomizerOptions Load(string loadPath, string savePath, bool isYa options.GeneralOptions.AutoMapUpdateBehavior = options.GeneralOptions.AutoTrackerChangeMap ? AutoMapUpdateBehavior.UpdateOnRegionChange : AutoMapUpdateBehavior.Disabled; + settingsUpdated = true; } // Remove deprecated config profiles @@ -137,6 +142,19 @@ public static RandomizerOptions Load(string loadPath, string savePath, bool isYa { options.GeneralOptions.SelectedProfiles = options.GeneralOptions.SelectedProfiles .Where(p => p != null && !ConfigProvider.DeprecatedConfigProfiles.Contains(p)).ToList(); + settingsUpdated = true; + } + + // Update HasOpenedSetupWindow if the Z3 rom path is populated + if (!options.GeneralOptions.HasOpenedSetupWindow && !string.IsNullOrEmpty(options.GeneralOptions.Z3RomPath)) + { + options.GeneralOptions.HasOpenedSetupWindow = true; + settingsUpdated = true; + } + + if (settingsUpdated) + { + options.Save(); } return options; diff --git a/src/TrackerCouncil.Smz3.Data/TrackerCouncil.Smz3.Data.csproj b/src/TrackerCouncil.Smz3.Data/TrackerCouncil.Smz3.Data.csproj index ac272ec37..239e94e08 100644 --- a/src/TrackerCouncil.Smz3.Data/TrackerCouncil.Smz3.Data.csproj +++ b/src/TrackerCouncil.Smz3.Data/TrackerCouncil.Smz3.Data.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/TrackerCouncil.Smz3.PatchBuilder/TrackerCouncil.Smz3.PatchBuilder.csproj b/src/TrackerCouncil.Smz3.PatchBuilder/TrackerCouncil.Smz3.PatchBuilder.csproj index ee579531a..5017dc8ca 100644 --- a/src/TrackerCouncil.Smz3.PatchBuilder/TrackerCouncil.Smz3.PatchBuilder.csproj +++ b/src/TrackerCouncil.Smz3.PatchBuilder/TrackerCouncil.Smz3.PatchBuilder.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/TrackerCouncil.Smz3.Shared/TrackerCouncil.Smz3.Shared.csproj b/src/TrackerCouncil.Smz3.Shared/TrackerCouncil.Smz3.Shared.csproj index 4a9d5f1e6..b889ce60b 100644 --- a/src/TrackerCouncil.Smz3.Shared/TrackerCouncil.Smz3.Shared.csproj +++ b/src/TrackerCouncil.Smz3.Shared/TrackerCouncil.Smz3.Shared.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/TrackerCouncil.Smz3.Tracking/TrackerCouncil.Smz3.Tracking.csproj b/src/TrackerCouncil.Smz3.Tracking/TrackerCouncil.Smz3.Tracking.csproj index 0b674238e..2a0a6e59c 100644 --- a/src/TrackerCouncil.Smz3.Tracking/TrackerCouncil.Smz3.Tracking.csproj +++ b/src/TrackerCouncil.Smz3.Tracking/TrackerCouncil.Smz3.Tracking.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/TrackerCouncil.Smz3.UI/Assets/Tracker.png b/src/TrackerCouncil.Smz3.UI/Assets/Tracker.png new file mode 100644 index 000000000..8622fdb3e Binary files /dev/null and b/src/TrackerCouncil.Smz3.UI/Assets/Tracker.png differ diff --git a/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs b/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs index 1cf102473..00497e858 100644 --- a/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs +++ b/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs @@ -40,7 +40,7 @@ public MainWindowViewModel InitializeModel(MainWindow window) { _window = window; _options = optionsFactory.Create(); - _model.HasInvalidOptions = !_options.GeneralOptions.Validate(); + _model.OpenSetupWindow = !_options.GeneralOptions.HasOpenedSetupWindow; ITaskService.Run(CheckForUpdates); return _model; } diff --git a/src/TrackerCouncil.Smz3.UI/Services/SetupWindowService.cs b/src/TrackerCouncil.Smz3.UI/Services/SetupWindowService.cs new file mode 100644 index 000000000..c0ee3b26b --- /dev/null +++ b/src/TrackerCouncil.Smz3.UI/Services/SetupWindowService.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography; +using System.Threading; +using System.Threading.Tasks; +using Avalonia.Media; +using AvaloniaControls; +using AvaloniaControls.ControlServices; +using Material.Icons; +using SnesConnectorLibrary; +using SnesConnectorLibrary.Requests; +using SNI; +using TrackerCouncil.Smz3.Data.Options; +using TrackerCouncil.Smz3.Shared.Enums; +using TrackerCouncil.Smz3.UI.ViewModels; + +namespace TrackerCouncil.Smz3.UI.Services; + +public class SetupWindowService(OptionsFactory optionsFactory, ISnesConnectorService snesConnectorService) : ControlService +{ + private const string Z3Hash = "03a63945398191337e896e5771f77173"; + private const string SMHash = "21f3e98df4780ee1c667b84e57d88675"; + + private SetupWindowViewModel _model = new(); + private RandomizerOptions _randomizerOptions = null!; + private CancellationTokenSource _cancellationTokenSource = new(); + + public SetupWindowViewModel GetViewModel() + { + snesConnectorService.GameDetected += SnesConnectorServiceOnConnected; + _randomizerOptions = optionsFactory.Create(); + SetZeldaRomPath(_randomizerOptions.GeneralOptions.Z3RomPath); + SetMetroidRomPath(_randomizerOptions.GeneralOptions.SMRomPath); + _randomizerOptions.GeneralOptions.HasOpenedSetupWindow = true; + _randomizerOptions.Save(); + snesConnectorService.CreateLuaScriptsFolder(_randomizerOptions.AutoTrackerScriptsOutputPath); + return _model; + } + + public bool SetRomPaths(IEnumerable romPaths) + { + var anyInvalidRom = false; + + foreach (var path in romPaths) + { + if (CheckFileHash(path, Z3Hash)) + { + _model.ZeldaRomPath = path; + _model.IsValidZeldaRom = true; + } + else if (CheckFileHash(path, SMHash)) + { + _model.MetroidRomPath = path; + _model.IsValidMetroidRom = true; + } + else + { + anyInvalidRom = true; + } + } + + return !anyInvalidRom; + } + + public async Task TestAutoTracking() + { + if (_model.IsConnecting) + { + return; + } + + _model.IsConnecting = true; + _cancellationTokenSource = new CancellationTokenSource(); + _model.AutoTrackerOpacity = 0.2f; + _model.AutoTrackerIconKind = MaterialIconKind.CircleOutline; + _model.AutoTrackerBrush = Brushes.White; + _model.AutoTrackerMessage = "Connecting..."; + + snesConnectorService.Connect(GetSnesConnectorSettings()); + + try + { + await Task.Delay(TimeSpan.FromSeconds(20), _cancellationTokenSource.Token); + + // If the task wasn't cancelled, then it didn't connect at all fully + _model.AutoTrackerOpacity = 1; + _model.AutoTrackerIconKind = MaterialIconKind.CloseCircleOutline; + _model.AutoTrackerBrush = Brushes.IndianRed; + _model.AutoTrackerMessage = "Unable to connect"; + await _cancellationTokenSource.CancelAsync(); + } + catch + { + // Do nothing + } + + _model.IsConnecting = false; + snesConnectorService.Disconnect(); + } + + public void SaveSettings() + { + if (_model.IsValidZeldaRom) + { + _randomizerOptions.GeneralOptions.Z3RomPath = _model.ZeldaRomPath; + } + + if (_model.IsValidMetroidRom) + { + _randomizerOptions.GeneralOptions.SMRomPath = _model.MetroidRomPath; + } + + _randomizerOptions.GeneralOptions.SnesConnectorSettings = GetSnesConnectorSettings(); + + if (!_model.TrackerVoiceEnabled) + { + _randomizerOptions.GeneralOptions.SpeechRecognitionMode = SpeechRecognitionMode.Disabled; + _randomizerOptions.GeneralOptions.TrackerVoiceFrequency = TrackerVoiceFrequency.Disabled; + } + + _randomizerOptions.GeneralOptions.SelectedProfiles = GetSelectedProfiles(); + _randomizerOptions.Save(); + } + + public void OnClose() + { + snesConnectorService.GameDetected -= SnesConnectorServiceOnConnected; + snesConnectorService.Disconnect(); + } + + public void OpenLuaFolder() + { + CrossPlatformTools.OpenDirectory(_randomizerOptions.AutoTrackerScriptsOutputPath); + } + + private SnesConnectorSettings GetSnesConnectorSettings() + { + var snesConnectorSettings = new SnesConnectorSettings(); + + if (_model.AutoTrackingDisable) + { + snesConnectorSettings.ConnectorType = SnesConnectorType.None; + } + else if (_model.AutoTrackingLua) + { + snesConnectorSettings.ConnectorType = SnesConnectorType.Lua; + } + else if (_model.AutoTrackingEmoTracker) + { + snesConnectorSettings.ConnectorType = SnesConnectorType.LuaEmoTracker; + } + else if (_model.AutoTrackingUsb2Snes) + { + snesConnectorSettings.ConnectorType = SnesConnectorType.Usb2Snes; + snesConnectorSettings.Usb2SnesAddress = _model.ConnectorIpAddress; + } + else if (_model.AutoTrackingSni) + { + snesConnectorSettings.ConnectorType = SnesConnectorType.Sni; + snesConnectorSettings.SniAddress = _model.ConnectorIpAddress; + } + + return snesConnectorSettings; + } + + private List GetSelectedProfiles() + { + var profiles = new List(); + + if (_model.TrackerSassEnabled) + { + profiles.Add("Sassy"); + } + + if (_model.TrackerCursingEnabled) + { + profiles.Add("Rated T for Teen"); + } + + if (_model.TrackerBcuEnabled) + { + profiles.Add("BCU"); + } + + return profiles; + } + + private void SetZeldaRomPath(string? path) + { + if (File.Exists(path) && CheckFileHash(path, Z3Hash)) + { + _model.ZeldaRomPath = path; + _model.IsValidZeldaRom = true; + } + else + { + _model.ZeldaRomPath = "Not Selected"; + _model.IsValidZeldaRom = false; + } + } + + private void SetMetroidRomPath(string? path) + { + if (File.Exists(path) && CheckFileHash(path, SMHash)) + { + _model.MetroidRomPath = path; + _model.IsValidMetroidRom = true; + } + else + { + _model.MetroidRomPath = "Not Selected"; + _model.IsValidMetroidRom = false; + } + } + + private bool CheckFileHash(string path, string expectedHash) + { + var bytes = File.ReadAllBytes(path); + var hash = MD5.HashData(bytes); + var hashString = BitConverter.ToString(hash).Replace("-", ""); + return expectedHash.Equals(hashString, StringComparison.OrdinalIgnoreCase); + } + + private void SnesConnectorServiceOnConnected(object? sender, EventArgs e) + { + _ = TestGetMemoryAsync(); + } + + private async Task TestGetMemoryAsync() + { + for (var i = 0; i < 5 && !_cancellationTokenSource.IsCancellationRequested; i++) + { + var response = await snesConnectorService.MakeMemoryRequestAsync(new SnesSingleMemoryRequest() + { + MemoryRequestType = SnesMemoryRequestType.RetrieveMemory, + SnesMemoryDomain = SnesMemoryDomain.ConsoleRAM, + AddressFormat = AddressFormat.Snes9x, + SniMemoryMapping = MemoryMapping.Unknown, + Address = 0x7e0000, + Length = 0x1 + }); + + if (response is { Successful: true, HasData: true }) + { + _model.AutoTrackerOpacity = 1; + _model.AutoTrackerIconKind = MaterialIconKind.CheckCircleOutline; + _model.AutoTrackerBrush = Brushes.Lime; + _model.AutoTrackerMessage = "Connection successful!"; + break; + } + else + { + _model.AutoTrackerOpacity = 1; + _model.AutoTrackerIconKind = MaterialIconKind.CloseCircleOutline; + _model.AutoTrackerBrush = Brushes.IndianRed; + _model.AutoTrackerMessage = "Invalid response"; + await Task.Delay(TimeSpan.FromSeconds(2f)); + } + } + + await _cancellationTokenSource.CancelAsync(); + } +} diff --git a/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj b/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj index a481bd2d2..40ac3512f 100644 --- a/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj +++ b/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj @@ -21,7 +21,7 @@ - + diff --git a/src/TrackerCouncil.Smz3.UI/ViewModels/MainWindowViewModel.cs b/src/TrackerCouncil.Smz3.UI/ViewModels/MainWindowViewModel.cs index 11f7140ee..7fed220cd 100644 --- a/src/TrackerCouncil.Smz3.UI/ViewModels/MainWindowViewModel.cs +++ b/src/TrackerCouncil.Smz3.UI/ViewModels/MainWindowViewModel.cs @@ -13,5 +13,5 @@ public MainWindowViewModel() public string NewVersionGitHubUrl { get; set; } = ""; - public bool HasInvalidOptions { get; set; } + public bool OpenSetupWindow { get; set; } } diff --git a/src/TrackerCouncil.Smz3.UI/ViewModels/SetupWindowViewModel.cs b/src/TrackerCouncil.Smz3.UI/ViewModels/SetupWindowViewModel.cs new file mode 100644 index 000000000..d15306e92 --- /dev/null +++ b/src/TrackerCouncil.Smz3.UI/ViewModels/SetupWindowViewModel.cs @@ -0,0 +1,82 @@ +using Avalonia.Markup.Xaml.MarkupExtensions; +using Avalonia.Media; +using AvaloniaControls.Models; +using Material.Icons; +using ReactiveUI.Fody.Helpers; + +namespace TrackerCouncil.Smz3.UI.ViewModels; + +public class SetupWindowViewModel : ViewModelBase +{ + + [Reactive, + ReactiveLinkedProperties(nameof(Step2BorderOpacity), nameof(Step3BorderOpacity), nameof(Step4BorderOpacity), + nameof(Step1ButtonOpacity), nameof(Step2ButtonOpacity), nameof(Step3ButtonOpacity), + nameof(Step4ButtonOpacity), nameof(DisplayPage1), nameof(DisplayPage2), nameof(DisplayPage3), + nameof(DisplayPage4), nameof(PreviousButtonEnabled), nameof(SkipStepVisible), nameof(NextButtonText), + nameof(NextButtonEnabled))] + public int StepNumber { get; set; } = 2; + + public float Step1ButtonOpacity => StepNumber == 1 ? 1f : 0.2f; + public float Step2ButtonOpacity => StepNumber == 2 ? 1f : 0.2f; + public float Step3ButtonOpacity => StepNumber == 3 ? 1f : 0.2f; + public float Step4ButtonOpacity => StepNumber == 4 ? 1f : 0.2f; + + public float Step1BorderOpacity => 1; + public float Step2BorderOpacity => StepNumber > 1 ? 1f : 0.2f; + public float Step3BorderOpacity => StepNumber > 2 ? 1f : 0.2f; + public float Step4BorderOpacity => StepNumber > 3 ? 1f : 0.2f; + + public bool PreviousButtonEnabled => StepNumber > 1; + public bool SkipStepVisible => StepNumber == 1; + public string NextButtonText => StepNumber == 4 ? "Close" : "Next"; + public bool NextButtonEnabled => (StepNumber == 1 && IsValidZeldaRom && IsValidMetroidRom) || StepNumber != 1; + + // Page 1 Properties + public bool DisplayPage1 => StepNumber == 1; + + [Reactive, ReactiveLinkedProperties(nameof(ZeldaRomIconOpacity), nameof(ZeldaRomBrush), nameof(ZeldaRomIconKind), nameof(NextButtonEnabled))] + public bool IsValidZeldaRom { get; set; } + public float ZeldaRomIconOpacity => IsValidZeldaRom ? 1f : 0.2f; + public IBrush ZeldaRomBrush => IsValidZeldaRom ? Brushes.LimeGreen : Brushes.White; + public MaterialIconKind ZeldaRomIconKind => IsValidZeldaRom ? MaterialIconKind.CheckCircleOutline : MaterialIconKind.CircleOutline; + [Reactive] public string ZeldaRomPath { get; set; } = "Not Selected"; + + [Reactive, ReactiveLinkedProperties(nameof(MetroidRomIconOpacity), nameof(MetroidRomBrush), nameof(MetroidRomIconKind), nameof(NextButtonEnabled))] + public bool IsValidMetroidRom { get; set; } + public float MetroidRomIconOpacity => IsValidMetroidRom ? 1f : 0.2f; + public IBrush MetroidRomBrush => IsValidMetroidRom ? Brushes.LimeGreen : Brushes.White; + public MaterialIconKind MetroidRomIconKind => IsValidMetroidRom ? MaterialIconKind.CheckCircleOutline : MaterialIconKind.CircleOutline; + [Reactive] public string MetroidRomPath { get; set; } = "Not Selected"; + + // Page 2 Properties + public bool DisplayPage2 => StepNumber == 2; + [Reactive, ReactiveLinkedProperties(nameof(TestAutoTrackerEnabled))] public bool AutoTrackingDisable { get; set; } = true; + public bool AutoTrackingLua { get; set; } + public bool AutoTrackingEmoTracker { get; set; } + [Reactive, ReactiveLinkedProperties(nameof(ConnectorIpAddressTextBoxEnabled))] public bool AutoTrackingUsb2Snes { get; set; } + [Reactive, ReactiveLinkedProperties(nameof(ConnectorIpAddressTextBoxEnabled))] public bool AutoTrackingSni { get; set; } + public string ConnectorIpAddress { get; set; } = ""; + public bool ConnectorIpAddressTextBoxEnabled => AutoTrackingUsb2Snes || AutoTrackingSni; + public bool TestAutoTrackerEnabled => !AutoTrackingDisable && !IsConnecting; + [Reactive] public IBrush AutoTrackerBrush { get; set; } = Brushes.White; + [Reactive] public MaterialIconKind AutoTrackerIconKind { get; set; } = MaterialIconKind.CircleOutline; + [Reactive] public float AutoTrackerOpacity { get; set; } = 0.2f; + [Reactive] public string AutoTrackerMessage { get; set; } = ""; + [Reactive, ReactiveLinkedProperties(nameof(TestAutoTrackerEnabled))] public bool IsConnecting { get; set; } + + // Page 3 Properties + public bool DisplayPage3 => StepNumber == 3; + public bool TrackerVoiceEnabled { get; set; } = true; + public bool TrackerVoiceDisabled { get; set; } + public bool TrackerSassEnabled { get; set; } = true; + public bool TrackerSassDisabled { get; set; } + public bool TrackerCursingEnabled { get; set; } + public bool TrackerCursingDisabled { get; set; } = true; + public bool TrackerBcuEnabled { get; set; } + public bool TrackerBcuDisabled { get; set; } = true; + + public bool DisplayPage4 => StepNumber == 4; + + +} diff --git a/src/TrackerCouncil.Smz3.UI/Views/AutoTrackingHelpWindow.axaml b/src/TrackerCouncil.Smz3.UI/Views/AutoTrackingHelpWindow.axaml index ae69d87f3..f51ffadb1 100644 --- a/src/TrackerCouncil.Smz3.UI/Views/AutoTrackingHelpWindow.axaml +++ b/src/TrackerCouncil.Smz3.UI/Views/AutoTrackingHelpWindow.axaml @@ -44,8 +44,48 @@ • BizHawk (BSNES Core Only) + + An alternate Lua Script mode for compatibility with the EmoTracker Lua script is also available if you use that for other randomizers. + + - • QUSB2SNES + • (Q)Usb2Snes + + + + Supported Emulators: + + + + • RetroArch (SNES9X or BSNES Cores) + • Snes9x-emunwa + • Snes9x-rr (by loading the QUsb2Snes Lua Script) + • BizHawk (by loading the QUsb2Snes Lua Script) + • Hardware such as the FxPakPro + + + + QUsb2Snes must be installed and running to connect to the emulator. + + + + • Super Nintendo Interface (SNI) + + + + Supported Emulators: + + + + • RetroArch (SNES9X or BSNES Cores) + • Snes9x-emunwa + • Snes9x-rr (by loading the SNI Lua Script) + • BizHawk (by loading the SNI Lua Script) + • Hardware such as the FxPakPro + + + + SNI must be installed and running to connect to the emulator. @@ -88,6 +128,30 @@ 3. Open the connector.lua script file. + + Enabling Connectivity in RetroArch + + + + 1. Open RetroArch + + + + 2. Go to Settings + + + + 3. Go to Network + + + + 4. Set Network Commands to "On" + + ().ShowDialog(this); - } - if (_service == null) { return; @@ -94,6 +86,20 @@ await MessageWindow.ShowInfoDialog( _ = ITaskService.Run(_service.ValidateTwitchToken); _ = ITaskService.Run(_service.DownloadConfigsAsync); _ = ITaskService.Run(_service.DownloadSpritesAsync); + + if (_model.OpenSetupWindow && _serviceProvider != null) + { + var result = await _serviceProvider.GetRequiredService() + .ShowDialog(this, SetupWindowStep.Roms); + if (result == SetupWindowCloseBehavior.OpenSettingsWindow) + { + _serviceProvider?.GetRequiredService().ShowDialog(this); + } + else if (result == SetupWindowCloseBehavior.OpenGenerationWindow) + { + _ = SoloRomListPanel.OpenGenerationWindow(); + } + } } private void OptionsMenuItem_OnClick(object? sender, RoutedEventArgs e) diff --git a/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml b/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml new file mode 100644 index 000000000..b5851d237 --- /dev/null +++ b/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Tracker Presents: SMZ3 Cas' Randomizer + + + + + + + Let's get you setup. First, we need the ROMs for A Link to the Past and Super Metroid. + + + + + + + File: + + + + + + + + + File: + + + + + + + + + + + + + Want to make your life easier? Tracker can track items, bosses, rewards, and more automatically by connecting to your emulator. + + + + + + Disable Auto Tracking + + + Enable Lua Auto Tracking (snes9x-rr, BizHawk) + Open Lua Script Folder + + + Enable EmoTracker Lua Auto Tracking (snes9x-rr, BizHawk) + Enable QUsb2Snes Auto Tracking (RetroArch, snes9x-emunwa, snes9x-rr, FxPakPro) + Enable SNI Auto Tracking (RetroArch, snes9x-emunwa, snes9x-rr, FxPakPro) + + + + + + + + + + + + + + + + Tracker can be your randomizer assistant. Let's customize your interactions with tracker. + + + + + Would you like to talk with Tracker? + + + Yes, let her speak! + No, I want peace and quiet. + + + Would you like Tracker to have a personality? + + + Yes, bring on the sass! + No, keep it to strictly business. + + + Are you okay with Tracker cursing? + + + Hell yeah! + Heck no. + + + Do you know who betus is? + + + Yeah, give me the in-jokes! + Who is that? + + + + + + + + + + + The basic setup is now complete! What would you like to do next? + + + + + + You can open the full settings window to change other settings such as enabling Twitch integration, + modifying the tracker UI background, and modifying other tracking behavior. + + + + + + Or, if you're ready to get started, you can open the window to start generating your first randomizer seed! + + + + + + + + + + + + + Art by Dr. Dubz + + + + + +