Add Gen 5-6 subform dialogs

17 generation-specific subforms:

Gen 5: Misc5, Pokedex5, DLC5, UnityTower5, CGearImage5
Gen 6: Trainer6, SecretBase6, PokedexXY, PokedexORAS,
       HallOfFame6, SuperTrain6, Link6, OPower6, Pokepuff6,
       BerryFieldXY, PokeBlockORAS, Roamer6
This commit is contained in:
montanon 2026-03-15 01:09:42 -03:00
parent 1640b0f19f
commit 7f44bc2e1e
51 changed files with 4668 additions and 0 deletions

View File

@ -0,0 +1,29 @@
using CommunityToolkit.Mvvm.ComponentModel;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the C-Gear skin image display (Gen 5).
/// Shows the current C-Gear background skin dimensions and status.
/// </summary>
public partial class CGearImage5ViewModel : SaveEditorViewModelBase
{
[ObservableProperty] private bool _hasSkin;
[ObservableProperty] private string _skinStatus = "No C-Gear skin loaded";
[ObservableProperty] private int _width;
[ObservableProperty] private int _height;
public CGearImage5ViewModel(SAV5 sav) : base(sav)
{
var data = sav.CGearSkinData;
CGearBackground bg = sav is SAV5BW ? new CGearBackgroundBW(data) : new CGearBackgroundB2W2(data);
_width = CGearBackground.Width;
_height = CGearBackground.Height;
_hasSkin = !bg.IsUninitialized;
_skinStatus = _hasSkin
? $"C-Gear skin loaded ({_width}x{_height})"
: "No C-Gear skin loaded";
}
}

View File

@ -0,0 +1,164 @@
using System;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for a Battle Video entry.
/// </summary>
public class BattleVideo5Entry
{
public int Index { get; }
public string Label { get; }
public BattleVideo5Entry(int index, string label)
{
Index = index;
Label = label;
}
}
/// <summary>
/// Model for a PWT entry.
/// </summary>
public class PWT5Entry
{
public int Index { get; }
public string Label { get; }
public PWT5Entry(int index, string label)
{
Index = index;
Label = label;
}
}
/// <summary>
/// Model for a Pokestar movie entry.
/// </summary>
public class Pokestar5Entry
{
public int Index { get; }
public string Label { get; }
public Pokestar5Entry(int index, string label)
{
Index = index;
Label = label;
}
}
/// <summary>
/// ViewModel for the Gen 5 DLC content editor.
/// Manages C-Gear skins, Battle Videos, PWT, Pokestar Movies, Musical Shows, Memory Links, and Pokedex Skins.
/// </summary>
public partial class DLC5ViewModel : SaveEditorViewModelBase
{
private readonly SAV5 SAV5;
// C-Gear
[ObservableProperty] private bool _hasCGear;
[ObservableProperty] private string _cGearStatus = "Not loaded";
// Battle Videos
public ObservableCollection<BattleVideo5Entry> BattleVideos { get; } = [];
[ObservableProperty]
private int _selectedBattleVideoIndex;
// PWT (B2W2 only)
public bool ShowPWT { get; }
public ObservableCollection<PWT5Entry> PWTEntries { get; } = [];
[ObservableProperty]
private int _selectedPWTIndex;
// Pokestar (B2W2 only)
public bool ShowPokestar { get; }
public ObservableCollection<Pokestar5Entry> PokestarMovies { get; } = [];
[ObservableProperty]
private int _selectedPokestarIndex;
// Musical
[ObservableProperty] private string _musicalName = string.Empty;
// Memory Link
[ObservableProperty] private string _link1Status = "Link 1";
[ObservableProperty] private string _link2Status = "Link 2";
public DLC5ViewModel(SAV5 sav) : base(sav)
{
SAV5 = sav;
ShowPWT = sav is SAV5B2W2;
ShowPokestar = sav is SAV5B2W2;
LoadCGear();
LoadBattleVideos();
LoadPWT();
LoadPokestar();
LoadMusical();
}
private void LoadCGear()
{
var data = SAV5.CGearSkinData;
var bg = SAV5 is SAV5BW ? (CGearBackground)new CGearBackgroundBW(data) : new CGearBackgroundB2W2(data);
_hasCGear = !bg.IsUninitialized;
_cGearStatus = _hasCGear ? "C-Gear skin loaded" : "No C-Gear skin";
}
private void LoadBattleVideos()
{
for (int i = 0; i < 4; i++)
{
var data = SAV5.GetBattleVideo(i);
var bvid = new BattleVideo5(data);
var name = bvid.IsUninitialized ? "Empty" : bvid.GetTrainerNames();
BattleVideos.Add(new BattleVideo5Entry(i, $"{i:00} - {name}"));
}
}
private void LoadPWT()
{
if (SAV5 is not SAV5B2W2 b2w2)
return;
for (int i = 0; i < SAV5B2W2.PWTCount; i++)
{
var data = b2w2.GetPWT(i);
var pwt = new WorldTournament5(data);
var name = pwt.Name;
if (string.IsNullOrWhiteSpace(name))
name = "Empty";
PWTEntries.Add(new PWT5Entry(i, $"{i + 1:00} - {name}"));
}
}
private void LoadPokestar()
{
if (SAV5 is not SAV5B2W2 b2w2)
return;
for (int i = 0; i < SAV5B2W2.PokestarCount; i++)
{
var data = b2w2.GetPokestarMovie(i);
var movie = new PokestarMovie5(data);
PokestarMovies.Add(new Pokestar5Entry(i, $"{i + 1:00} - {movie.Name}"));
}
}
private void LoadMusical()
{
_musicalName = SAV5.Musical.MusicalName;
}
[RelayCommand]
private void Save()
{
SAV5.Musical.MusicalName = MusicalName;
SAV.State.Edited = true;
Modified = true;
}
}

View File

@ -0,0 +1,425 @@
using System;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for a fly destination entry (Gen 5).
/// </summary>
public partial class FlyDest5Model : ObservableObject
{
public int FlagBit { get; }
public string Name { get; }
[ObservableProperty]
private bool _unlocked;
public FlyDest5Model(int flagBit, string name, bool unlocked)
{
FlagBit = flagBit;
Name = name;
_unlocked = unlocked;
}
}
/// <summary>
/// Model for a Key System entry (B2W2).
/// </summary>
public partial class KeyEntry5Model : ObservableObject
{
public int Index { get; }
public string Label { get; }
public bool IsObtain { get; }
[ObservableProperty]
private bool _enabled;
public KeyEntry5Model(int index, string label, bool isObtain, bool enabled)
{
Index = index;
Label = label;
IsObtain = isObtain;
_enabled = enabled;
}
}
/// <summary>
/// Model for a Musical prop entry.
/// </summary>
public partial class PropModel : ObservableObject
{
public int Index { get; }
public string Name { get; }
[ObservableProperty]
private bool _obtained;
public PropModel(int index, string name, bool obtained)
{
Index = index;
Name = name;
_obtained = obtained;
}
}
/// <summary>
/// ViewModel for the Gen 5 Misc editor.
/// Covers Fly Destinations, Roamer (BW), Key System (B2W2), Musical Props, Records, and Battle Subway.
/// </summary>
public partial class Misc5ViewModel : SaveEditorViewModelBase
{
private readonly SAV5 SAV5;
private readonly BattleSubway5 Subway;
private readonly BattleSubwayPlay5 SubwayPlay;
private readonly Record5 Record;
// Fly
public ObservableCollection<FlyDest5Model> FlyDestinations { get; } = [];
private int _flyOffset;
private int[] _flyDestC = [];
// Roamer (BW only)
public bool ShowRoamer { get; }
[ObservableProperty] private int _roamer641State;
[ObservableProperty] private int _roamer642State;
[ObservableProperty] private int _roamStatus;
[ObservableProperty] private bool _libertyPass;
public string[] RoamerStates { get; } = ["Not roamed", "Roaming", "Defeated", "Captured"];
public string[] RoamStatusStates { get; } = ["Not happened", "Go to route 7", "Unknown (2)", "Event finished"];
// Key System (B2W2 only)
public bool ShowKeySystem { get; }
public ObservableCollection<KeyEntry5Model> KeyEntries { get; } = [];
// Musical Props
public ObservableCollection<PropModel> Props { get; } = [];
// Battle Subway
[ObservableProperty] private int _subwayCurrentType;
[ObservableProperty] private int _subwayCurrentBattle;
// Subway flags
[ObservableProperty] private bool _subwayFlag0;
[ObservableProperty] private bool _subwayFlag1;
[ObservableProperty] private bool _subwayFlag2;
[ObservableProperty] private bool _subwayFlag3;
[ObservableProperty] private bool _superSingle;
[ObservableProperty] private bool _superDouble;
[ObservableProperty] private bool _superMulti;
[ObservableProperty] private bool _subwayFlag7;
[ObservableProperty] private bool _npcMet;
// Subway records
[ObservableProperty] private int _singlePast;
[ObservableProperty] private int _singleRecord;
[ObservableProperty] private int _doublePast;
[ObservableProperty] private int _doubleRecord;
[ObservableProperty] private int _multiNpcPast;
[ObservableProperty] private int _multiNpcRecord;
[ObservableProperty] private int _multiFriendsPast;
[ObservableProperty] private int _multiFriendsRecord;
[ObservableProperty] private int _superSinglePast;
[ObservableProperty] private int _superSingleRecord;
[ObservableProperty] private int _superDoublePast;
[ObservableProperty] private int _superDoubleRecord;
[ObservableProperty] private int _superMultiNpcPast;
[ObservableProperty] private int _superMultiNpcRecord;
[ObservableProperty] private int _superMultiFriendsPast;
[ObservableProperty] private int _superMultiFriendsRecord;
// Records
[ObservableProperty] private int _record16Index;
[ObservableProperty] private int _record16Value;
[ObservableProperty] private int _record32Index;
[ObservableProperty] private uint _record32Value;
public Misc5ViewModel(SAV5 sav) : base(sav)
{
SAV5 = sav;
Subway = sav.BattleSubway;
SubwayPlay = sav.BattleSubwayPlay;
Record = sav.Records;
ReadFly();
ReadRoamer();
ReadKeySystem();
ReadMusical();
ReadSubway();
ReadRecords();
ShowRoamer = sav is SAV5BW;
ShowKeySystem = sav is SAV5B2W2;
}
private void ReadFly()
{
string[] flyNames;
switch (SAV5.Version)
{
case GameVersion.B or GameVersion.W or GameVersion.BW:
_flyOffset = 0x204B2;
flyNames = [
"Nuvema Town", "Accumula Town", "Striaton City", "Nacrene City",
"Castelia City", "Nimbasa City", "Driftveil City", "Mistralton City",
"Icirrus City", "Opelucid City", "Victory Road", "Pokemon League",
"Lacunosa Town", "Undella Town", "Black City/White Forest", "(Unity Tower)",
];
_flyDestC = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 11, 10, 13, 12, 14];
break;
case GameVersion.B2 or GameVersion.W2 or GameVersion.B2W2:
_flyOffset = 0x20392;
flyNames = [
"Aspertia City", "Floccesy Town", "Virbank City",
"Nuvema Town", "Accumula Town", "Striaton City", "Nacrene City",
"Castelia City", "Nimbasa City", "Driftveil City", "Mistralton City",
"Icirrus City", "Opelucid City",
"Lacunosa Town", "Undella Town", "Black City/White Forest",
"Lentimas Town", "Humilau City", "Victory Road", "Pokemon League",
"Pokestar Studios", "Join Avenue", "PWT", "(Unity Tower)",
];
_flyDestC = [24, 27, 25, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 20, 28, 26, 66, 19, 5, 6, 7, 22];
break;
default:
flyNames = [];
break;
}
uint valFly = ReadUInt32LittleEndian(SAV5.Data[_flyOffset..]);
for (int i = 0; i < flyNames.Length; i++)
{
bool isSet;
if (_flyDestC[i] < 32)
isSet = (valFly & (1u << _flyDestC[i])) != 0;
else
isSet = (SAV5.Data[_flyOffset + (_flyDestC[i] >> 3)] & (1 << (_flyDestC[i] & 7))) != 0;
FlyDestinations.Add(new FlyDest5Model(_flyDestC[i], flyNames[i], isSet));
}
}
private void ReadRoamer()
{
if (SAV5 is SAV5BW bw)
{
var encount = bw.Encount;
_roamer641State = Math.Clamp((int)encount.GetRoamerState(1), (int)0, (int)3);
_roamer642State = Math.Clamp((int)encount.GetRoamerState(0), (int)0, (int)3);
_roamStatus = Math.Clamp((int)bw.EventWork.GetWorkRoamer(), (int)0, (int)3);
_libertyPass = bw.Misc.IsLibertyTicketActivated;
}
}
private void ReadKeySystem()
{
if (SAV5 is SAV5B2W2 b2w2)
{
var keys = b2w2.Keys;
string[] keyNames = ["EasyKey", "ChallengeKey", "CityKey", "IronKey", "IcebergKey"];
for (int i = 0; i < 5; i++)
{
KeyEntries.Add(new KeyEntry5Model(i, $"Obtain {keyNames[i]}", true, keys.GetIsKeyObtained((KeyType5)i)));
KeyEntries.Add(new KeyEntry5Model(i, $"Unlock {keyNames[i]}", false, keys.GetIsKeyUnlocked((KeyType5)i)));
}
}
}
private void ReadMusical()
{
var musical = SAV5.Musical;
// Musical has 100 props
for (int i = 0; i < 100; i++)
{
var name = $"Prop {i:000}";
Props.Add(new PropModel(i, name, musical.GetHasProp(i)));
}
}
private void ReadSubway()
{
_subwayCurrentType = SubwayPlay.CurrentType;
_subwayCurrentBattle = SubwayPlay.CurrentBattle;
_subwayFlag0 = Subway.Flag0;
_subwayFlag1 = Subway.Flag1;
_subwayFlag2 = Subway.Flag2;
_subwayFlag3 = Subway.Flag3;
_superSingle = Subway.SuperSingle;
_superDouble = Subway.SuperDouble;
_superMulti = Subway.SuperMulti;
_subwayFlag7 = Subway.Flag7;
_npcMet = Subway.NPCMet;
_singlePast = Subway.SinglePast;
_singleRecord = Subway.SingleRecord;
_doublePast = Subway.DoublePast;
_doubleRecord = Subway.DoubleRecord;
_multiNpcPast = Subway.MultiNPCPast;
_multiNpcRecord = Subway.MultiNPCRecord;
_multiFriendsPast = Subway.MultiFriendsPast;
_multiFriendsRecord = Subway.MultiFriendsRecord;
_superSinglePast = Subway.SuperSinglePast;
_superSingleRecord = Subway.SuperSingleRecord;
_superDoublePast = Subway.SuperDoublePast;
_superDoubleRecord = Subway.SuperDoubleRecord;
_superMultiNpcPast = Subway.SuperMultiNPCPast;
_superMultiNpcRecord = Subway.SuperMultiNPCRecord;
_superMultiFriendsPast = Subway.SuperMultiFriendsPast;
_superMultiFriendsRecord = Subway.SuperMultiFriendsRecord;
}
private void ReadRecords()
{
_record16Value = Record.GetRecord16(0);
_record32Value = Record.GetRecord32(0);
}
partial void OnRecord16IndexChanged(int value)
{
if (value >= 0 && value < Record5.Record16)
Record16Value = Record.GetRecord16(value);
}
partial void OnRecord32IndexChanged(int value)
{
if (value >= 0 && value < Record5.Record32)
Record32Value = Record.GetRecord32(value);
}
[RelayCommand]
private void UnlockAllFlyDest()
{
foreach (var dest in FlyDestinations)
dest.Unlocked = true;
}
[RelayCommand]
private void UnlockAllKeys()
{
foreach (var entry in KeyEntries)
entry.Enabled = true;
}
[RelayCommand]
private void UnlockAllProps()
{
foreach (var prop in Props)
prop.Obtained = true;
}
[RelayCommand]
private void Save()
{
SaveFly();
SaveRoamer();
SaveKeySystem();
SaveMusical();
SaveSubway();
SaveRecords();
SAV.State.Edited = true;
Modified = true;
}
private void SaveFly()
{
uint valFly = ReadUInt32LittleEndian(SAV5.Data[_flyOffset..]);
for (int i = 0; i < FlyDestinations.Count; i++)
{
var dest = FlyDestinations[i];
if (_flyDestC[i] < 32)
{
if (dest.Unlocked)
valFly |= 1u << _flyDestC[i];
else
valFly &= ~(1u << _flyDestC[i]);
}
else
{
var ofs = _flyOffset + (_flyDestC[i] >> 3);
SAV5.Data[ofs] = (byte)((SAV5.Data[ofs] & ~(1 << (_flyDestC[i] & 7))) | ((dest.Unlocked ? 1 : 0) << (_flyDestC[i] & 7)));
}
}
WriteUInt32LittleEndian(SAV5.Data[_flyOffset..], valFly);
}
private void SaveRoamer()
{
if (SAV5 is SAV5BW bw)
{
var encount = bw.Encount;
encount.SetRoamerState(1, (byte)Roamer641State);
encount.SetRoamerState(0, (byte)Roamer642State);
bw.EventWork.SetWorkRoamer((ushort)RoamStatus);
if (LibertyPass != bw.Misc.IsLibertyTicketActivated)
bw.Misc.IsLibertyTicketActivated = LibertyPass;
}
}
private void SaveKeySystem()
{
if (SAV5 is SAV5B2W2 b2w2)
{
var keys = b2w2.Keys;
for (int i = 0; i < 5; i++)
{
var obtainIndex = i * 2;
var unlockIndex = obtainIndex + 1;
keys.SetIsKeyObtained((KeyType5)i, KeyEntries[obtainIndex].Enabled);
keys.SetIsKeyUnlocked((KeyType5)i, KeyEntries[unlockIndex].Enabled);
}
}
}
private void SaveMusical()
{
var musical = SAV5.Musical;
foreach (var prop in Props)
musical.SetHasProp(prop.Index, prop.Obtained);
}
private void SaveSubway()
{
SubwayPlay.CurrentType = SubwayCurrentType;
SubwayPlay.CurrentBattle = SubwayCurrentBattle;
Subway.Flag0 = SubwayFlag0;
Subway.Flag1 = SubwayFlag1;
Subway.Flag2 = SubwayFlag2;
Subway.Flag3 = SubwayFlag3;
Subway.SuperSingle = SuperSingle;
Subway.SuperDouble = SuperDouble;
Subway.SuperMulti = SuperMulti;
Subway.Flag7 = SubwayFlag7;
Subway.NPCMet = NpcMet;
Subway.SinglePast = SinglePast;
Subway.SingleRecord = SingleRecord;
Subway.DoublePast = DoublePast;
Subway.DoubleRecord = DoubleRecord;
Subway.MultiNPCPast = MultiNpcPast;
Subway.MultiNPCRecord = MultiNpcRecord;
Subway.MultiFriendsPast = MultiFriendsPast;
Subway.MultiFriendsRecord = MultiFriendsRecord;
Subway.SuperSinglePast = SuperSinglePast;
Subway.SuperSingleRecord = SuperSingleRecord;
Subway.SuperDoublePast = SuperDoublePast;
Subway.SuperDoubleRecord = SuperDoubleRecord;
Subway.SuperMultiNPCPast = SuperMultiNpcPast;
Subway.SuperMultiNPCRecord = SuperMultiNpcRecord;
Subway.SuperMultiFriendsPast = SuperMultiFriendsPast;
Subway.SuperMultiFriendsRecord = SuperMultiFriendsRecord;
}
private void SaveRecords()
{
Record.SetRecord16(Record16Index, (ushort)Record16Value);
Record.SetRecord32(Record32Index, Record32Value);
Record.EndAccess();
}
}

