diff --git a/PKHeX.Avalonia/ViewModels/MainWindowViewModel.cs b/PKHeX.Avalonia/ViewModels/MainWindowViewModel.cs index 2fac9adb2..54ed623fe 100644 --- a/PKHeX.Avalonia/ViewModels/MainWindowViewModel.cs +++ b/PKHeX.Avalonia/ViewModels/MainWindowViewModel.cs @@ -811,7 +811,7 @@ private async Task ExportBoxShowdownAsync() try { var box = SaveFile.GetBoxData(SavEditor.CurrentBox); - var text = string.Join("\n\n", box.Where(p => p.Species > 0).Select(ShowdownParsing.GetShowdownText)); + var text = string.Join("\n\n", box.Where(p => p is not null && p.Species > 0).Select(ShowdownParsing.GetShowdownText)); if (string.IsNullOrWhiteSpace(text)) { StatusMessage = "No Pokemon in box to export."; diff --git a/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs b/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs index 539581378..fc2e881b1 100644 --- a/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs +++ b/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs @@ -338,9 +338,13 @@ public string NatureTooltip [ObservableProperty] private ComboItem? _selectedAlphaMove; [ObservableProperty] private bool _hasAlphaMove; - // Move Shop / Tech Record visibility + // Move Shop / Tech Record / Plus Record visibility [ObservableProperty] private bool _hasMoveShop; [ObservableProperty] private bool _hasTechRecords; + [ObservableProperty] private bool _hasPlusRecord; + + // Super Training (Medals) visibility — Gen 6 + [ObservableProperty] private bool _hasSuperTraining; // Gen-specific: Catch Rate (Gen 1) [ObservableProperty] private int _catchRate; @@ -1478,6 +1482,12 @@ public void PopulateFields(PKM pk) // Tech Records (Gen 8+) HasTechRecords = pk is ITechRecord; + // Plus Records (Gen 9a - Z:A) + HasPlusRecord = pk is IPlusRecord; + + // Super Training / Medals (Gen 6) + HasSuperTraining = pk is ISuperTrainRegimen; + // Origin Mark indicator var gen = pk.Generation; HasOriginMark = gen >= 3; @@ -1896,6 +1906,39 @@ private async Task OpenTechRecords() catch (Exception ex) { LegalityReport = $"Tech Record error: {ex.Message}"; } } + [RelayCommand] + private async Task OpenPlusRecord() + { + if (Entity is not IPlusRecord plus) return; + if (Entity.PersonalInfo is not IPermitPlus permit) return; + try + { + PreparePKM(); + var vm = new PlusRecordEditorViewModel(plus, permit, Entity); + var view = new PlusRecordEditorView { DataContext = vm }; + var mainWindow = (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow; + if (mainWindow != null) + await view.ShowDialog(mainWindow); + } + catch (Exception ex) { LegalityReport = $"Plus Record error: {ex.Message}"; } + } + + [RelayCommand] + private async Task OpenMedals() + { + if (Entity is not ISuperTrainRegimen st) return; + try + { + PreparePKM(); + var vm = new SuperTrainingEditorViewModel(st); + var view = new SuperTrainingEditorView { DataContext = vm }; + var mainWindow = (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow; + if (mainWindow != null) + await view.ShowDialog(mainWindow); + } + catch (Exception ex) { LegalityReport = $"Super Training error: {ex.Message}"; } + } + // --- Ribbons / Memories commands --- [RelayCommand] diff --git a/PKHeX.Avalonia/ViewModels/SAVEditorViewModel.cs b/PKHeX.Avalonia/ViewModels/SAVEditorViewModel.cs index d0fa8a1b4..d378503b5 100644 --- a/PKHeX.Avalonia/ViewModels/SAVEditorViewModel.cs +++ b/PKHeX.Avalonia/ViewModels/SAVEditorViewModel.cs @@ -287,6 +287,7 @@ private void RefreshBox() for (int i = 0; i < slotCount && i < BoxSlots.Count; i++) { var pk = _sav.GetBoxSlotAtIndex(CurrentBox, i); + if (pk is null) continue; BoxSlots[i].Entity = pk; if (pk.Species == 0) { @@ -310,6 +311,7 @@ private void RefreshParty() for (int i = 0; i < _sav.PartyCount && i < PartySlots.Count; i++) { var pk = _sav.GetPartySlotAtIndex(i); + if (pk is null) continue; PartySlots[i].Entity = pk; if (pk.Species == 0) { @@ -388,7 +390,8 @@ private void SetSlot(SlotModel? slot) if (boxIndex >= 0) { var existing = _sav.GetBoxSlotAtIndex(CurrentBox, boxIndex); - PushUndo(CurrentBox, boxIndex, existing, isParty: false); + if (existing is not null) + PushUndo(CurrentBox, boxIndex, existing, isParty: false); _sav.SetBoxSlotAtIndex(pk, CurrentBox, boxIndex); RefreshBox(); return; @@ -398,7 +401,8 @@ private void SetSlot(SlotModel? slot) if (partyIndex >= 0) { var existing = _sav.GetPartySlotAtIndex(partyIndex); - PushUndo(0, partyIndex, existing, isParty: true); + if (existing is not null) + PushUndo(0, partyIndex, existing, isParty: true); _sav.SetPartySlotAtIndex(pk, partyIndex); RefreshParty(); } @@ -426,7 +430,8 @@ private void DeleteSlot(SlotModel? slot) if (boxIndex >= 0) { var existing = _sav.GetBoxSlotAtIndex(CurrentBox, boxIndex); - PushUndo(CurrentBox, boxIndex, existing, isParty: false); + if (existing is not null) + PushUndo(CurrentBox, boxIndex, existing, isParty: false); _sav.SetBoxSlotAtIndex(_sav.BlankPKM, CurrentBox, boxIndex); RefreshBox(); return; @@ -436,7 +441,8 @@ private void DeleteSlot(SlotModel? slot) if (partyIndex >= 0) { var existing = _sav.GetPartySlotAtIndex(partyIndex); - PushUndo(0, partyIndex, existing, isParty: true); + if (existing is not null) + PushUndo(0, partyIndex, existing, isParty: true); _sav.DeletePartySlot(partyIndex); RefreshParty(); } @@ -524,6 +530,7 @@ private void RefreshExtraSlots(SaveFile sav) foreach (var slotInfo in extras) { var pk = slotInfo.Read(sav); + if (pk is null) continue; var model = new SlotModel { Slot = slotInfo.Slot, @@ -675,7 +682,7 @@ private void VerifyAllPkm() for (int slot = 0; slot < _sav.BoxSlotCount; slot++) { var pk = _sav.GetBoxSlotAtIndex(box, slot); - if (pk.Species == 0) continue; + if (pk is null || pk.Species == 0) continue; total++; var la = new LegalityAnalysis(pk); if (la.Valid) legal++; else illegal++; diff --git a/PKHeX.Avalonia/Views/PKMEditorView.axaml b/PKHeX.Avalonia/Views/PKMEditorView.axaml index 0c6ed1e52..6ff5e74eb 100644 --- a/PKHeX.Avalonia/Views/PKMEditorView.axaml +++ b/PKHeX.Avalonia/Views/PKMEditorView.axaml @@ -523,12 +523,14 @@ DisplayMemberBinding="{Binding Text, DataType=core:ComboItem}" Height="25" Width="200" HorizontalAlignment="Left" /> - +