View File

@ -0,0 +1,208 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for a single Gen 5 Pokedex species entry.
/// </summary>
public partial class Pokedex5EntryModel : ObservableObject
{
public ushort Species { get; }
public string Label { get; }
// Caught
[ObservableProperty] private bool _caught;
// Seen: Male, Female, Male Shiny, Female Shiny
[ObservableProperty] private bool _seenMale;
[ObservableProperty] private bool _seenFemale;
[ObservableProperty] private bool _seenMaleShiny;
[ObservableProperty] private bool _seenFemaleShiny;
// Displayed: Male, Female, Male Shiny, Female Shiny
[ObservableProperty] private bool _dispMale;
[ObservableProperty] private bool _dispFemale;
[ObservableProperty] private bool _dispMaleShiny;
[ObservableProperty] private bool _dispFemaleShiny;
// Language flags (7 languages: JPN, ENG, FRE, ITA, GER, SPA, KOR)
[ObservableProperty] private bool[] _languages;
public bool HasLanguages { get; }
public Pokedex5EntryModel(ushort species, string label, bool hasLanguages)
{
Species = species;
Label = label;
HasLanguages = hasLanguages;
_languages = new bool[7];
}
}
/// <summary>
/// ViewModel for the Gen 5 Pokedex editor.
/// Edits seen/caught/language/form status per species.
/// </summary>
public partial class Pokedex5ViewModel : SaveEditorViewModelBase
{
private readonly SAV5 SAV5;
private readonly Zukan5 Dex;
private const int LangCount = 7;
[ObservableProperty] private string _searchText = string.Empty;
[ObservableProperty] private bool _nationalDexUnlocked;
[ObservableProperty] private bool _nationalDexActive;
[ObservableProperty] private string _spindaPid = "00000000";
public ObservableCollection<Pokedex5EntryModel> AllEntries { get; } = [];
[ObservableProperty]
private ObservableCollection<Pokedex5EntryModel> _filteredEntries = [];
public Pokedex5ViewModel(SAV5 sav) : base(sav)
{
SAV5 = sav;
Dex = sav.Zukan;
_nationalDexUnlocked = Dex.IsNationalDexUnlocked;
_nationalDexActive = Dex.IsNationalDexMode;
_spindaPid = Dex.Spinda.ToString("X8");
var speciesNames = GameInfo.Strings.specieslist;
for (ushort i = 1; i <= sav.MaxSpeciesID; i++)
{
var name = i < speciesNames.Length ? speciesNames[i] : $"Species {i}";
var label = $"{i:000} - {name}";
bool hasLangs = i <= 493; // Language flags only for Gen 1-4 species
var entry = new Pokedex5EntryModel(i, label, hasLangs)
{
Caught = Dex.GetCaught(i),
SeenMale = Dex.GetSeen(i, 0),
SeenFemale = Dex.GetSeen(i, 1),
SeenMaleShiny = Dex.GetSeen(i, 2),
SeenFemaleShiny = Dex.GetSeen(i, 3),
DispMale = Dex.GetDisplayed(i, 0),
DispFemale = Dex.GetDisplayed(i, 1),
DispMaleShiny = Dex.GetDisplayed(i, 2),
DispFemaleShiny = Dex.GetDisplayed(i, 3),
};
if (hasLangs)
{
var langs = new bool[LangCount];
for (int l = 0; l < LangCount; l++)
langs[l] = Dex.GetLanguageFlag(i, l);
entry.Languages = langs;
}
AllEntries.Add(entry);
}
FilteredEntries = new ObservableCollection<Pokedex5EntryModel>(AllEntries);
}
partial void OnSearchTextChanged(string value) => ApplyFilter();
private void ApplyFilter()
{
if (string.IsNullOrWhiteSpace(SearchText))
{
FilteredEntries = new ObservableCollection<Pokedex5EntryModel>(AllEntries);
return;
}
FilteredEntries = new ObservableCollection<Pokedex5EntryModel>(
AllEntries.Where(e => e.Label.Contains(SearchText, StringComparison.OrdinalIgnoreCase)));
}
[RelayCommand]
private void SeenAll()
{
foreach (var entry in AllEntries)
{
entry.SeenMale = true;
entry.SeenFemale = true;
if (!entry.DispMale && !entry.DispFemale && !entry.DispMaleShiny && !entry.DispFemaleShiny)
entry.DispMale = true;
}
}
[RelayCommand]
private void CaughtAll()
{
foreach (var entry in AllEntries)
{
entry.Caught = true;
if (entry.HasLanguages)
{
var langs = new bool[LangCount];
for (int i = 0; i < LangCount; i++)
langs[i] = true;
entry.Languages = langs;
}
}
}
[RelayCommand]
private void ClearAll()
{
foreach (var entry in AllEntries)
{
entry.Caught = false;
entry.SeenMale = false;
entry.SeenFemale = false;
entry.SeenMaleShiny = false;
entry.SeenFemaleShiny = false;
entry.DispMale = false;
entry.DispFemale = false;
entry.DispMaleShiny = false;
entry.DispFemaleShiny = false;
if (entry.HasLanguages)
entry.Languages = new bool[LangCount];
}
}
[RelayCommand]
private void CompleteAll()
{
SeenAll();
CaughtAll();
}
[RelayCommand]
private void Save()
{
foreach (var entry in AllEntries)
{
var species = entry.Species;
Dex.SetCaught(species, entry.Caught);
Dex.SetSeen(species, 0, entry.SeenMale);
Dex.SetSeen(species, 1, entry.SeenFemale);
Dex.SetSeen(species, 2, entry.SeenMaleShiny);
Dex.SetSeen(species, 3, entry.SeenFemaleShiny);
Dex.SetDisplayed(species, 0, entry.DispMale);
Dex.SetDisplayed(species, 1, entry.DispFemale);
Dex.SetDisplayed(species, 2, entry.DispMaleShiny);
Dex.SetDisplayed(species, 3, entry.DispFemaleShiny);
if (entry.HasLanguages)
{
for (int l = 0; l < LangCount; l++)
Dex.SetLanguageFlag(species, l, entry.Languages[l]);
}
}
Dex.IsNationalDexUnlocked = NationalDexUnlocked;
Dex.IsNationalDexMode = NationalDexActive;
if (uint.TryParse(SpindaPid, System.Globalization.NumberStyles.HexNumber, null, out var spinda))
Dex.Spinda = spinda;
SAV.State.Edited = true;
Modified = true;
}
}

View File

@ -0,0 +1,97 @@
using System;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for a single berry plot entry.
/// </summary>
public partial class BerryPlotModel : ObservableObject
{
public int Index { get; }
[ObservableProperty]
private int _berry;
[ObservableProperty]
private int _u1;
[ObservableProperty]
private int _u2;
[ObservableProperty]
private int _u3;
[ObservableProperty]
private int _u4;
[ObservableProperty]
private int _u5;
[ObservableProperty]
private int _u6;
[ObservableProperty]
private int _u7;
public string DisplayName => $"Plot {Index + 1}";
public BerryPlotModel(int index) => Index = index;
}
/// <summary>
/// ViewModel for the Gen 6 XY Berry Field viewer.
/// Read-only display of berry plots (no save, just viewing).
/// </summary>
public partial class SAVBerryFieldXYViewModel : SaveEditorViewModelBase
{
private readonly SAV6XY _sav;
public ObservableCollection<BerryPlotModel> Plots { get; } = [];
[ObservableProperty]
private BerryPlotModel? _selectedPlot;
[ObservableProperty]
private int _selectedPlotIndex = -1;
public SAVBerryFieldXYViewModel(SAV6XY sav) : base(sav)
{
_sav = sav;
for (int i = 0; i < BerryField6XY.Count; i++)
{
var model = new BerryPlotModel(i);
Plots.Add(model);
}
if (Plots.Count > 0)
SelectedPlotIndex = 0;
}
partial void OnSelectedPlotIndexChanged(int value)
{
if (value < 0 || value >= Plots.Count)
return;
LoadPlot(value);
SelectedPlot = Plots[value];
}
private void LoadPlot(int index)
{
var span = _sav.BerryField.GetPlot(index);
var model = Plots[index];
model.Berry = ReadUInt16LittleEndian(span);
model.U1 = ReadUInt16LittleEndian(span[(2 * 1)..]);
model.U2 = ReadUInt16LittleEndian(span[(2 * 2)..]);
model.U3 = ReadUInt16LittleEndian(span[(2 * 3)..]);
model.U4 = ReadUInt16LittleEndian(span[(2 * 4)..]);
model.U5 = ReadUInt16LittleEndian(span[(2 * 5)..]);
model.U6 = ReadUInt16LittleEndian(span[(2 * 6)..]);
model.U7 = ReadUInt16LittleEndian(span[(2 * 7)..]);
}
}

View File

@ -0,0 +1,229 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the Gen 6 Hall of Fame viewer/editor.
/// Shows 16 entries with 6 team members each.
/// </summary>
public partial class SAVHallOfFame6ViewModel : SaveEditorViewModelBase
{
private readonly SAV6 _origin;
private readonly SAV6 _sav;
private readonly HallOfFame6 _fame;
private bool _loading;
public List<string> EntryNames { get; } = [];
public List<ComboItem> SpeciesList { get; }
public List<ComboItem> ItemsList { get; }
public List<ComboItem> MovesList { get; }
[ObservableProperty]
private int _selectedEntryIndex = -1;
[ObservableProperty]
private int _memberIndex = 1;
[ObservableProperty]
private int _maxMembers = 6;
[ObservableProperty]
private int _selectedSpecies;
[ObservableProperty]
private int _selectedItem;
[ObservableProperty]
private int _move1;
[ObservableProperty]
private int _move2;
[ObservableProperty]
private int _move3;
[ObservableProperty]
private int _move4;
[ObservableProperty]
private string _ec = "00000000";
[ObservableProperty]
private string _tid = "00000";
[ObservableProperty]
private string _sid = "00000";
[ObservableProperty]
private string _nickname = string.Empty;
[ObservableProperty]
private string _otName = string.Empty;
[ObservableProperty]
private bool _isShiny;
[ObservableProperty]
private bool _isNicknamed;
[ObservableProperty]
private int _level;
[ObservableProperty]
private string _entryText = string.Empty;
[ObservableProperty]
private string _clearIndex = "000";
public SAVHallOfFame6ViewModel(SAV6 sav) : base(sav)
{
_sav = (SAV6)(_origin = sav).Clone();
_fame = ((ISaveBlock6Main)_sav).HallOfFame;
var filtered = GameInfo.FilteredSources;
SpeciesList = filtered.Species.ToList();
ItemsList = filtered.Items.ToList();
MovesList = filtered.Moves.ToList();
for (int i = 0; i < HallOfFame6.Entries; i++)
EntryNames.Add($"Entry {i}");
SelectedEntryIndex = 0;
}
partial void OnSelectedEntryIndexChanged(int value)
{
if (value < 0)
return;
LoadEntry(value);
}
partial void OnMemberIndexChanged(int value)
{
if (_loading || value < 1 || SelectedEntryIndex < 0)
return;
LoadMember(SelectedEntryIndex, value - 1);
}
private void LoadEntry(int index)
{
_loading = true;
var span = _fame.GetEntry(index);
var vnd = new HallFame6Index(span[^4..]);
ClearIndex = vnd.ClearIndex.ToString("000");
var sb = new StringBuilder();
sb.AppendLine($"Entry #{vnd.ClearIndex}");
if (!vnd.HasData)
{
sb.AppendLine("No records in this slot.");
EntryText = sb.ToString();
MemberIndex = 1;
MaxMembers = 1;
_loading = false;
return;
}
var year = vnd.Year + 2000;
var month = vnd.Month;
var day = vnd.Day;
sb.AppendLine($"Date: {year}/{month:00}/{day:00}");
int monCount = 0;
for (int i = 0; i < 6; i++)
{
var slice = span[(i * HallFame6Entity.SIZE)..];
var entity = new HallFame6Entity(slice, _sav.Language);
if (entity.Species == 0)
continue;
monCount++;
var str = GameInfo.Strings;
sb.AppendLine($" {str.Species[entity.Species]} Lv.{entity.Level} - {str.Item[entity.HeldItem]}");
}
EntryText = sb.ToString();
MaxMembers = monCount == 0 ? 1 : monCount;
MemberIndex = 1;
LoadMember(index, 0);
_loading = false;
}
private void LoadMember(int entryIndex, int memberIdx)
{
_loading = true;
var slice = _fame.GetEntity(entryIndex, memberIdx);
var entity = new HallFame6Entity(slice, _sav.Language);
SelectedSpecies = entity.Species;
SelectedItem = entity.HeldItem;
Move1 = entity.Move1;
Move2 = entity.Move2;
Move3 = entity.Move3;
Move4 = entity.Move4;
Ec = entity.EncryptionConstant.ToString("X8");
Tid = entity.TID16.ToString("00000");
Sid = entity.SID16.ToString("00000");
Nickname = entity.Nickname;
OtName = entity.OriginalTrainerName;
IsShiny = entity.IsShiny;
IsNicknamed = entity.IsNicknamed;
Level = (int)entity.Level;
_loading = false;
}
private void SaveMember()
{
if (SelectedEntryIndex < 0 || MemberIndex < 1)
return;
var slice = _fame.GetEntity(SelectedEntryIndex, MemberIndex - 1);
var entity = new HallFame6Entity(slice, _sav.Language)
{
Species = (ushort)SelectedSpecies,
HeldItem = (ushort)SelectedItem,
Move1 = (ushort)Move1,
Move2 = (ushort)Move2,
Move3 = (ushort)Move3,
Move4 = (ushort)Move4,
EncryptionConstant = Convert.ToUInt32(Ec, 16),
TID16 = ushort.TryParse(Tid, out var tid) ? tid : (ushort)0,
SID16 = ushort.TryParse(Sid, out var sid) ? sid : (ushort)0,
Nickname = Nickname,
OriginalTrainerName = OtName,
IsShiny = IsShiny,
IsNicknamed = IsNicknamed,
Level = (uint)Math.Clamp(Level, 0, 100),
};
var span = _fame.GetEntry(SelectedEntryIndex);
_ = new HallFame6Index(span[^4..])
{
ClearIndex = ushort.TryParse(ClearIndex, out var ci) ? ci : (ushort)0,
HasData = true,
};
}
[RelayCommand]
private void DeleteEntry()
{
if (SelectedEntryIndex < 1)
return;
_fame.ClearEntry(SelectedEntryIndex);
LoadEntry(SelectedEntryIndex);
}
[RelayCommand]
private void Save()
{
SaveMember();
_origin.CopyChangesFrom(_sav);
Modified = true;
}
}

View File

@ -0,0 +1,163 @@
using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the Gen 6 Link event editor.
/// Edits link data including items, quantities, battle points, and pokemiles.
/// </summary>
public partial class SAVLink6ViewModel : SaveEditorViewModelBase
{
private readonly SaveFile _origin;
private readonly ISaveBlock6Main _clone;
private readonly PL6 _gifts;
public List<ComboItem> ItemsList { get; }
[ObservableProperty]
private string _linkSource = string.Empty;
[ObservableProperty]
private bool _linkAvailable;
[ObservableProperty]
private int _battlePoints;
[ObservableProperty]
private int _pokemiles;
[ObservableProperty]
private int _item1;
[ObservableProperty]
private int _item2;
[ObservableProperty]
private int _item3;
[ObservableProperty]
private int _item4;
[ObservableProperty]
private int _item5;
[ObservableProperty]
private int _item6;
[ObservableProperty]
private int _quantity1;
[ObservableProperty]
private int _quantity2;
[ObservableProperty]
private int _quantity3;
[ObservableProperty]
private int _quantity4;
[ObservableProperty]
private int _quantity5;
[ObservableProperty]
private int _quantity6;
[ObservableProperty]
private string _pkm1 = string.Empty;
[ObservableProperty]
private string _pkm2 = string.Empty;
[ObservableProperty]
private string _pkm3 = string.Empty;
[ObservableProperty]
private string _pkm4 = string.Empty;
[ObservableProperty]
private string _pkm5 = string.Empty;
[ObservableProperty]
private string _pkm6 = string.Empty;
public SAVLink6ViewModel(SaveFile sav) : base(sav)
{
_origin = sav;
var clone = sav.Clone();
_clone = (ISaveBlock6Main)clone;
_gifts = _clone.Link.Gifts;
ItemsList = GameInfo.FilteredSources.Items.ToList();
LoadLinkData();
}
private void LoadLinkData()
{
LinkSource = _gifts.Origin;
LinkAvailable = _gifts.Enabled;
BattlePoints = _gifts.BattlePoints;
Pokemiles = _gifts.Pokemiles;
Item1 = _gifts.Item1;
Item2 = _gifts.Item2;
Item3 = _gifts.Item3;
Item4 = _gifts.Item4;
Item5 = _gifts.Item5;
Item6 = _gifts.Item6;
Quantity1 = _gifts.Quantity1;
Quantity2 = _gifts.Quantity2;
Quantity3 = _gifts.Quantity3;
Quantity4 = _gifts.Quantity4;
Quantity5 = _gifts.Quantity5;
Quantity6 = _gifts.Quantity6;
Pkm1 = GetSpecies(_gifts.Entity1.Species);
Pkm2 = GetSpecies(_gifts.Entity2.Species);
Pkm3 = GetSpecies(_gifts.Entity3.Species);
Pkm4 = GetSpecies(_gifts.Entity4.Species);
Pkm5 = GetSpecies(_gifts.Entity5.Species);
Pkm6 = GetSpecies(_gifts.Entity6.Species);
}
private static string GetSpecies(ushort species)
{
var arr = GameInfo.Strings.Species;
if (species < arr.Count)
return arr[species];
return species.ToString();
}
[RelayCommand]
private void Save()
{
_gifts.Origin = LinkSource;
_gifts.Enabled = LinkAvailable;
_gifts.BattlePoints = (ushort)BattlePoints;
_gifts.Pokemiles = (ushort)Pokemiles;
_gifts.Item1 = (ushort)Item1;
_gifts.Item2 = (ushort)Item2;
_gifts.Item3 = (ushort)Item3;
_gifts.Item4 = (ushort)Item4;
_gifts.Item5 = (ushort)Item5;
_gifts.Item6 = (ushort)Item6;
_gifts.Quantity1 = (ushort)Quantity1;
_gifts.Quantity2 = (ushort)Quantity2;
_gifts.Quantity3 = (ushort)Quantity3;
_gifts.Quantity4 = (ushort)Quantity4;
_gifts.Quantity5 = (ushort)Quantity5;
_gifts.Quantity6 = (ushort)Quantity6;
_clone.Link.RefreshChecksum();
_origin.CopyChangesFrom((SaveFile)_clone);
Modified = true;
}
}

View File

@ -0,0 +1,151 @@
using System;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for an unlock flag item.
/// </summary>
public partial class OPowerUnlockModel : ObservableObject
{
public string Name { get; }
public int Index { get; }
[ObservableProperty]
private bool _isUnlocked;
public OPowerUnlockModel(string name, int index, bool unlocked)
{
Name = name;
Index = index;
_isUnlocked = unlocked;
}
}
/// <summary>
/// Model for a field/battle level row.
/// </summary>
public partial class OPowerLevelModel : ObservableObject
{
public string Name { get; }
public int Index { get; }
[ObservableProperty]
private byte _level1;
[ObservableProperty]
private byte _level2;
public OPowerLevelModel(string name, int index, byte level1, byte level2)
{
Name = name;
Index = index;
_level1 = level1;
_level2 = level2;
}
}
/// <summary>
/// ViewModel for the Gen 6 O-Power editor.
/// Edits unlock states, field/battle levels, and points.
/// </summary>
public partial class SAVOPower6ViewModel : SaveEditorViewModelBase
{
private readonly SaveFile _origin;
private readonly SaveFile _clone;
private readonly OPower6 _block;
public ObservableCollection<OPowerUnlockModel> UnlockFlags { get; } = [];
public ObservableCollection<OPowerLevelModel> FieldLevels { get; } = [];
public ObservableCollection<OPowerLevelModel> BattleLevels { get; } = [];
[ObservableProperty]
private byte _points;
public SAVOPower6ViewModel(ISaveBlock6Main sav) : base((SaveFile)sav)
{
_origin = (SaveFile)sav;
_clone = _origin.Clone();
_block = ((ISaveBlock6Main)_clone).OPower;
LoadData();
}
private void LoadData()
{
UnlockFlags.Clear();
FieldLevels.Clear();
BattleLevels.Clear();
// Unlock flags - use enum names
var indexNames = Enum.GetNames<OPower6Index>();
int indexCount = (int)OPower6Index.Count;
for (int i = 0; i < indexCount; i++)
{
var name = i < indexNames.Length ? indexNames[i] : $"Index {i}";
bool unlocked = _block.GetState((OPower6Index)i) == OPowerFlagState.Unlocked;
UnlockFlags.Add(new OPowerUnlockModel(name, i, unlocked));
}
// Field levels
var fieldNames = Enum.GetNames<OPower6FieldType>();
int fieldCount = (int)OPower6FieldType.Count;
for (int i = 0; i < fieldCount; i++)
{
var name = i < fieldNames.Length ? fieldNames[i] : $"Field {i}";
FieldLevels.Add(new OPowerLevelModel(name, i,
_block.GetLevel1((OPower6FieldType)i),
_block.GetLevel2((OPower6FieldType)i)));
}
// Battle levels
var battleNames = Enum.GetNames<OPower6BattleType>();
int battleCount = (int)OPower6BattleType.Count;
for (int i = 0; i < battleCount; i++)
{
var name = i < battleNames.Length ? battleNames[i] : $"Battle {i}";
BattleLevels.Add(new OPowerLevelModel(name, i,
_block.GetLevel1((OPower6BattleType)i),
_block.GetLevel2((OPower6BattleType)i)));
}
Points = _block.Points;
}
[RelayCommand]
private void GiveAll()
{
_block.UnlockAll();
LoadData();
}
[RelayCommand]
private void ClearAll()
{
_block.ClearAll();
LoadData();
}
[RelayCommand]
private void Save()
{
foreach (var flag in UnlockFlags)
_block.SetState((OPower6Index)flag.Index, flag.IsUnlocked ? OPowerFlagState.Unlocked : OPowerFlagState.Locked);
foreach (var field in FieldLevels)
{
_block.SetLevel1((OPower6FieldType)field.Index, field.Level1);
_block.SetLevel2((OPower6FieldType)field.Index, field.Level2);
}
foreach (var battle in BattleLevels)
{
_block.SetLevel1((OPower6BattleType)battle.Index, battle.Level1);
_block.SetLevel2((OPower6BattleType)battle.Index, battle.Level2);
}
_block.Points = Points;
_origin.CopyChangesFrom(_clone);
Modified = true;
}
}

View File

@ -0,0 +1,74 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for a single PokeBlock entry in ORAS.
/// </summary>
public partial class PokeBlock6Model : ObservableObject
{
public int Index { get; }
public string Label { get; }
[ObservableProperty]
private uint _count;
public PokeBlock6Model(int index, string label, uint count)
{
Index = index;
Label = label;
_count = count;
}
}
/// <summary>
/// ViewModel for the Gen 6 ORAS PokeBlock editor.
/// Edits the 12 pokeblock counts.
/// </summary>
public partial class SAVPokeBlockORASViewModel : SaveEditorViewModelBase
{
private readonly SAV6AO _origin;
private readonly SAV6AO _sav;
public ObservableCollection<PokeBlock6Model> Blocks { get; } = [];
public SAVPokeBlockORASViewModel(SAV6AO sav) : base(sav)
{
_sav = (SAV6AO)(_origin = sav).Clone();
var contest = _sav.Contest;
var blockNames = GameInfo.Strings.pokeblocks;
for (int i = 0; i < Contest6.CountBlock; i++)
{
var label = (94 + i < blockNames.Length) ? blockNames[94 + i] : $"Block {i}";
Blocks.Add(new PokeBlock6Model(i, label, contest.GetBlockCount(i)));
}
}
[RelayCommand]
private void GiveAll()
{
foreach (var block in Blocks)
block.Count = 999;
}
[RelayCommand]
private void ClearAll()
{
foreach (var block in Blocks)
block.Count = 0;
}
[RelayCommand]
private void Save()
{
var contest = _sav.Contest;
foreach (var block in Blocks)
contest.SetBlockCount(block.Index, block.Count);
_origin.CopyChangesFrom(_sav);
Modified = true;
}
}

View File

@ -0,0 +1,233 @@
using System;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the Gen 6 ORAS Pokedex editor.
/// Edits seen/caught/language flags and DexNav counts per species.
/// </summary>
public partial class SAVPokedexORASViewModel : SaveEditorViewModelBase
{
private readonly SaveFile _origin;
private readonly SAV6AO _sav;
private readonly Zukan6AO _zukan;
private bool _editing;
private ushort _species = ushort.MaxValue;
public ObservableCollection<string> SpeciesNames { get; } = [];
[ObservableProperty]
private int _selectedSpeciesIndex = -1;
[ObservableProperty]
private bool _caught;
[ObservableProperty]
private bool _seenMale;
[ObservableProperty]
private bool _seenFemale;
[ObservableProperty]
private bool _seenMaleShiny;
[ObservableProperty]
private bool _seenFemaleShiny;
[ObservableProperty]
private bool _displayedMale;
[ObservableProperty]
private bool _displayedFemale;
[ObservableProperty]
private bool _displayedMaleShiny;
[ObservableProperty]
private bool _displayedFemaleShiny;
[ObservableProperty]
private bool _langJPN;
[ObservableProperty]
private bool _langENG;
[ObservableProperty]
private bool _langFRE;
[ObservableProperty]
private bool _langITA;
[ObservableProperty]
private bool _langGER;
[ObservableProperty]
private bool _langSPA;
[ObservableProperty]
private bool _langKOR;
[ObservableProperty]
private bool _nationalDexUnlocked;
[ObservableProperty]
private bool _nationalDexActive;
[ObservableProperty]
private string _spindaPid = "00000000";
[ObservableProperty]
private int _countSeen;
[ObservableProperty]
private int _countObtained;
public SAVPokedexORASViewModel(SAV6AO sav) : base(sav)
{
_sav = (SAV6AO)(_origin = sav).Clone();
_zukan = _sav.Zukan;
for (int i = 1; i <= _sav.MaxSpeciesID; i++)
SpeciesNames.Add($"{i:000} - {GameInfo.Strings.specieslist[i]}");
NationalDexUnlocked = _zukan.IsNationalDexUnlocked;
NationalDexActive = _zukan.IsNationalDexMode;
SpindaPid = _zukan.Spinda.ToString("X8");
SelectedSpeciesIndex = 0;
}
partial void OnSelectedSpeciesIndexChanged(int value)
{
if (value < 0 || _editing)
return;
SaveEntry();
_editing = true;
_species = (ushort)(value + 1);
LoadEntry();
_editing = false;
}
private void LoadEntry()
{
Caught = _zukan.GetCaught(_species);
SeenMale = _zukan.GetSeen(_species, 0);
SeenFemale = _zukan.GetSeen(_species, 1);
SeenMaleShiny = _zukan.GetSeen(_species, 2);
SeenFemaleShiny = _zukan.GetSeen(_species, 3);
DisplayedMale = _zukan.GetDisplayed(_species, 0);
DisplayedFemale = _zukan.GetDisplayed(_species, 1);
DisplayedMaleShiny = _zukan.GetDisplayed(_species, 2);
DisplayedFemaleShiny = _zukan.GetDisplayed(_species, 3);
LangJPN = _zukan.GetLanguageFlag(_species, 0);
LangENG = _zukan.GetLanguageFlag(_species, 1);
LangFRE = _zukan.GetLanguageFlag(_species, 2);
LangITA = _zukan.GetLanguageFlag(_species, 3);
LangGER = _zukan.GetLanguageFlag(_species, 4);
LangSPA = _zukan.GetLanguageFlag(_species, 5);
LangKOR = _zukan.GetLanguageFlag(_species, 6);
CountSeen = _zukan.GetCountSeen(_species);
CountObtained = _zukan.GetCountObtained(_species);
}
private void SaveEntry()
{
if (_species is 0 or > 721)
return;
_zukan.SetCaught(_species, Caught);
_zukan.SetSeen(_species, 0, SeenMale);
_zukan.SetSeen(_species, 1, SeenFemale);
_zukan.SetSeen(_species, 2, SeenMaleShiny);
_zukan.SetSeen(_species, 3, SeenFemaleShiny);
_zukan.SetDisplayed(_species, 0, DisplayedMale);
_zukan.SetDisplayed(_species, 1, DisplayedFemale);
_zukan.SetDisplayed(_species, 2, DisplayedMaleShiny);
_zukan.SetDisplayed(_species, 3, DisplayedFemaleShiny);
_zukan.SetLanguageFlag(_species, 0, LangJPN);
_zukan.SetLanguageFlag(_species, 1, LangENG);
_zukan.SetLanguageFlag(_species, 2, LangFRE);
_zukan.SetLanguageFlag(_species, 3, LangITA);
_zukan.SetLanguageFlag(_species, 4, LangGER);
_zukan.SetLanguageFlag(_species, 5, LangSPA);
_zukan.SetLanguageFlag(_species, 6, LangKOR);
_zukan.SetCountSeen(_species, (ushort)Math.Clamp(CountSeen, 0, ushort.MaxValue));
_zukan.SetCountObtained(_species, (ushort)Math.Clamp(CountObtained, 0, ushort.MaxValue));
}
[RelayCommand]
private void SeenAll()
{
SaveEntry();
_zukan.SeenAll(shinyToo: false);
LoadEntry();
}
[RelayCommand]
private void SeenNone()
{
SaveEntry();
_zukan.SeenNone();
LoadEntry();
}
[RelayCommand]
private void CaughtAll()
{
SaveEntry();
var language = (LanguageID)_sav.Language;
_zukan.CaughtAll(language, allLanguages: false);
LoadEntry();
}
[RelayCommand]
private void CaughtNone()
{
SaveEntry();
_zukan.CaughtNone();
LoadEntry();
}
[RelayCommand]
private void Complete()
{
SaveEntry();
var language = (LanguageID)_sav.Language;
_zukan.SeenAll(shinyToo: false);
_zukan.CaughtAll(language, allLanguages: false);
LoadEntry();
}
[RelayCommand]
private void MaxDexNav()
{
for (ushort i = 0; i < _sav.MaxSpeciesID; i++)
_zukan.SetCountSeen(i, 999);
LoadEntry();
}
[RelayCommand]
private void ResetDexNav()
{
for (ushort i = 0; i < _sav.MaxSpeciesID; i++)
_zukan.SetCountSeen(i, 0);
LoadEntry();
}
[RelayCommand]
private void Save()
{
SaveEntry();
_zukan.IsNationalDexUnlocked = NationalDexUnlocked;
_zukan.IsNationalDexMode = NationalDexActive;
_zukan.Spinda = Convert.ToUInt32(SpindaPid, 16);
if (_species is not 0)
_zukan.InitialSpecies = _species;
_origin.CopyChangesFrom(_sav);
Modified = true;
}
}

View File

@ -0,0 +1,213 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the Gen 6 XY Pokedex editor.
/// Edits seen/caught/language flags per species.
/// </summary>
public partial class SAVPokedexXYViewModel : SaveEditorViewModelBase
{
private readonly SaveFile _origin;
private readonly SAV6XY _sav;
private readonly Zukan6XY _zukan;
private bool _editing;
private ushort _species = ushort.MaxValue;
public ObservableCollection<string> SpeciesNames { get; } = [];
[ObservableProperty]
private int _selectedSpeciesIndex = -1;
// Caught
[ObservableProperty]
private bool _caught;
// Seen M/F/MS/FS
[ObservableProperty]
private bool _seenMale;
[ObservableProperty]
private bool _seenFemale;
[ObservableProperty]
private bool _seenMaleShiny;
[ObservableProperty]
private bool _seenFemaleShiny;
// Displayed M/F/MS/FS
[ObservableProperty]
private bool _displayedMale;
[ObservableProperty]
private bool _displayedFemale;
[ObservableProperty]
private bool _displayedMaleShiny;
[ObservableProperty]
private bool _displayedFemaleShiny;
// Language flags
[ObservableProperty]
private bool _langJPN;
[ObservableProperty]
private bool _langENG;
[ObservableProperty]
private bool _langFRE;
[ObservableProperty]
private bool _langITA;
[ObservableProperty]
private bool _langGER;
[ObservableProperty]
private bool _langSPA;
[ObservableProperty]
private bool _langKOR;
[ObservableProperty]
private bool _nationalDexUnlocked;
[ObservableProperty]
private bool _nationalDexActive;
[ObservableProperty]
private string _spindaPid = "00000000";
public SAVPokedexXYViewModel(SAV6XY sav) : base(sav)
{
_sav = (SAV6XY)(_origin = sav).Clone();
_zukan = _sav.Zukan;
for (int i = 1; i <= _sav.MaxSpeciesID; i++)
SpeciesNames.Add($"{i:000} - {GameInfo.Strings.specieslist[i]}");
NationalDexUnlocked = _zukan.IsNationalDexUnlocked;
NationalDexActive = _zukan.IsNationalDexMode;
SpindaPid = _zukan.Spinda.ToString("X8");
SelectedSpeciesIndex = 0;
}
partial void OnSelectedSpeciesIndexChanged(int value)
{
if (value < 0 || _editing)
return;
SaveEntry();
_editing = true;
_species = (ushort)(value + 1);
LoadEntry();
_editing = false;
}
private void LoadEntry()
{
Caught = _zukan.GetCaught(_species);
SeenMale = _zukan.GetSeen(_species, 0);
SeenFemale = _zukan.GetSeen(_species, 1);
SeenMaleShiny = _zukan.GetSeen(_species, 2);
SeenFemaleShiny = _zukan.GetSeen(_species, 3);
DisplayedMale = _zukan.GetDisplayed(_species, 0);
DisplayedFemale = _zukan.GetDisplayed(_species, 1);
DisplayedMaleShiny = _zukan.GetDisplayed(_species, 2);
DisplayedFemaleShiny = _zukan.GetDisplayed(_species, 3);
LangJPN = _zukan.GetLanguageFlag(_species, 0);
LangENG = _zukan.GetLanguageFlag(_species, 1);
LangFRE = _zukan.GetLanguageFlag(_species, 2);
LangITA = _zukan.GetLanguageFlag(_species, 3);
LangGER = _zukan.GetLanguageFlag(_species, 4);
LangSPA = _zukan.GetLanguageFlag(_species, 5);
LangKOR = _zukan.GetLanguageFlag(_species, 6);
}
private void SaveEntry()
{
if (_species is 0 or > 721)
return;
_zukan.SetCaught(_species, Caught);
_zukan.SetSeen(_species, 0, SeenMale);
_zukan.SetSeen(_species, 1, SeenFemale);
_zukan.SetSeen(_species, 2, SeenMaleShiny);
_zukan.SetSeen(_species, 3, SeenFemaleShiny);
_zukan.SetDisplayed(_species, 0, DisplayedMale);
_zukan.SetDisplayed(_species, 1, DisplayedFemale);
_zukan.SetDisplayed(_species, 2, DisplayedMaleShiny);
_zukan.SetDisplayed(_species, 3, DisplayedFemaleShiny);
_zukan.SetLanguageFlag(_species, 0, LangJPN);
_zukan.SetLanguageFlag(_species, 1, LangENG);
_zukan.SetLanguageFlag(_species, 2, LangFRE);
_zukan.SetLanguageFlag(_species, 3, LangITA);
_zukan.SetLanguageFlag(_species, 4, LangGER);
_zukan.SetLanguageFlag(_species, 5, LangSPA);
_zukan.SetLanguageFlag(_species, 6, LangKOR);
}
[RelayCommand]
private void SeenAll()
{
SaveEntry();
_zukan.SeenAll(shinyToo: false);
LoadEntry();
}
[RelayCommand]
private void SeenNone()
{
SaveEntry();
_zukan.SeenNone();
LoadEntry();
}
[RelayCommand]
private void CaughtAll()
{
SaveEntry();
var language = (LanguageID)_sav.Language;
_zukan.CaughtAll(language, allLanguages: false);
LoadEntry();
}
[RelayCommand]
private void CaughtNone()
{
SaveEntry();
_zukan.CaughtNone();
LoadEntry();
}
[RelayCommand]
private void Complete()
{
SaveEntry();
var language = (LanguageID)_sav.Language;
_zukan.SeenAll(shinyToo: false);
_zukan.CaughtAll(language, allLanguages: false);
LoadEntry();
}
[RelayCommand]
private void Save()
{
SaveEntry();
_zukan.IsNationalDexUnlocked = NationalDexUnlocked;
_zukan.IsNationalDexMode = NationalDexActive;
_zukan.Spinda = Convert.ToUInt32(SpindaPid, 16);
if (_species is not 0)
_zukan.InitialSpecies = _species;
_origin.CopyChangesFrom(_sav);
Modified = true;
}
}

View File

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for a single Pokepuff slot.
/// </summary>
public partial class PokepuffSlotModel : ObservableObject
{
public int Index { get; }
[ObservableProperty]
private int _selectedPuffIndex;
public string DisplayName => $"Slot {Index + 1}";
public PokepuffSlotModel(int index, int puffIndex)
{
Index = index;
_selectedPuffIndex = puffIndex;
}
}
/// <summary>
/// ViewModel for the Gen 6 Pokepuff collection editor.
/// </summary>
public partial class SAVPokepuff6ViewModel : SaveEditorViewModelBase
{
private readonly ISaveBlock6Main _sav;
public ObservableCollection<PokepuffSlotModel> Slots { get; } = [];
public List<string> PuffNames { get; }
public SAVPokepuff6ViewModel(ISaveBlock6Main sav) : base((SaveFile)sav)
{
_sav = sav;
PuffNames = [.. GameInfo.Strings.puffs];
LoadPuffs();
}
private void LoadPuffs()
{
Slots.Clear();
var puffs = _sav.Puff.GetPuffs();
for (int i = 0; i < puffs.Length; i++)
{
int puffVal = puffs[i];
if (puffVal >= PuffNames.Count)
puffVal = 0;
Slots.Add(new PokepuffSlotModel(i, puffVal));
}
}
[RelayCommand]
private void GiveAll()
{
_sav.Puff.MaxCheat(false);
LoadPuffs();
}
[RelayCommand]
private void GiveBest()
{
_sav.Puff.MaxCheat(true);
LoadPuffs();
}
[RelayCommand]
private void ClearAll()
{
_sav.Puff.Reset();
LoadPuffs();
}
[RelayCommand]
private void Sort()
{
SavePuffs();
_sav.Puff.Sort(false);
LoadPuffs();
}
[RelayCommand]
private void SortReverse()
{
SavePuffs();
_sav.Puff.Sort(true);
LoadPuffs();
}
private void SavePuffs()
{
var puffs = new byte[Slots.Count];
for (int i = 0; i < Slots.Count; i++)
puffs[i] = (byte)Slots[i].SelectedPuffIndex;
_sav.Puff.SetPuffs(puffs);
_sav.Puff.PuffCount = puffs.Length;
}
[RelayCommand]
private void Save()
{
SavePuffs();
Modified = true;
}
}

View File

@ -0,0 +1,68 @@
using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the Gen 6 Roaming Pokemon editor.
/// Edits species, roam state, and times encountered.
/// </summary>
public partial class SAVRoamer6ViewModel : SaveEditorViewModelBase
{
private readonly SAV6XY _origin;
private readonly SAV6XY _sav;
private readonly Roamer6 _roamer;
public List<string> SpeciesChoices { get; }
public List<string> RoamStateChoices { get; } = ["Inactive", "Roaming", "Stationary", "Defeated", "Captured"];
[ObservableProperty]
private int _selectedSpeciesIndex;
[ObservableProperty]
private int _selectedRoamStateIndex;
[ObservableProperty]
private uint _timesEncountered;
public SAVRoamer6ViewModel(SAV6XY sav) : base(sav)
{
_sav = (SAV6XY)(_origin = sav).Clone();
_roamer = _sav.Encount.Roamer;
var species = GameInfo.Strings.specieslist;
SpeciesChoices =
[
species[(int)Species.Articuno],
species[(int)Species.Zapdos],
species[(int)Species.Moltres],
];
SelectedSpeciesIndex = GetInitialIndex();
TimesEncountered = _roamer.TimesEncountered;
SelectedRoamStateIndex = (int)_roamer.RoamStatus;
}
private int GetInitialIndex()
{
const int speciesOffset = 144;
const int starterChoiceIndex = 48;
if (_roamer.Species != 0)
return _roamer.Species - speciesOffset;
return _sav.EventWork.GetWork(starterChoiceIndex);
}
[RelayCommand]
private void Save()
{
const int speciesOffset = 144;
_roamer.Species = (ushort)(speciesOffset + SelectedSpeciesIndex);
_roamer.TimesEncountered = TimesEncountered;
_roamer.RoamStatus = (Roamer6State)SelectedRoamStateIndex;
_origin.CopyChangesFrom(_sav);
Modified = true;
}
}

View File

@ -0,0 +1,182 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the Gen 6 ORAS Secret Base editor.
/// Edits base list, decorations, trainer info.
/// </summary>
public partial class SAVSecretBase6ViewModel : SaveEditorViewModelBase
{
private readonly SaveFile _origin;
private readonly SAV6AO _sav;
private bool _loading;
public ObservableCollection<string> BaseNames { get; } = [];
[ObservableProperty]
private int _selectedBaseIndex = -1;
// Base properties (displayed via PropertyGrid-like fields)
[ObservableProperty]
private string _trainerName = string.Empty;
[ObservableProperty]
private int _baseLocation;
[ObservableProperty]
private string _teamName = string.Empty;
[ObservableProperty]
private string _teamSlogan = string.Empty;
// Decoration placement
[ObservableProperty]
private int _placementIndex;
[ObservableProperty]
private int _placementGood;
[ObservableProperty]
private int _placementX;
[ObservableProperty]
private int _placementY;
[ObservableProperty]
private int _placementRotation;
[ObservableProperty]
private uint _capturedRecord;
private SecretBase6? _currentBase;
private int _currentPlacementIndex = -1;
public SAVSecretBase6ViewModel(SAV6AO sav) : base(sav)
{
_sav = (SAV6AO)(_origin = sav).Clone();
CapturedRecord = (uint)_sav.Records.GetRecord(080);
ReloadBaseList();
if (BaseNames.Count > 0)
SelectedBaseIndex = 0;
}
private void ReloadBaseList()
{
_loading = true;
BaseNames.Clear();
var block = _sav.SecretBase;
var self = block.GetSecretBaseSelf();
BaseNames.Add($"* {self.TrainerName}");
for (int i = 0; i < SecretBase6Block.OtherSecretBaseCount; i++)
{
var other = block.GetSecretBaseOther(i);
string name = other.TrainerName;
if (string.IsNullOrWhiteSpace(name))
name = "Empty";
BaseNames.Add($"{i + 1:00} {name}");
}
_loading = false;
}
partial void OnSelectedBaseIndexChanged(int value)
{
if (value < 0 || _loading)
return;
SaveCurrentBase();
LoadBase(value);
}
partial void OnPlacementIndexChanged(int value)
{
if (_currentBase == null || _loading)
return;
SavePlacement();
LoadPlacement(value);
}
private void LoadBase(int index)
{
_loading = true;
_currentPlacementIndex = -1;
_currentBase = index == 0
? _sav.SecretBase.GetSecretBaseSelf()
: _sav.SecretBase.GetSecretBaseOther(index - 1);
TrainerName = _currentBase.TrainerName;
BaseLocation = _currentBase.BaseLocation;
TeamName = _currentBase.TeamName;
TeamSlogan = _currentBase.TeamSlogan;
PlacementIndex = 0;
LoadPlacement(0);
_loading = false;
}
private void LoadPlacement(int index)
{
if (_currentBase == null || index < 0 || index >= SecretBase6.COUNT_GOODS)
return;
_currentPlacementIndex = index;
var p = _currentBase.GetPlacement(index);
PlacementGood = p.Good;
PlacementX = p.X;
PlacementY = p.Y;
PlacementRotation = p.Rotation;
}
private void SavePlacement()
{
if (_currentBase == null || _currentPlacementIndex < 0)
return;
var p = _currentBase.GetPlacement(_currentPlacementIndex);
p.Good = (ushort)PlacementGood;
p.X = (ushort)PlacementX;
p.Y = (ushort)PlacementY;
p.Rotation = (byte)PlacementRotation;
}
private void SaveCurrentBase()
{
if (_currentBase == null)
return;
SavePlacement();
_currentBase.TrainerName = TrainerName;
_currentBase.BaseLocation = BaseLocation;
_currentBase.TeamName = TeamName;
_currentBase.TeamSlogan = TeamSlogan;
}
[RelayCommand]
private void GiveAllDecor()
{
_sav.SecretBase.GiveAllGoods();
}
[RelayCommand]
private void DeleteBase()
{
if (SelectedBaseIndex < 1)
return;
int index = SelectedBaseIndex - 1;
_sav.SecretBase.DeleteOther(index);
_currentBase = null;
_currentPlacementIndex = -1;
ReloadBaseList();
SelectedBaseIndex = index + 1;
}
[RelayCommand]
private void Save()
{
SaveCurrentBase();
_sav.Records.SetRecord(080, (int)CapturedRecord);
_origin.CopyChangesFrom(_sav);
Modified = true;
}
}

View File

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for a training bag slot.
/// </summary>
public partial class TrainingBagSlotModel : ObservableObject
{
public int Index { get; }
[ObservableProperty]
private int _selectedBagIndex;
public string DisplayName => $"Slot {Index + 1}";
public TrainingBagSlotModel(int index, int bagIndex)
{
Index = index;
_selectedBagIndex = bagIndex;
}
}
/// <summary>
/// ViewModel for the Gen 6 Super Training editor.
/// Edits training bags and regimen records.
/// </summary>
public partial class SAVSuperTrain6ViewModel : SaveEditorViewModelBase
{
private readonly SaveFile _origin;
private readonly SAV6 _sav;
private readonly SuperTrainBlock _stb;
private bool _loading;
public List<string> StageNames { get; } = [];
public List<string> BagNames { get; }
public List<ComboItem> SpeciesList { get; }
public ObservableCollection<TrainingBagSlotModel> BagSlots { get; } = [];
[ObservableProperty]
private int _selectedStageIndex = -1;
// Record holder 1
[ObservableProperty]
private int _species1;
[ObservableProperty]
private string _gender1 = "0";
[ObservableProperty]
private string _form1 = "0";
[ObservableProperty]
private string _time1 = "0";
// Record holder 2
[ObservableProperty]
private int _species2;
[ObservableProperty]
private string _gender2 = "0";
[ObservableProperty]
private string _form2 = "0";
[ObservableProperty]
private string _time2 = "0";
public SAVSuperTrain6ViewModel(SAV6 sav) : base(sav)
{
_sav = (SAV6)(_origin = sav).Clone();
_stb = ((ISaveBlock6Main)_sav).SuperTrain;
var bagNames = GameInfo.Strings.trainingbags.ToList();
if (bagNames.Count > 0)
bagNames[0] = "---";
BagNames = bagNames;
SpeciesList = GameInfo.FilteredSources.Species.ToList();
var stages = GameInfo.Strings.trainingstage;
for (int i = 0; i < 32; i++)
StageNames.Add($"{i + 1:00} - {stages[i]}");
// Load bags
for (int i = 0; i < 12; i++)
{
int bagId = _stb.GetBag(i);
BagSlots.Add(new TrainingBagSlotModel(i, bagId));
}
SelectedStageIndex = 0;
}
partial void OnSelectedStageIndexChanged(int value)
{
if (value < 0)
return;
LoadStageRecord(value);
}
private void LoadStageRecord(int index)
{
_loading = true;
var h1 = _stb.GetHolder1(index);
var h2 = _stb.GetHolder2(index);
Species1 = h1.Species;
Gender1 = h1.Gender.ToString();
Form1 = h1.Form.ToString();
Species2 = h2.Species;
Gender2 = h2.Gender.ToString();
Form2 = h2.Form.ToString();
Time1 = _stb.GetTime1(index).ToString(CultureInfo.InvariantCulture);
Time2 = _stb.GetTime2(index).ToString(CultureInfo.InvariantCulture);
_loading = false;
}
private void SaveStageRecord(int index)
{
if (index < 0)
return;
var h1 = _stb.GetHolder1(index);
h1.Species = (ushort)Species1;
if (byte.TryParse(Gender1, out var g1)) h1.Gender = g1;
if (byte.TryParse(Form1, out var f1)) h1.Form = f1;
var h2 = _stb.GetHolder2(index);
h2.Species = (ushort)Species2;
if (byte.TryParse(Gender2, out var g2)) h2.Gender = g2;
if (byte.TryParse(Form2, out var f2)) h2.Form = f2;
if (float.TryParse(Time1, out var t1)) _stb.SetTime1(index, t1);
if (float.TryParse(Time2, out var t2)) _stb.SetTime2(index, t2);
}
[RelayCommand]
private void Save()
{
SaveStageRecord(SelectedStageIndex);
// Save bags
int emptySlots = 0;
for (int i = 0; i < 12; i++)
{
int bagIndex = BagSlots[i].SelectedBagIndex;
if (bagIndex <= 0)
{
emptySlots++;
continue;
}
_stb.SetBag(i - emptySlots, (byte)bagIndex);
}
_origin.CopyChangesFrom(_sav);
Modified = true;
}
}

View File

@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the Gen 6 trainer editor.
/// Edits OT name, TID/SID, money, play time, badges, BP, pokemiles, maison records, etc.
/// </summary>
public partial class SAVTrainer6ViewModel : SaveEditorViewModelBase
{
private readonly SaveFile _origin;
private readonly SAV6 _sav;
public string[] GenderChoices { get; } = ["Male", "Female"];
[ObservableProperty]
private string _otName = string.Empty;
[ObservableProperty]
private string _tid = "00000";
[ObservableProperty]
private string _sid = "00000";
[ObservableProperty]
private string _money = "0";
[ObservableProperty]
private int _gender;
[ObservableProperty]
private int _playedHours;
[ObservableProperty]
private int _playedMinutes;
[ObservableProperty]
private int _playedSeconds;
[ObservableProperty]
private string _bp = "0";
[ObservableProperty]
private string _pokemiles = "0";
[ObservableProperty]
private string _style = "0";
[ObservableProperty]
private bool _megaUnlocked;
[ObservableProperty]
private bool _megaRayquazaUnlocked;
[ObservableProperty]
private bool _showStyle;
[ObservableProperty]
private bool _showMegaRayquaza;
// Badges
[ObservableProperty]
private bool _badge1;
[ObservableProperty]
private bool _badge2;
[ObservableProperty]
private bool _badge3;
[ObservableProperty]
private bool _badge4;
[ObservableProperty]
private bool _badge5;
[ObservableProperty]
private bool _badge6;
[ObservableProperty]
private bool _badge7;
[ObservableProperty]
private bool _badge8;
// Sayings
[ObservableProperty]
private string _saying1 = string.Empty;
[ObservableProperty]
private string _saying2 = string.Empty;
[ObservableProperty]
private string _saying3 = string.Empty;
[ObservableProperty]
private string _saying4 = string.Empty;
[ObservableProperty]
private string _saying5 = string.Empty;
public SAVTrainer6ViewModel(SAV6 sav) : base(sav)
{
_sav = (SAV6)(_origin = sav).Clone();
ShowStyle = _sav is SAV6XY;
ShowMegaRayquaza = _sav is SAV6AO;
LoadData();
}
private void LoadData()
{
OtName = _sav.OT;
Tid = _sav.TID16.ToString("00000");
Sid = _sav.SID16.ToString("00000");
Money = _sav.Money.ToString();
Gender = _sav.Gender;
PlayedHours = _sav.PlayedHours;
PlayedMinutes = _sav.PlayedMinutes;
PlayedSeconds = _sav.PlayedSeconds;
Bp = _sav.BP.ToString();
Pokemiles = _sav.GetRecord(63).ToString();
var sit = _sav.Situation;
Style = sit.Style.ToString();
int badgeval = _sav.Badges;
Badge1 = (badgeval & (1 << 0)) != 0;
Badge2 = (badgeval & (1 << 1)) != 0;
Badge3 = (badgeval & (1 << 2)) != 0;
Badge4 = (badgeval & (1 << 3)) != 0;
Badge5 = (badgeval & (1 << 4)) != 0;
Badge6 = (badgeval & (1 << 5)) != 0;
Badge7 = (badgeval & (1 << 6)) != 0;
Badge8 = (badgeval & (1 << 7)) != 0;
var status = _sav.Status;
Saying1 = status.Saying1;
Saying2 = status.Saying2;
Saying3 = status.Saying3;
Saying4 = status.Saying4;
Saying5 = status.Saying5;
MegaUnlocked = status.IsMegaEvolutionUnlocked;
MegaRayquazaUnlocked = status.IsMegaRayquazaUnlocked;
}
[RelayCommand]
private void MaxCash()
{
Money = "9999999";
}
[RelayCommand]
private void Save()
{
_sav.OT = OtName;
_sav.TID16 = (ushort)(uint.TryParse(Tid, out var tid) ? tid : 0u);
_sav.SID16 = (ushort)(uint.TryParse(Sid, out var sid) ? sid : 0u);
_sav.Money = uint.TryParse(Money, out var money) ? money : 0u;
_sav.Gender = (byte)Gender;
_sav.Overworld.ResetPlayerModel();
_sav.PlayedHours = (ushort)PlayedHours;
_sav.PlayedMinutes = (ushort)(PlayedMinutes % 60);
_sav.PlayedSeconds = (ushort)(PlayedSeconds % 60);
_sav.BP = ushort.TryParse(Bp, out var bp) ? bp : (ushort)0;
_sav.SetRecord(63, int.TryParse(Pokemiles, out var pm1) ? pm1 : 0);
_sav.SetRecord(64, int.TryParse(Pokemiles, out var pm2) ? pm2 : 0);
var sit = _sav.Situation;
if (byte.TryParse(Style, out var style))
sit.Style = style;
int badgeval = 0;
if (Badge1) badgeval |= 1 << 0;
if (Badge2) badgeval |= 1 << 1;
if (Badge3) badgeval |= 1 << 2;
if (Badge4) badgeval |= 1 << 3;
if (Badge5) badgeval |= 1 << 4;
if (Badge6) badgeval |= 1 << 5;
if (Badge7) badgeval |= 1 << 6;
if (Badge8) badgeval |= 1 << 7;
_sav.Badges = badgeval;
var status = _sav.Status;
status.Saying1 = Saying1;
status.Saying2 = Saying2;
status.Saying3 = Saying3;
status.Saying4 = Saying4;
status.Saying5 = Saying5;
status.IsMegaEvolutionUnlocked = MegaUnlocked;
status.IsMegaRayquazaUnlocked = MegaRayquazaUnlocked;
_origin.CopyChangesFrom(_sav);
Modified = true;
}
}

View File

@ -0,0 +1,166 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Core;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// Model for a Geonet location row (Gen 5).
/// </summary>
public partial class GeonetEntry5Model : ObservableObject
{
public int Country { get; }
public string CountryName { get; }
public int Subregion { get; }
public string SubregionName { get; }
[ObservableProperty]
private int _point;
public GeonetEntry5Model(int country, string countryName, int subregion, string subregionName, int point)
{
Country = country;
CountryName = countryName;
Subregion = subregion;
SubregionName = subregionName;
_point = point;
}
}
/// <summary>
/// Model for a Unity Tower floor entry.
/// </summary>
public partial class UnityTowerFloorModel : ObservableObject
{
public int Country { get; }
public string CountryName { get; }
[ObservableProperty]
private bool _unlocked;
public UnityTowerFloorModel(int country, string countryName, bool unlocked)
{
Country = country;
CountryName = countryName;
_unlocked = unlocked;
}
}
/// <summary>
/// ViewModel for the Unity Tower / Geonet editor (Gen 5).
/// Edits Geonet globe data and Unity Tower floor unlock status.
/// </summary>
public partial class UnityTower5ViewModel : SaveEditorViewModelBase
{
private readonly SAV5 SAV5;
private readonly UnityTower5 Tower;
[ObservableProperty] private bool _globalFlag;
[ObservableProperty] private bool _unityTowerFlag;
public ObservableCollection<GeonetEntry5Model> GeonetEntries { get; } = [];
public ObservableCollection<UnityTowerFloorModel> FloorEntries { get; } = [];
public string[] PointNames { get; } = ["None", "Blue", "Yellow", "Red"];
public UnityTower5ViewModel(SAV5 sav) : base(sav)
{
SAV5 = sav;
Tower = sav.UnityTower;
_globalFlag = Tower.GlobalFlag;
_unityTowerFlag = Tower.UnityTowerFlag;
LoadGeonet();
LoadFloors();
}
private void LoadGeonet()
{
GeonetEntries.Clear();
for (int i = 1; i <= UnityTower5.CountryCount; i++)
{
var country = i;
var countryName = $"Country {country}";
var subregionCount = UnityTower5.GetSubregionCount((byte)country);
if (subregionCount == 0)
{
var point = (int)Tower.GetCountrySubregion((byte)country, 0);
GeonetEntries.Add(new GeonetEntry5Model(country, countryName, 0, "Default", point));
}
else
{
for (int j = 1; j <= subregionCount; j++)
{
var point = (int)Tower.GetCountrySubregion((byte)country, (byte)j);
GeonetEntries.Add(new GeonetEntry5Model(country, countryName, j, $"Region {j}", point));
}
}
}
}
private void LoadFloors()
{
FloorEntries.Clear();
for (int i = 1; i <= UnityTower5.CountryCount; i++)
{
var countryName = $"Country {i}";
var unlocked = Tower.GetUnityTowerFloor((byte)i);
FloorEntries.Add(new UnityTowerFloorModel(i, countryName, unlocked));
}
}
[RelayCommand]
private void SetAllLocations()
{
Tower.SetAll();
GlobalFlag = Tower.GlobalFlag;
UnityTowerFlag = Tower.UnityTowerFlag;
LoadGeonet();
LoadFloors();
}
[RelayCommand]
private void SetAllLegalLocations()
{
Tower.SetAllLegal();
GlobalFlag = Tower.GlobalFlag;
UnityTowerFlag = Tower.UnityTowerFlag;
LoadGeonet();
LoadFloors();
}
[RelayCommand]
private void ClearLocations()
{
Tower.ClearAll();
GlobalFlag = Tower.GlobalFlag;
UnityTowerFlag = Tower.UnityTowerFlag;
LoadGeonet();
LoadFloors();
}
[RelayCommand]
private void Save()
{
Tower.ClearAll();
foreach (var entry in GeonetEntries)
{
if (entry.Country > 0)
Tower.SetCountrySubregion((byte)entry.Country, (byte)entry.Subregion, (GeonetPoint)entry.Point);
}
foreach (var floor in FloorEntries)
Tower.SetUnityTowerFloor((byte)floor.Country, floor.Unlocked);
Tower.SetSAVCountry();
Tower.GlobalFlag = GlobalFlag;
Tower.UnityTowerFlag = UnityTowerFlag;
SAV.State.Edited = true;
Modified = true;
}
}

View File

@ -0,0 +1,34 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.CGearImage5View"
x:DataType="vm:CGearImage5ViewModel"
Title="C-Gear Skin"
Width="350" Height="200"
MinWidth="300" MinHeight="150"
WindowStartupLocation="CenterOwner"
CanResize="False">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Close" Click="OnCloseClick" Width="80" />
</StackPanel>
<StackPanel Spacing="8" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="C-Gear Background Skin" FontWeight="Bold" FontSize="16"
HorizontalAlignment="Center" />
<TextBlock Text="{Binding SkinStatus}" HorizontalAlignment="Center" />
<StackPanel Orientation="Horizontal" Spacing="12" HorizontalAlignment="Center"
IsVisible="{Binding HasSkin}">
<TextBlock Text="Width:" VerticalAlignment="Center" />
<TextBlock Text="{Binding Width}" VerticalAlignment="Center" />
<TextBlock Text="Height:" VerticalAlignment="Center" />
<TextBlock Text="{Binding Height}" VerticalAlignment="Center" />
</StackPanel>
</StackPanel>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,16 @@
using Avalonia.Interactivity;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class CGearImage5View : SubformWindow
{
public CGearImage5View()
{
InitializeComponent();
}
private void OnCloseClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,94 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.DLC5View"
x:DataType="vm:DLC5ViewModel"
Title="Gen 5 DLC Editor"
Width="600" Height="550"
MinWidth="450" MinHeight="400"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<TabControl>
<!-- C-Gear -->
<TabItem Header="C-Gear">
<StackPanel Spacing="8" Margin="8">
<TextBlock Text="C-Gear Skin" FontWeight="Bold" FontSize="14" />
<TextBlock Text="{Binding CGearStatus}" />
</StackPanel>
</TabItem>
<!-- Battle Videos -->
<TabItem Header="Battle Videos">
<StackPanel Spacing="8" Margin="8">
<TextBlock Text="Battle Videos" FontWeight="Bold" FontSize="14" />
<ListBox ItemsSource="{Binding BattleVideos}" SelectedIndex="{Binding SelectedBattleVideoIndex}" MaxHeight="300">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:BattleVideo5Entry">
<TextBlock Text="{Binding Label}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</TabItem>
<!-- PWT (B2W2 only) -->
<TabItem Header="PWT" IsVisible="{Binding ShowPWT}">
<StackPanel Spacing="8" Margin="8">
<TextBlock Text="Pokemon World Tournament" FontWeight="Bold" FontSize="14" />
<ListBox ItemsSource="{Binding PWTEntries}" SelectedIndex="{Binding SelectedPWTIndex}" MaxHeight="300">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:PWT5Entry">
<TextBlock Text="{Binding Label}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</TabItem>
<!-- Pokestar (B2W2 only) -->
<TabItem Header="Pokestar" IsVisible="{Binding ShowPokestar}">
<StackPanel Spacing="8" Margin="8">
<TextBlock Text="Pokestar Studios" FontWeight="Bold" FontSize="14" />
<ListBox ItemsSource="{Binding PokestarMovies}" SelectedIndex="{Binding SelectedPokestarIndex}" MaxHeight="300">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:Pokestar5Entry">
<TextBlock Text="{Binding Label}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</TabItem>
<!-- Musical -->
<TabItem Header="Musical">
<StackPanel Spacing="8" Margin="8">
<TextBlock Text="Musical Show" FontWeight="Bold" FontSize="14" />
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="Musical Name:" VerticalAlignment="Center" />
<TextBox Text="{Binding MusicalName}" Width="200" />
</StackPanel>
</StackPanel>
</TabItem>
<!-- Memory Link -->
<TabItem Header="Memory Link">
<StackPanel Spacing="8" Margin="8">
<TextBlock Text="Memory Link Data" FontWeight="Bold" FontSize="14" />
<TextBlock Text="{Binding Link1Status}" />
<TextBlock Text="{Binding Link2Status}" />
</StackPanel>
</TabItem>
</TabControl>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class DLC5View : SubformWindow
{
public DLC5View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is DLC5ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,181 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.Misc5View"
x:DataType="vm:Misc5ViewModel"
Title="Gen 5 Misc Editor"
Width="700" Height="750"
MinWidth="550" MinHeight="500"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<TabControl>
<!-- Fly Destinations -->
<TabItem Header="Fly">
<StackPanel Spacing="8" Margin="8">
<Button Content="Unlock All" Command="{Binding UnlockAllFlyDestCommand}" HorizontalAlignment="Left" />
<ScrollViewer MaxHeight="500">
<ItemsControl ItemsSource="{Binding FlyDestinations}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:FlyDest5Model">
<CheckBox Content="{Binding Name}" IsChecked="{Binding Unlocked}" Margin="4,1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</TabItem>
<!-- Roamer (BW only) -->
<TabItem Header="Roamer" IsVisible="{Binding ShowRoamer}">
<StackPanel Spacing="8" Margin="8">
<Grid ColumnDefinitions="130,*" RowDefinitions="Auto,Auto,Auto,Auto" Margin="0,4">
<TextBlock Grid.Row="0" Grid.Column="0" Text="Tornadus (641):" VerticalAlignment="Center" Margin="0,4" />
<ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding RoamerStates}" SelectedIndex="{Binding Roamer641State}" Width="180" Margin="8,4" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Thundurus (642):" VerticalAlignment="Center" Margin="0,4" />
<ComboBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding RoamerStates}" SelectedIndex="{Binding Roamer642State}" Width="180" Margin="8,4" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Roam Status:" VerticalAlignment="Center" Margin="0,4" />
<ComboBox Grid.Row="2" Grid.Column="1" ItemsSource="{Binding RoamStatusStates}" SelectedIndex="{Binding RoamStatus}" Width="180" Margin="8,4" />
</Grid>
<CheckBox Content="Liberty Pass Activated" IsChecked="{Binding LibertyPass}" Margin="0,8" />
</StackPanel>
</TabItem>
<!-- Key System (B2W2 only) -->
<TabItem Header="Key System" IsVisible="{Binding ShowKeySystem}">
<StackPanel Spacing="8" Margin="8">
<Button Content="Unlock All" Command="{Binding UnlockAllKeysCommand}" HorizontalAlignment="Left" />
<ItemsControl ItemsSource="{Binding KeyEntries}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:KeyEntry5Model">
<CheckBox Content="{Binding Label}" IsChecked="{Binding Enabled}" Margin="4,1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</TabItem>
<!-- Musical Props -->
<TabItem Header="Musical">
<StackPanel Spacing="8" Margin="8">
<Button Content="Unlock All Props" Command="{Binding UnlockAllPropsCommand}" HorizontalAlignment="Left" />
<ScrollViewer MaxHeight="500">
<ItemsControl ItemsSource="{Binding Props}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:PropModel">
<CheckBox Content="{Binding Name}" IsChecked="{Binding Obtained}" Margin="4,1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</TabItem>
<!-- Battle Subway -->
<TabItem Header="Subway">
<ScrollViewer>
<StackPanel Spacing="8" Margin="8">
<TextBlock Text="Running Battle" FontWeight="Bold" FontSize="14" />
<Grid ColumnDefinitions="130,*" RowDefinitions="Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="0" Text="Current Type:" VerticalAlignment="Center" Margin="0,4" />
<NumericUpDown Grid.Row="0" Grid.Column="1" Value="{Binding SubwayCurrentType}" Minimum="0" Maximum="15" Width="120" Margin="8,4" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Current Battle:" VerticalAlignment="Center" Margin="0,4" />
<NumericUpDown Grid.Row="1" Grid.Column="1" Value="{Binding SubwayCurrentBattle}" Minimum="0" Maximum="999" Width="120" Margin="8,4" />
</Grid>
<TextBlock Text="Normal Flags" FontWeight="Bold" FontSize="14" Margin="0,8,0,0" />
<WrapPanel>
<CheckBox Content="Flag 0" IsChecked="{Binding SubwayFlag0}" Margin="4,2" />
<CheckBox Content="Flag 1" IsChecked="{Binding SubwayFlag1}" Margin="4,2" />
<CheckBox Content="Flag 2" IsChecked="{Binding SubwayFlag2}" Margin="4,2" />
<CheckBox Content="Flag 3" IsChecked="{Binding SubwayFlag3}" Margin="4,2" />
</WrapPanel>
<TextBlock Text="Super Flags" FontWeight="Bold" FontSize="14" Margin="0,8,0,0" />
<WrapPanel>
<CheckBox Content="Super Single" IsChecked="{Binding SuperSingle}" Margin="4,2" />
<CheckBox Content="Super Double" IsChecked="{Binding SuperDouble}" Margin="4,2" />
<CheckBox Content="Super Multi" IsChecked="{Binding SuperMulti}" Margin="4,2" />
<CheckBox Content="Flag 7" IsChecked="{Binding SubwayFlag7}" Margin="4,2" />
</WrapPanel>
<CheckBox Content="NPC Met" IsChecked="{Binding NpcMet}" Margin="4,4" />
<TextBlock Text="Normal Records" FontWeight="Bold" FontSize="14" Margin="0,8,0,0" />
<Grid ColumnDefinitions="130,100,100,100" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="1" Text="Past" FontWeight="SemiBold" Margin="4" />
<TextBlock Grid.Row="0" Grid.Column="2" Text="Record" FontWeight="SemiBold" Margin="4" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Single:" VerticalAlignment="Center" />
<NumericUpDown Grid.Row="1" Grid.Column="1" Value="{Binding SinglePast}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<NumericUpDown Grid.Row="1" Grid.Column="2" Value="{Binding SingleRecord}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Double:" VerticalAlignment="Center" />
<NumericUpDown Grid.Row="2" Grid.Column="1" Value="{Binding DoublePast}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<NumericUpDown Grid.Row="2" Grid.Column="2" Value="{Binding DoubleRecord}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<TextBlock Grid.Row="3" Grid.Column="0" Text="Multi NPC:" VerticalAlignment="Center" />
<NumericUpDown Grid.Row="3" Grid.Column="1" Value="{Binding MultiNpcPast}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<NumericUpDown Grid.Row="3" Grid.Column="2" Value="{Binding MultiNpcRecord}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="Multi Friends:" VerticalAlignment="Center" />
<NumericUpDown Grid.Row="4" Grid.Column="1" Value="{Binding MultiFriendsPast}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<NumericUpDown Grid.Row="4" Grid.Column="2" Value="{Binding MultiFriendsRecord}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
</Grid>
<TextBlock Text="Super Records" FontWeight="Bold" FontSize="14" Margin="0,8,0,0" />
<Grid ColumnDefinitions="130,100,100,100" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="1" Text="Past" FontWeight="SemiBold" Margin="4" />
<TextBlock Grid.Row="0" Grid.Column="2" Text="Record" FontWeight="SemiBold" Margin="4" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Super Single:" VerticalAlignment="Center" />
<NumericUpDown Grid.Row="1" Grid.Column="1" Value="{Binding SuperSinglePast}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<NumericUpDown Grid.Row="1" Grid.Column="2" Value="{Binding SuperSingleRecord}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Super Double:" VerticalAlignment="Center" />
<NumericUpDown Grid.Row="2" Grid.Column="1" Value="{Binding SuperDoublePast}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<NumericUpDown Grid.Row="2" Grid.Column="2" Value="{Binding SuperDoubleRecord}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<TextBlock Grid.Row="3" Grid.Column="0" Text="Super Multi NPC:" VerticalAlignment="Center" />
<NumericUpDown Grid.Row="3" Grid.Column="1" Value="{Binding SuperMultiNpcPast}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<NumericUpDown Grid.Row="3" Grid.Column="2" Value="{Binding SuperMultiNpcRecord}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="Super Multi Friends:" VerticalAlignment="Center" />
<NumericUpDown Grid.Row="4" Grid.Column="1" Value="{Binding SuperMultiFriendsPast}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
<NumericUpDown Grid.Row="4" Grid.Column="2" Value="{Binding SuperMultiFriendsRecord}" Minimum="0" Maximum="9999" Width="90" Margin="4" />
</Grid>
</StackPanel>
</ScrollViewer>
</TabItem>
<!-- Records -->
<TabItem Header="Records">
<StackPanel Spacing="8" Margin="8">
<TextBlock Text="Records" FontWeight="Bold" FontSize="14" />
<Grid ColumnDefinitions="100,100,100,*" RowDefinitions="Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="0" Text="Record16:" VerticalAlignment="Center" Margin="0,4" />
<NumericUpDown Grid.Row="0" Grid.Column="1" Value="{Binding Record16Index}" Minimum="0" Maximum="99" Width="90" Margin="4" />
<TextBlock Grid.Row="0" Grid.Column="2" Text="Value:" VerticalAlignment="Center" Margin="4" />
<NumericUpDown Grid.Row="0" Grid.Column="3" Value="{Binding Record16Value}" Minimum="0" Maximum="65535" Width="120" Margin="4" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Record32:" VerticalAlignment="Center" Margin="0,4" />
<NumericUpDown Grid.Row="1" Grid.Column="1" Value="{Binding Record32Index}" Minimum="0" Maximum="67" Width="90" Margin="4" />
<TextBlock Grid.Row="1" Grid.Column="2" Text="Value:" VerticalAlignment="Center" Margin="4" />
<NumericUpDown Grid.Row="1" Grid.Column="3" Value="{Binding Record32Value}" Minimum="0" Maximum="999999999" Width="120" Margin="4" />
</Grid>
</StackPanel>
</TabItem>
</TabControl>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class Misc5View : SubformWindow
{
public Misc5View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is Misc5ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,60 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.Pokedex5View"
x:DataType="vm:Pokedex5ViewModel"
Title="Gen 5 Pokedex Editor"
Width="700" Height="650"
MinWidth="500" MinHeight="400"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Complete All" Command="{Binding CompleteAllCommand}" />
<Button Content="Seen All" Command="{Binding SeenAllCommand}" />
<Button Content="Caught All" Command="{Binding CaughtAllCommand}" />
<Button Content="Clear All" Command="{Binding ClearAllCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<!-- Top controls -->
<StackPanel DockPanel.Dock="Top" Spacing="8" Margin="0,0,0,8">
<StackPanel Orientation="Horizontal" Spacing="12">
<CheckBox Content="National Dex Unlocked" IsChecked="{Binding NationalDexUnlocked}" />
<CheckBox Content="National Dex Active" IsChecked="{Binding NationalDexActive}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="Spinda PID:" VerticalAlignment="Center" />
<TextBox Text="{Binding SpindaPid}" Width="120" />
</StackPanel>
</StackPanel>
<!-- Search box -->
<TextBox DockPanel.Dock="Top" Watermark="Search species..."
Text="{Binding SearchText}" Margin="0,0,0,8" />
<!-- Species list -->
<ScrollViewer>
<ItemsControl ItemsSource="{Binding FilteredEntries}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:Pokedex5EntryModel">
<StackPanel Orientation="Horizontal" Spacing="6" Margin="4,2">
<TextBlock Text="{Binding Label}" Width="160" VerticalAlignment="Center" />
<CheckBox Content="Caught" IsChecked="{Binding Caught}" VerticalAlignment="Center" />
<CheckBox Content="Seen M" IsChecked="{Binding SeenMale}" VerticalAlignment="Center" />
<CheckBox Content="Seen F" IsChecked="{Binding SeenFemale}" VerticalAlignment="Center" />
<CheckBox Content="Disp M" IsChecked="{Binding DispMale}" VerticalAlignment="Center" />
<CheckBox Content="Disp F" IsChecked="{Binding DispFemale}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class Pokedex5View : SubformWindow
{
public Pokedex5View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is Pokedex5ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,77 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVBerryFieldXYView"
x:DataType="vm:SAVBerryFieldXYViewModel"
Title="Berry Field (XY)"
Width="500" Height="420"
MinWidth="400" MinHeight="350"
WindowStartupLocation="CenterOwner"
CanResize="False">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<Grid ColumnDefinitions="140,*">
<!-- Left: Plot list -->
<ListBox Grid.Column="0" ItemsSource="{Binding Plots}"
SelectedIndex="{Binding SelectedPlotIndex}"
Margin="0,0,8,0">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:BerryPlotModel">
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!-- Right: Plot details (read-only) -->
<ScrollViewer Grid.Column="1">
<StackPanel Spacing="8"
DataContext="{Binding SelectedPlot}"
x:DataType="vm:BerryPlotModel"
x:CompileBindings="False">
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,Auto,Auto">
<StackPanel Grid.Column="0" Grid.Row="0" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Berry" FontWeight="SemiBold" />
<TextBox Text="{Binding Berry}" IsReadOnly="True" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="U1" />
<TextBox Text="{Binding U1}" IsReadOnly="True" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="U2" />
<TextBox Text="{Binding U2}" IsReadOnly="True" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="U3" />
<TextBox Text="{Binding U3}" IsReadOnly="True" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="U4" />
<TextBox Text="{Binding U4}" IsReadOnly="True" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="2" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="U5" />
<TextBox Text="{Binding U5}" IsReadOnly="True" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="3" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="U6" />
<TextBox Text="{Binding U6}" IsReadOnly="True" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="3" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="U7" />
<TextBox Text="{Binding U7}" IsReadOnly="True" />
</StackPanel>
</Grid>
</StackPanel>
</ScrollViewer>
</Grid>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,16 @@
using Avalonia.Interactivity;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVBerryFieldXYView : SubformWindow
{
public SAVBerryFieldXYView()
{
InitializeComponent();
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,128 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVHallOfFame6View"
x:DataType="vm:SAVHallOfFame6ViewModel"
Title="Hall of Fame (Gen 6)"
Width="650" Height="700"
MinWidth="550" MinHeight="600"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Delete Entry" Command="{Binding DeleteEntryCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<Grid ColumnDefinitions="150,*">
<!-- Left: Entry list -->
<ListBox Grid.Column="0" ItemsSource="{Binding EntryNames}"
SelectedIndex="{Binding SelectedEntryIndex}"
Margin="0,0,8,0" />
<!-- Right: Details -->
<ScrollViewer Grid.Column="1">
<StackPanel Spacing="8">
<!-- Entry summary -->
<TextBox Text="{Binding EntryText}" IsReadOnly="True"
AcceptsReturn="True" Height="120"
FontFamily="Courier New" FontSize="12" />
<Grid ColumnDefinitions="*,*">
<StackPanel Grid.Column="0" Spacing="2" Margin="0,0,4,0">
<TextBlock Text="Clear Index" />
<TextBox Text="{Binding ClearIndex}" MaxLength="5" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="2" Margin="4,0,0,0">
<TextBlock Text="Party Member #" />
<NumericUpDown Value="{Binding MemberIndex}" Minimum="1"
Maximum="{Binding MaxMembers}" />
</StackPanel>
</Grid>
<Separator />
<TextBlock Text="Pokemon Details" FontWeight="SemiBold" FontSize="14" />
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<StackPanel Grid.Column="0" Grid.Row="0" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Species" />
<ComboBox ItemsSource="{Binding SpeciesList}"
SelectedValue="{Binding SelectedSpecies}"
SelectedValueBinding="{Binding Value}"
DisplayMemberBinding="{Binding Text}" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Held Item" />
<ComboBox ItemsSource="{Binding ItemsList}"
SelectedValue="{Binding SelectedItem}"
SelectedValueBinding="{Binding Value}"
DisplayMemberBinding="{Binding Text}" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Move 1" />
<ComboBox ItemsSource="{Binding MovesList}"
SelectedValue="{Binding Move1}"
SelectedValueBinding="{Binding Value}"
DisplayMemberBinding="{Binding Text}" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Move 2" />
<ComboBox ItemsSource="{Binding MovesList}"
SelectedValue="{Binding Move2}"
SelectedValueBinding="{Binding Value}"
DisplayMemberBinding="{Binding Text}" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Move 3" />
<ComboBox ItemsSource="{Binding MovesList}"
SelectedValue="{Binding Move3}"
SelectedValueBinding="{Binding Value}"
DisplayMemberBinding="{Binding Text}" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="2" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Move 4" />
<ComboBox ItemsSource="{Binding MovesList}"
SelectedValue="{Binding Move4}"
SelectedValueBinding="{Binding Value}"
DisplayMemberBinding="{Binding Text}" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="3" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Nickname" />
<TextBox Text="{Binding Nickname}" MaxLength="12" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="3" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="OT Name" />
<TextBox Text="{Binding OtName}" MaxLength="12" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="4" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="TID" />
<TextBox Text="{Binding Tid}" MaxLength="5" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="4" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="SID" />
<TextBox Text="{Binding Sid}" MaxLength="5" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="5" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Level" />
<NumericUpDown Value="{Binding Level}" Minimum="0" Maximum="100" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="5" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="EC" />
<TextBox Text="{Binding Ec}" MaxLength="8" />
</StackPanel>
<WrapPanel Grid.Column="0" Grid.Row="6" Grid.ColumnSpan="2" Margin="0,4">
<CheckBox Content="Shiny" IsChecked="{Binding IsShiny}" Margin="0,0,12,0" />
<CheckBox Content="Nicknamed" IsChecked="{Binding IsNicknamed}" />
</WrapPanel>
</Grid>
</StackPanel>
</ScrollViewer>
</Grid>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVHallOfFame6View : SubformWindow
{
public SAVHallOfFame6View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVHallOfFame6ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,74 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVLink6View"
x:DataType="vm:SAVLink6ViewModel"
Title="Link Data Editor (Gen 6)"
Width="550" Height="620"
MinWidth="480" MinHeight="520"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<ScrollViewer>
<StackPanel Spacing="8">
<CheckBox Content="Link Available" IsChecked="{Binding LinkAvailable}" />
<StackPanel Spacing="4">
<TextBlock Text="Link Source" FontWeight="SemiBold" />
<TextBox Text="{Binding LinkSource}" />
</StackPanel>
<Grid ColumnDefinitions="*,*" Margin="0,4">
<StackPanel Grid.Column="0" Spacing="2" Margin="0,0,4,0">
<TextBlock Text="Battle Points" FontWeight="SemiBold" />
<NumericUpDown Value="{Binding BattlePoints}" Minimum="0" Maximum="65535" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="2" Margin="4,0,0,0">
<TextBlock Text="Pokemiles" FontWeight="SemiBold" />
<NumericUpDown Value="{Binding Pokemiles}" Minimum="0" Maximum="65535" />
</StackPanel>
</Grid>
<Separator />
<TextBlock Text="Items" FontWeight="SemiBold" FontSize="14" />
<Grid ColumnDefinitions="*,80" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto">
<ComboBox Grid.Column="0" Grid.Row="0" ItemsSource="{Binding ItemsList}" SelectedValue="{Binding Item1}" SelectedValueBinding="{Binding Value}" DisplayMemberBinding="{Binding Text}" Margin="0,2" />
<NumericUpDown Grid.Column="1" Grid.Row="0" Value="{Binding Quantity1}" Minimum="0" Maximum="255" Margin="4,2,0,2" />
<ComboBox Grid.Column="0" Grid.Row="1" ItemsSource="{Binding ItemsList}" SelectedValue="{Binding Item2}" SelectedValueBinding="{Binding Value}" DisplayMemberBinding="{Binding Text}" Margin="0,2" />
<NumericUpDown Grid.Column="1" Grid.Row="1" Value="{Binding Quantity2}" Minimum="0" Maximum="255" Margin="4,2,0,2" />
<ComboBox Grid.Column="0" Grid.Row="2" ItemsSource="{Binding ItemsList}" SelectedValue="{Binding Item3}" SelectedValueBinding="{Binding Value}" DisplayMemberBinding="{Binding Text}" Margin="0,2" />
<NumericUpDown Grid.Column="1" Grid.Row="2" Value="{Binding Quantity3}" Minimum="0" Maximum="255" Margin="4,2,0,2" />
<ComboBox Grid.Column="0" Grid.Row="3" ItemsSource="{Binding ItemsList}" SelectedValue="{Binding Item4}" SelectedValueBinding="{Binding Value}" DisplayMemberBinding="{Binding Text}" Margin="0,2" />
<NumericUpDown Grid.Column="1" Grid.Row="3" Value="{Binding Quantity4}" Minimum="0" Maximum="255" Margin="4,2,0,2" />
<ComboBox Grid.Column="0" Grid.Row="4" ItemsSource="{Binding ItemsList}" SelectedValue="{Binding Item5}" SelectedValueBinding="{Binding Value}" DisplayMemberBinding="{Binding Text}" Margin="0,2" />
<NumericUpDown Grid.Column="1" Grid.Row="4" Value="{Binding Quantity5}" Minimum="0" Maximum="255" Margin="4,2,0,2" />
<ComboBox Grid.Column="0" Grid.Row="5" ItemsSource="{Binding ItemsList}" SelectedValue="{Binding Item6}" SelectedValueBinding="{Binding Value}" DisplayMemberBinding="{Binding Text}" Margin="0,2" />
<NumericUpDown Grid.Column="1" Grid.Row="5" Value="{Binding Quantity6}" Minimum="0" Maximum="255" Margin="4,2,0,2" />
</Grid>
<Separator />
<TextBlock Text="Pokemon (Read Only)" FontWeight="SemiBold" FontSize="14" />
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,Auto">
<TextBox Grid.Column="0" Grid.Row="0" Text="{Binding Pkm1}" IsReadOnly="True" Margin="0,2,4,2" />
<TextBox Grid.Column="1" Grid.Row="0" Text="{Binding Pkm2}" IsReadOnly="True" Margin="4,2,0,2" />
<TextBox Grid.Column="0" Grid.Row="1" Text="{Binding Pkm3}" IsReadOnly="True" Margin="0,2,4,2" />
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Pkm4}" IsReadOnly="True" Margin="4,2,0,2" />
<TextBox Grid.Column="0" Grid.Row="2" Text="{Binding Pkm5}" IsReadOnly="True" Margin="0,2,4,2" />
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Pkm6}" IsReadOnly="True" Margin="4,2,0,2" />
</Grid>
</StackPanel>
</ScrollViewer>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVLink6View : SubformWindow
{
public SAVLink6View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVLink6ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,79 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVOPower6View"
x:DataType="vm:SAVOPower6ViewModel"
Title="O-Power Editor (Gen 6)"
Width="550" Height="600"
MinWidth="480" MinHeight="500"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Give All" Command="{Binding GiveAllCommand}" />
<Button Content="Clear All" Command="{Binding ClearAllCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<ScrollViewer>
<StackPanel Spacing="12">
<!-- Points -->
<StackPanel Spacing="4">
<TextBlock Text="Points" FontWeight="SemiBold" />
<NumericUpDown Value="{Binding Points}" Minimum="0" Maximum="255" />
</StackPanel>
<!-- Field Levels -->
<TextBlock Text="Field O-Powers" FontWeight="SemiBold" FontSize="14" />
<ItemsControl ItemsSource="{Binding FieldLevels}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:OPowerLevelModel">
<Grid ColumnDefinitions="120,*,*" Margin="0,2">
<TextBlock Grid.Column="0" Text="{Binding Name}"
VerticalAlignment="Center" />
<NumericUpDown Grid.Column="1" Value="{Binding Level1}"
Minimum="0" Maximum="3" Margin="4,0" />
<NumericUpDown Grid.Column="2" Value="{Binding Level2}"
Minimum="0" Maximum="3" Margin="4,0" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Battle Levels -->
<TextBlock Text="Battle O-Powers" FontWeight="SemiBold" FontSize="14" />
<ItemsControl ItemsSource="{Binding BattleLevels}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:OPowerLevelModel">
<Grid ColumnDefinitions="120,*,*" Margin="0,2">
<TextBlock Grid.Column="0" Text="{Binding Name}"
VerticalAlignment="Center" />
<NumericUpDown Grid.Column="1" Value="{Binding Level1}"
Minimum="0" Maximum="3" Margin="4,0" />
<NumericUpDown Grid.Column="2" Value="{Binding Level2}"
Minimum="0" Maximum="3" Margin="4,0" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Unlock Flags -->
<TextBlock Text="Unlock Flags" FontWeight="SemiBold" FontSize="14" />
<ItemsControl ItemsSource="{Binding UnlockFlags}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:OPowerUnlockModel">
<CheckBox Content="{Binding Name}"
IsChecked="{Binding IsUnlocked}" Margin="0,1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVOPower6View : SubformWindow
{
public SAVOPower6View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVOPower6ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,39 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVPokeBlockORASView"
x:DataType="vm:SAVPokeBlockORASViewModel"
Title="PokeBlock Editor (ORAS)"
Width="400" Height="550"
MinWidth="350" MinHeight="450"
WindowStartupLocation="CenterOwner"
CanResize="False">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Give All" Command="{Binding GiveAllCommand}" />
<Button Content="Clear All" Command="{Binding ClearAllCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Blocks}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:PokeBlock6Model">
<Grid ColumnDefinitions="*,120" Margin="0,2">
<TextBlock Grid.Column="0" Text="{Binding Label}"
VerticalAlignment="Center" />
<NumericUpDown Grid.Column="1" Value="{Binding Count}"
Minimum="0" Maximum="999" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVPokeBlockORASView : SubformWindow
{
public SAVPokeBlockORASView()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVPokeBlockORASViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,93 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVPokedexORASView"
x:DataType="vm:SAVPokedexORASViewModel"
Title="Pokedex Editor (ORAS)"
Width="620" Height="680"
MinWidth="520" MinHeight="580"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Seen All" Command="{Binding SeenAllCommand}" />
<Button Content="Caught All" Command="{Binding CaughtAllCommand}" />
<Button Content="Complete" Command="{Binding CompleteCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<Grid ColumnDefinitions="180,*">
<!-- Left: Species list -->
<ListBox Grid.Column="0" ItemsSource="{Binding SpeciesNames}"
SelectedIndex="{Binding SelectedSpeciesIndex}"
Margin="0,0,8,0" />
<!-- Right: Details -->
<ScrollViewer Grid.Column="1">
<StackPanel Spacing="8">
<CheckBox Content="National Dex Unlocked" IsChecked="{Binding NationalDexUnlocked}" />
<CheckBox Content="National Dex Active" IsChecked="{Binding NationalDexActive}" />
<StackPanel Spacing="4">
<TextBlock Text="Spinda PID" FontWeight="SemiBold" />
<TextBox Text="{Binding SpindaPid}" MaxLength="8" />
</StackPanel>
<Separator />
<CheckBox Content="Caught" IsChecked="{Binding Caught}" FontWeight="SemiBold" />
<TextBlock Text="Seen" FontWeight="SemiBold" />
<WrapPanel>
<CheckBox Content="Male" IsChecked="{Binding SeenMale}" Margin="0,0,8,0" />
<CheckBox Content="Female" IsChecked="{Binding SeenFemale}" Margin="0,0,8,0" />
<CheckBox Content="Male Shiny" IsChecked="{Binding SeenMaleShiny}" Margin="0,0,8,0" />
<CheckBox Content="Female Shiny" IsChecked="{Binding SeenFemaleShiny}" />
</WrapPanel>
<TextBlock Text="Displayed" FontWeight="SemiBold" />
<WrapPanel>
<CheckBox Content="Male" IsChecked="{Binding DisplayedMale}" Margin="0,0,8,0" />
<CheckBox Content="Female" IsChecked="{Binding DisplayedFemale}" Margin="0,0,8,0" />
<CheckBox Content="Male Shiny" IsChecked="{Binding DisplayedMaleShiny}" Margin="0,0,8,0" />
<CheckBox Content="Female Shiny" IsChecked="{Binding DisplayedFemaleShiny}" />
</WrapPanel>
<TextBlock Text="Languages" FontWeight="SemiBold" />
<WrapPanel>
<CheckBox Content="JPN" IsChecked="{Binding LangJPN}" Margin="0,0,8,0" />
<CheckBox Content="ENG" IsChecked="{Binding LangENG}" Margin="0,0,8,0" />
<CheckBox Content="FRE" IsChecked="{Binding LangFRE}" Margin="0,0,8,0" />
<CheckBox Content="ITA" IsChecked="{Binding LangITA}" Margin="0,0,8,0" />
<CheckBox Content="GER" IsChecked="{Binding LangGER}" Margin="0,0,8,0" />
<CheckBox Content="SPA" IsChecked="{Binding LangSPA}" Margin="0,0,8,0" />
<CheckBox Content="KOR" IsChecked="{Binding LangKOR}" />
</WrapPanel>
<Separator />
<TextBlock Text="DexNav Counts" FontWeight="SemiBold" />
<Grid ColumnDefinitions="*,*">
<StackPanel Grid.Column="0" Spacing="2" Margin="0,0,4,0">
<TextBlock Text="Seen Count" />
<NumericUpDown Value="{Binding CountSeen}" Minimum="0" Maximum="65535" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="2" Margin="4,0,0,0">
<TextBlock Text="Obtained Count" />
<NumericUpDown Value="{Binding CountObtained}" Minimum="0" Maximum="65535" />
</StackPanel>
</Grid>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Max DexNav" Command="{Binding MaxDexNavCommand}" />
<Button Content="Reset DexNav" Command="{Binding ResetDexNavCommand}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</Grid>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVPokedexORASView : SubformWindow
{
public SAVPokedexORASView()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVPokedexORASViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,75 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVPokedexXYView"
x:DataType="vm:SAVPokedexXYViewModel"
Title="Pokedex Editor (XY)"
Width="600" Height="650"
MinWidth="500" MinHeight="550"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Seen All" Command="{Binding SeenAllCommand}" />
<Button Content="Caught All" Command="{Binding CaughtAllCommand}" />
<Button Content="Complete" Command="{Binding CompleteCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<Grid ColumnDefinitions="180,*">
<!-- Left: Species list -->
<ListBox Grid.Column="0" ItemsSource="{Binding SpeciesNames}"
SelectedIndex="{Binding SelectedSpeciesIndex}"
Margin="0,0,8,0" />
<!-- Right: Details -->
<ScrollViewer Grid.Column="1">
<StackPanel Spacing="8">
<CheckBox Content="National Dex Unlocked" IsChecked="{Binding NationalDexUnlocked}" />
<CheckBox Content="National Dex Active" IsChecked="{Binding NationalDexActive}" />
<StackPanel Spacing="4">
<TextBlock Text="Spinda PID" FontWeight="SemiBold" />
<TextBox Text="{Binding SpindaPid}" MaxLength="8" />
</StackPanel>
<Separator />
<CheckBox Content="Caught" IsChecked="{Binding Caught}" FontWeight="SemiBold" />
<TextBlock Text="Seen" FontWeight="SemiBold" />
<WrapPanel>
<CheckBox Content="Male" IsChecked="{Binding SeenMale}" Margin="0,0,8,0" />
<CheckBox Content="Female" IsChecked="{Binding SeenFemale}" Margin="0,0,8,0" />
<CheckBox Content="Male Shiny" IsChecked="{Binding SeenMaleShiny}" Margin="0,0,8,0" />
<CheckBox Content="Female Shiny" IsChecked="{Binding SeenFemaleShiny}" />
</WrapPanel>
<TextBlock Text="Displayed" FontWeight="SemiBold" />
<WrapPanel>
<CheckBox Content="Male" IsChecked="{Binding DisplayedMale}" Margin="0,0,8,0" />
<CheckBox Content="Female" IsChecked="{Binding DisplayedFemale}" Margin="0,0,8,0" />
<CheckBox Content="Male Shiny" IsChecked="{Binding DisplayedMaleShiny}" Margin="0,0,8,0" />
<CheckBox Content="Female Shiny" IsChecked="{Binding DisplayedFemaleShiny}" />
</WrapPanel>
<TextBlock Text="Languages" FontWeight="SemiBold" />
<WrapPanel>
<CheckBox Content="JPN" IsChecked="{Binding LangJPN}" Margin="0,0,8,0" />
<CheckBox Content="ENG" IsChecked="{Binding LangENG}" Margin="0,0,8,0" />
<CheckBox Content="FRE" IsChecked="{Binding LangFRE}" Margin="0,0,8,0" />
<CheckBox Content="ITA" IsChecked="{Binding LangITA}" Margin="0,0,8,0" />
<CheckBox Content="GER" IsChecked="{Binding LangGER}" Margin="0,0,8,0" />
<CheckBox Content="SPA" IsChecked="{Binding LangSPA}" Margin="0,0,8,0" />
<CheckBox Content="KOR" IsChecked="{Binding LangKOR}" />
</WrapPanel>
</StackPanel>
</ScrollViewer>
</Grid>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVPokedexXYView : SubformWindow
{
public SAVPokedexXYView()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVPokedexXYViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,43 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVPokepuff6View"
x:DataType="vm:SAVPokepuff6ViewModel"
Title="Pokepuff Editor (Gen 6)"
Width="400" Height="550"
MinWidth="350" MinHeight="450"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Give All" Command="{Binding GiveAllCommand}" />
<Button Content="Give Best" Command="{Binding GiveBestCommand}" />
<Button Content="Clear" Command="{Binding ClearAllCommand}" />
<Button Content="Sort" Command="{Binding SortCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Slots}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:PokepuffSlotModel">
<Grid ColumnDefinitions="60,*" Margin="0,2">
<TextBlock Grid.Column="0" Text="{Binding DisplayName}"
VerticalAlignment="Center" />
<ComboBox Grid.Column="1"
ItemsSource="{Binding $parent[views:SubformWindow].((vm:SAVPokepuff6ViewModel)DataContext).PuffNames}"
SelectedIndex="{Binding SelectedPuffIndex}"
HorizontalAlignment="Stretch" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVPokepuff6View : SubformWindow
{
public SAVPokepuff6View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVPokepuff6ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,41 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVRoamer6View"
x:DataType="vm:SAVRoamer6ViewModel"
Title="Roaming Pokemon (Gen 6)"
Width="380" Height="300"
MinWidth="320" MinHeight="260"
WindowStartupLocation="CenterOwner"
CanResize="False">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<StackPanel Spacing="8">
<StackPanel Spacing="4">
<TextBlock Text="Species" FontWeight="SemiBold" />
<ComboBox ItemsSource="{Binding SpeciesChoices}"
SelectedIndex="{Binding SelectedSpeciesIndex}" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Roam State" FontWeight="SemiBold" />
<ComboBox ItemsSource="{Binding RoamStateChoices}"
SelectedIndex="{Binding SelectedRoamStateIndex}" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Times Encountered" FontWeight="SemiBold" />
<NumericUpDown Value="{Binding TimesEncountered}" Minimum="0" Maximum="4294967295" />
</StackPanel>
</StackPanel>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVRoamer6View : SubformWindow
{
public SAVRoamer6View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVRoamer6ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,87 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVSecretBase6View"
x:DataType="vm:SAVSecretBase6ViewModel"
Title="Secret Base Editor (Gen 6)"
Width="620" Height="620"
MinWidth="520" MinHeight="500"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Give All Decor" Command="{Binding GiveAllDecorCommand}" />
<Button Content="Delete Base" Command="{Binding DeleteBaseCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<Grid ColumnDefinitions="170,*">
<!-- Left: Base list -->
<ListBox Grid.Column="0" ItemsSource="{Binding BaseNames}"
SelectedIndex="{Binding SelectedBaseIndex}"
Margin="0,0,8,0" />
<!-- Right: Details -->
<ScrollViewer Grid.Column="1">
<StackPanel Spacing="8">
<TextBlock Text="Base Info" FontWeight="SemiBold" FontSize="14" />
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,Auto">
<StackPanel Grid.Column="0" Grid.Row="0" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Trainer Name" />
<TextBox Text="{Binding TrainerName}" MaxLength="12" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Location ID" />
<NumericUpDown Value="{Binding BaseLocation}" Minimum="-1" Maximum="85" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Team Name" />
<TextBox Text="{Binding TeamName}" MaxLength="16" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Team Slogan" />
<TextBox Text="{Binding TeamSlogan}" MaxLength="16" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Spacing="2" Margin="0,0,0,4">
<TextBlock Text="Captured Record (Flags)" />
<NumericUpDown Value="{Binding CapturedRecord}" Minimum="0" Maximum="4294967295" />
</StackPanel>
</Grid>
<Separator />
<TextBlock Text="Decoration Placements" FontWeight="SemiBold" FontSize="14" />
<StackPanel Spacing="4">
<TextBlock Text="Placement Index" />
<NumericUpDown Value="{Binding PlacementIndex}" Minimum="0" Maximum="27" />
</StackPanel>
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto">
<StackPanel Grid.Column="0" Grid.Row="0" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Good" />
<NumericUpDown Value="{Binding PlacementGood}" Minimum="0" Maximum="65535" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Rotation" />
<NumericUpDown Value="{Binding PlacementRotation}" Minimum="0" Maximum="255" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="X" />
<NumericUpDown Value="{Binding PlacementX}" Minimum="0" Maximum="65535" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Y" />
<NumericUpDown Value="{Binding PlacementY}" Minimum="0" Maximum="65535" />
</StackPanel>
</Grid>
</StackPanel>
</ScrollViewer>
</Grid>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVSecretBase6View : SubformWindow
{
public SAVSecretBase6View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVSecretBase6ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,95 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVSuperTrain6View"
x:DataType="vm:SAVSuperTrain6ViewModel"
Title="Super Training Editor (Gen 6)"
Width="600" Height="650"
MinWidth="500" MinHeight="500"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<ScrollViewer>
<StackPanel Spacing="8">
<!-- Training Bags -->
<TextBlock Text="Training Bags" FontWeight="SemiBold" FontSize="14" />
<ItemsControl ItemsSource="{Binding BagSlots}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:TrainingBagSlotModel">
<Grid ColumnDefinitions="60,*" Margin="0,2">
<TextBlock Grid.Column="0" Text="{Binding DisplayName}"
VerticalAlignment="Center" />
<ComboBox Grid.Column="1"
ItemsSource="{Binding $parent[views:SubformWindow].((vm:SAVSuperTrain6ViewModel)DataContext).BagNames}"
SelectedIndex="{Binding SelectedBagIndex}"
HorizontalAlignment="Stretch" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Separator Margin="0,4" />
<!-- Stage Records -->
<TextBlock Text="Stage Records" FontWeight="SemiBold" FontSize="14" />
<StackPanel Spacing="4">
<TextBlock Text="Stage" />
<ComboBox ItemsSource="{Binding StageNames}"
SelectedIndex="{Binding SelectedStageIndex}"
HorizontalAlignment="Stretch" />
</StackPanel>
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,Auto,Auto">
<StackPanel Grid.Column="0" Grid.Row="0" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Species 1" />
<ComboBox ItemsSource="{Binding SpeciesList}"
SelectedValue="{Binding Species1}"
SelectedValueBinding="{Binding Value}"
DisplayMemberBinding="{Binding Text}" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Species 2" />
<ComboBox ItemsSource="{Binding SpeciesList}"
SelectedValue="{Binding Species2}"
SelectedValueBinding="{Binding Value}"
DisplayMemberBinding="{Binding Text}" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Gender 1" />
<TextBox Text="{Binding Gender1}" MaxLength="3" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Gender 2" />
<TextBox Text="{Binding Gender2}" MaxLength="3" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Form 1" />
<TextBox Text="{Binding Form1}" MaxLength="3" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="2" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Form 2" />
<TextBox Text="{Binding Form2}" MaxLength="3" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="3" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Time 1" />
<TextBox Text="{Binding Time1}" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="3" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Time 2" />
<TextBox Text="{Binding Time2}" />
</StackPanel>
</Grid>
</StackPanel>
</ScrollViewer>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVSuperTrain6View : SubformWindow
{
public SAVSuperTrain6View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVSuperTrain6ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,123 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.SAVTrainer6View"
x:DataType="vm:SAVTrainer6ViewModel"
Title="Trainer Editor (Gen 6)"
Width="550" Height="700"
MinWidth="480" MinHeight="600"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<ScrollViewer>
<StackPanel Spacing="8">
<!-- Basic Info -->
<TextBlock Text="Basic Info" FontWeight="SemiBold" FontSize="14" />
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,Auto">
<StackPanel Grid.Column="0" Grid.Row="0" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="OT Name" />
<TextBox Text="{Binding OtName}" MaxLength="12" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="Gender" />
<ComboBox ItemsSource="{Binding GenderChoices}"
SelectedIndex="{Binding Gender}" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="TID" />
<TextBox Text="{Binding Tid}" MaxLength="5" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Spacing="2" Margin="4,0,0,4">
<TextBlock Text="SID" />
<TextBox Text="{Binding Sid}" MaxLength="5" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Spacing="2" Margin="0,0,4,4">
<TextBlock Text="Money" />
<StackPanel Orientation="Horizontal" Spacing="4">
<TextBox Text="{Binding Money}" MaxLength="7" />
<Button Content="Max" Command="{Binding MaxCashCommand}" />
</StackPanel>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="2" Spacing="2" Margin="4,0,0,4"
IsVisible="{Binding ShowStyle}">
<TextBlock Text="Style" />
<TextBox Text="{Binding Style}" MaxLength="3" />
</StackPanel>
</Grid>
<Separator />
<!-- Play Time -->
<TextBlock Text="Play Time" FontWeight="SemiBold" FontSize="14" />
<Grid ColumnDefinitions="*,*,*">
<StackPanel Grid.Column="0" Spacing="2" Margin="0,0,4,0">
<TextBlock Text="Hours" />
<NumericUpDown Value="{Binding PlayedHours}" Minimum="0" Maximum="65535" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="2" Margin="4,0,4,0">
<TextBlock Text="Minutes" />
<NumericUpDown Value="{Binding PlayedMinutes}" Minimum="0" Maximum="59" />
</StackPanel>
<StackPanel Grid.Column="2" Spacing="2" Margin="4,0,0,0">
<TextBlock Text="Seconds" />
<NumericUpDown Value="{Binding PlayedSeconds}" Minimum="0" Maximum="59" />
</StackPanel>
</Grid>
<!-- BP / Pokemiles -->
<Grid ColumnDefinitions="*,*">
<StackPanel Grid.Column="0" Spacing="2" Margin="0,0,4,0">
<TextBlock Text="BP" />
<TextBox Text="{Binding Bp}" MaxLength="5" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="2" Margin="4,0,0,0">
<TextBlock Text="Pokemiles" />
<TextBox Text="{Binding Pokemiles}" MaxLength="7" />
</StackPanel>
</Grid>
<Separator />
<!-- Badges -->
<TextBlock Text="Badges" FontWeight="SemiBold" FontSize="14" />
<WrapPanel>
<CheckBox Content="Badge 1" IsChecked="{Binding Badge1}" Margin="0,0,8,0" />
<CheckBox Content="Badge 2" IsChecked="{Binding Badge2}" Margin="0,0,8,0" />
<CheckBox Content="Badge 3" IsChecked="{Binding Badge3}" Margin="0,0,8,0" />
<CheckBox Content="Badge 4" IsChecked="{Binding Badge4}" Margin="0,0,8,0" />
<CheckBox Content="Badge 5" IsChecked="{Binding Badge5}" Margin="0,0,8,0" />
<CheckBox Content="Badge 6" IsChecked="{Binding Badge6}" Margin="0,0,8,0" />
<CheckBox Content="Badge 7" IsChecked="{Binding Badge7}" Margin="0,0,8,0" />
<CheckBox Content="Badge 8" IsChecked="{Binding Badge8}" />
</WrapPanel>
<!-- Mega -->
<WrapPanel>
<CheckBox Content="Mega Evolution Unlocked" IsChecked="{Binding MegaUnlocked}" Margin="0,0,12,0" />
<CheckBox Content="Mega Rayquaza Unlocked" IsChecked="{Binding MegaRayquazaUnlocked}"
IsVisible="{Binding ShowMegaRayquaza}" />
</WrapPanel>
<Separator />
<!-- Sayings -->
<TextBlock Text="Sayings" FontWeight="SemiBold" FontSize="14" />
<TextBox Text="{Binding Saying1}" Watermark="Saying 1" Margin="0,2" />
<TextBox Text="{Binding Saying2}" Watermark="Saying 2" Margin="0,2" />
<TextBox Text="{Binding Saying3}" Watermark="Saying 3" Margin="0,2" />
<TextBox Text="{Binding Saying4}" Watermark="Saying 4" Margin="0,2" />
<TextBox Text="{Binding Saying5}" Watermark="Saying 5" Margin="0,2" />
</StackPanel>
</ScrollViewer>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class SAVTrainer6View : SubformWindow
{
public SAVTrainer6View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is SAVTrainer6ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}

View File

@ -0,0 +1,68 @@
<views:SubformWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
xmlns:vm="using:PKHeX.Avalonia.ViewModels.Subforms"
x:Class="PKHeX.Avalonia.Views.Subforms.UnityTower5View"
x:DataType="vm:UnityTower5ViewModel"
Title="Unity Tower / Geonet Editor"
Width="700" Height="600"
MinWidth="550" MinHeight="400"
WindowStartupLocation="CenterOwner"
CanResize="True">
<DockPanel Margin="8">
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Set All" Command="{Binding SetAllLocationsCommand}" />
<Button Content="Set Legal" Command="{Binding SetAllLegalLocationsCommand}" />
<Button Content="Clear" Command="{Binding ClearLocationsCommand}" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>
<!-- Top flags -->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="12" Margin="0,0,0,8">
<CheckBox Content="Global Flag" IsChecked="{Binding GlobalFlag}" />
<CheckBox Content="Unity Tower Flag" IsChecked="{Binding UnityTowerFlag}" />
</StackPanel>
<TabControl>
<!-- Geonet -->
<TabItem Header="Geonet">
<DataGrid ItemsSource="{Binding GeonetEntries}"
AutoGenerateColumns="False"
CanUserResizeColumns="True"
CanUserSortColumns="True"
IsReadOnly="False"
GridLinesVisibility="Horizontal">
<DataGrid.Columns>
<DataGridTextColumn Header="Country" Binding="{Binding CountryName}" IsReadOnly="True" Width="150" />
<DataGridTextColumn Header="Subregion" Binding="{Binding SubregionName}" IsReadOnly="True" Width="150" />
<DataGridTemplateColumn Header="Point" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="vm:GeonetEntry5Model">
<NumericUpDown Value="{Binding Point}" Minimum="0" Maximum="3" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</TabItem>
<!-- Unity Tower Floors -->
<TabItem Header="Unity Tower">
<ScrollViewer>
<ItemsControl ItemsSource="{Binding FloorEntries}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:UnityTowerFloorModel">
<CheckBox Content="{Binding CountryName}" IsChecked="{Binding Unlocked}" Margin="4,1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</TabItem>
</TabControl>
</DockPanel>
</views:SubformWindow>

View File

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
using PKHeX.Avalonia.ViewModels.Subforms;
namespace PKHeX.Avalonia.Views.Subforms;
public partial class UnityTower5View : SubformWindow
{
public UnityTower5View()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
if (DataContext is UnityTower5ViewModel vm)
vm.SaveCommand.Execute(null);
CloseWithResult(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
CloseWithResult(false);
}
}