Merge pull request #10 from kwsch/master
Update from upstream repo kwsch/PKHeX
1
.gitignore
vendored
|
@ -40,6 +40,7 @@ local.properties
|
|||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
*.vs
|
||||
|
||||
# Build results
|
||||
|
||||
|
|
1
PKHeX.WinForms/MainWindow/Main.Designer.cs
generated
|
@ -926,6 +926,7 @@
|
|||
this.Label_CurLevel.TabIndex = 7;
|
||||
this.Label_CurLevel.Text = "Level:";
|
||||
this.Label_CurLevel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.Label_CurLevel.Click += new System.EventHandler(this.clickMetLocation);
|
||||
//
|
||||
// TB_Level
|
||||
//
|
||||
|
|
|
@ -320,14 +320,14 @@ namespace PKHeX.WinForms
|
|||
string supported = string.Join(";", SAV.PKMExtensions.Select(s => "*."+s).Concat(new[] {"*.pkm"}));
|
||||
OpenFileDialog ofd = new OpenFileDialog
|
||||
{
|
||||
Filter = $"Supported Files|main;*.sav;*.bin;*.{ekx};{supported};*.bak" +
|
||||
Filter = "All Files|*.*" +
|
||||
$"|Supported Files|main;*.sav;*.dat;*.gci;*.bin;*.{ekx};{supported};*.bak" +
|
||||
"|3DS Main Files|main" +
|
||||
"|Save Files|*.sav" +
|
||||
"|Save Files|*.sav;*.dat;*.gci" +
|
||||
$"|Decrypted PKM File|{supported}" +
|
||||
$"|Encrypted PKM File|*.{ekx}" +
|
||||
"|Binary File|*.bin" +
|
||||
"|Backup File|*.bak" +
|
||||
"|All Files|*.*"
|
||||
"|Backup File|*.bak"
|
||||
};
|
||||
|
||||
// Detect main
|
||||
|
@ -691,7 +691,9 @@ namespace PKHeX.WinForms
|
|||
string ext = Path.GetExtension(path);
|
||||
FileInfo fi = new FileInfo(path);
|
||||
if (fi.Length > 0x10009C && fi.Length != 0x380000)
|
||||
WinFormsUtil.Error("Input file is too large.", path);
|
||||
WinFormsUtil.Error("Input file is too large." + Environment.NewLine + $"Size: {fi.Length} bytes", path);
|
||||
else if (fi.Length < 32)
|
||||
WinFormsUtil.Error("Input file is too small." + Environment.NewLine + $"Size: {fi.Length} bytes", path);
|
||||
else
|
||||
{
|
||||
byte[] input; try { input = File.ReadAllBytes(path); }
|
||||
|
@ -844,52 +846,22 @@ namespace PKHeX.WinForms
|
|||
}
|
||||
private bool openXOR(byte[] input, string path)
|
||||
{
|
||||
// Detection of stored Decryption XORpads:
|
||||
if (ModifierKeys == Keys.Control) return false; // no xorpad compatible
|
||||
byte[] savID = input.Take(0x10).ToArray();
|
||||
string exepath = Application.StartupPath;
|
||||
string xorpath = exepath.Clone().ToString();
|
||||
string[] XORpads = Directory.GetFiles(xorpath);
|
||||
// try to get a save file via xorpad in same folder
|
||||
string[] pads = Directory.GetFiles(path);
|
||||
var s = SaveUtil.getSAVfromXORpads(input, pads);
|
||||
|
||||
int loop = 0;
|
||||
|
||||
while (xorpath == exepath && loop++ == 0)
|
||||
if (s == null) // failed to find xorpad in path folder
|
||||
{
|
||||
foreach (byte[] data in from file in XORpads let fi = new FileInfo(file) where (fi.Name.ToLower().Contains("xorpad") || fi.Name.ToLower().Contains("key")) && (fi.Length == 0x10009C || fi.Length == 0x100000) select File.ReadAllBytes(file))
|
||||
{
|
||||
// Fix xorpad alignment
|
||||
byte[] xorpad = data;
|
||||
if (xorpad.Length == 0x10009C) // Trim off Powersaves' header
|
||||
xorpad = xorpad.Skip(0x9C).ToArray(); // returns 0x100000
|
||||
|
||||
if (!xorpad.Take(0x10).SequenceEqual(savID)) continue;
|
||||
|
||||
// Set up Decrypted File
|
||||
byte[] decryptedPS = input.Skip(0x5400).Take(SaveUtil.SIZE_G6ORAS).ToArray();
|
||||
|
||||
// xor through and decrypt
|
||||
for (int z = 0; z < decryptedPS.Length; z++)
|
||||
decryptedPS[z] ^= xorpad[0x5400 + z];
|
||||
|
||||
// Weakly check the validity of the decrypted content
|
||||
if (BitConverter.ToUInt32(decryptedPS, SaveUtil.SIZE_G6ORAS - 0x1F0) == SaveUtil.BEEF)
|
||||
Array.Resize(ref decryptedPS, SaveUtil.SIZE_G6ORAS); // set to ORAS size
|
||||
else if (BitConverter.ToUInt32(decryptedPS, SaveUtil.SIZE_G6XY - 0x1F0) == SaveUtil.BEEF)
|
||||
Array.Resize(ref decryptedPS, SaveUtil.SIZE_G6XY); // set to X/Y size
|
||||
else if (BitConverter.ToUInt32(decryptedPS, SaveUtil.SIZE_G7SM - 0x1F0) == SaveUtil.BEEF)
|
||||
Array.Resize(ref decryptedPS, SaveUtil.SIZE_G7SM); // set to S/M size
|
||||
else
|
||||
continue;
|
||||
|
||||
// Save file is now decrypted!
|
||||
// Trigger Loading of the decrypted save file.
|
||||
openSAV(SaveUtil.getVariantSAV(decryptedPS), path);
|
||||
return true;
|
||||
}
|
||||
// End file check loop, check the input path for xorpads too if it isn't the same as the EXE (quite common).
|
||||
xorpath = Path.GetDirectoryName(path); // try again in the next folder up
|
||||
// try again
|
||||
pads = Directory.GetFiles(WorkingDirectory);
|
||||
s = SaveUtil.getSAVfromXORpads(input, pads);
|
||||
}
|
||||
return false; // no xorpad compatible
|
||||
|
||||
if (s == null)
|
||||
return false; // failed
|
||||
|
||||
openSAV(s, s.FileName);
|
||||
return true;
|
||||
}
|
||||
private void openSAV(SaveFile sav, string path)
|
||||
{
|
||||
|
@ -943,6 +915,8 @@ namespace PKHeX.WinForms
|
|||
}
|
||||
|
||||
// clean fields
|
||||
bool WindowToggleRequired = SAV.Generation < 3 && sav.Generation >= 3; // version combobox refresh hack
|
||||
bool WindowTranslationRequired = false;
|
||||
PKM pk = preparePKM();
|
||||
populateFields(SAV.BlankPKM);
|
||||
SAV = sav;
|
||||
|
@ -987,8 +961,6 @@ namespace PKHeX.WinForms
|
|||
}
|
||||
setPKXBoxes(); // Reload all of the PKX Windows
|
||||
|
||||
bool WindowTranslationRequired = false;
|
||||
|
||||
// Hide content if not present in game.
|
||||
GB_SUBE.Visible = SAV.HasSUBE;
|
||||
PB_Locked.Visible = SAV.HasBattleBox && SAV.BattleBoxLocked;
|
||||
|
@ -1231,7 +1203,17 @@ namespace PKHeX.WinForms
|
|||
PKMConverter.updateConfig(SAV.SubRegion, SAV.Country, SAV.ConsoleRegion, SAV.OT, SAV.Gender, SAV.Language);
|
||||
|
||||
if (WindowTranslationRequired) // force update -- re-added controls may be untranslated
|
||||
{
|
||||
// Keep window title
|
||||
title = Text;
|
||||
WinFormsUtil.TranslateInterface(this, curlanguage);
|
||||
Text = title;
|
||||
}
|
||||
if (WindowToggleRequired) // Version combobox selectedvalue needs a little help, only updates once it is visible
|
||||
{
|
||||
tabMain.SelectedTab = Tab_Met; // parent tab of CB_GameOrigin
|
||||
tabMain.SelectedTab = Tab_Main; // first tab
|
||||
}
|
||||
|
||||
// No changes made yet
|
||||
UndoStack.Clear(); Menu_Undo.Enabled = false;
|
||||
|
@ -1413,11 +1395,11 @@ namespace PKHeX.WinForms
|
|||
CB_GameOrigin.DataSource = new BindingSource(GameInfo.VersionDataSource.Where(g => g.Value <= SAV.MaxGameID || SAV.Generation >= 3 && g.Value == 15).ToList(), null);
|
||||
|
||||
// Set the Move ComboBoxes too..
|
||||
var moves = (HaX ? GameInfo.HaXMoveDataSource : GameInfo.MoveDataSource).Where(m => m.Value <= SAV.MaxMoveID).ToList(); // Filter Z-Moves if appropriate
|
||||
GameInfo.MoveDataSource = (HaX ? GameInfo.HaXMoveDataSource : GameInfo.LegalMoveDataSource).Where(m => m.Value <= SAV.MaxMoveID).ToList(); // Filter Z-Moves if appropriate
|
||||
foreach (ComboBox cb in new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4, CB_RelearnMove1, CB_RelearnMove2, CB_RelearnMove3, CB_RelearnMove4 })
|
||||
{
|
||||
cb.DisplayMember = "Text"; cb.ValueMember = "Value";
|
||||
cb.DataSource = new BindingSource(moves, null);
|
||||
cb.DataSource = new BindingSource(GameInfo.MoveDataSource, null);
|
||||
}
|
||||
}
|
||||
private Action getFieldsfromPKM;
|
||||
|
@ -1960,8 +1942,12 @@ namespace PKHeX.WinForms
|
|||
return;
|
||||
|
||||
pkm = preparePKM();
|
||||
updateLegality();
|
||||
if (Legality.Valid)
|
||||
return;
|
||||
|
||||
var encounter = Legality.getSuggestedMetInfo();
|
||||
if (encounter == null || encounter.Location < 0)
|
||||
if (encounter == null || (pkm.Format >= 3 && encounter.Location < 0))
|
||||
{
|
||||
WinFormsUtil.Alert("Unable to provide a suggestion.");
|
||||
return;
|
||||
|
@ -1970,21 +1956,37 @@ namespace PKHeX.WinForms
|
|||
int level = encounter.Level;
|
||||
int location = encounter.Location;
|
||||
int minlvl = Legal.getLowestLevel(pkm, encounter.Species);
|
||||
|
||||
if (pkm.Met_Level == level && pkm.Met_Location == location && pkm.CurrentLevel >= minlvl)
|
||||
if (minlvl == 0)
|
||||
minlvl = level;
|
||||
|
||||
if (pkm.CurrentLevel >= minlvl && pkm.Met_Level == level && pkm.Met_Location == location)
|
||||
return;
|
||||
if (minlvl < level)
|
||||
minlvl = level;
|
||||
|
||||
var met_list = GameInfo.getLocationList((GameVersion)pkm.Version, SAV.Generation, egg: false);
|
||||
var locstr = met_list.FirstOrDefault(loc => loc.Value == location)?.Text;
|
||||
string suggestion = $"Suggested:\nMet Location: {locstr}\nMet Level: {level}";
|
||||
var suggestion = new List<string> {"Suggested:"};
|
||||
if (pkm.Format >= 3)
|
||||
{
|
||||
var met_list = GameInfo.getLocationList((GameVersion)pkm.Version, SAV.Generation, egg: false);
|
||||
var locstr = met_list.FirstOrDefault(loc => loc.Value == location)?.Text;
|
||||
suggestion.Add($"Met Location: {locstr}");
|
||||
suggestion.Add($"Met Level: {level}");
|
||||
}
|
||||
if (pkm.CurrentLevel < minlvl)
|
||||
suggestion += $"\nCurrent Level {minlvl}";
|
||||
suggestion.Add($"Current Level: {minlvl}");
|
||||
|
||||
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, suggestion) != DialogResult.Yes)
|
||||
if (suggestion.Count == 1) // no suggestion
|
||||
return;
|
||||
|
||||
TB_MetLevel.Text = level.ToString();
|
||||
CB_MetLocation.SelectedValue = location;
|
||||
string suggest = string.Join(Environment.NewLine, suggestion);
|
||||
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, suggest) != DialogResult.Yes)
|
||||
return;
|
||||
|
||||
if (pkm.Format >= 3)
|
||||
{
|
||||
TB_MetLevel.Text = level.ToString();
|
||||
CB_MetLocation.SelectedValue = location;
|
||||
}
|
||||
|
||||
if (pkm.CurrentLevel < minlvl)
|
||||
TB_Level.Text = minlvl.ToString();
|
||||
|
@ -2290,7 +2292,10 @@ namespace PKHeX.WinForms
|
|||
}
|
||||
}
|
||||
else if (PKX.getGender(CB_Form.Text) < 2)
|
||||
Label_Gender.Text = CB_Form.Text;
|
||||
{
|
||||
if (CB_Form.Items.Count == 2) // actually M/F; Pumpkaboo formes in German are S,M,L,XL
|
||||
Label_Gender.Text = gendersymbols[PKX.getGender(CB_Form.Text)];
|
||||
}
|
||||
|
||||
if (changingFields)
|
||||
return;
|
||||
|
@ -2562,7 +2567,7 @@ namespace PKHeX.WinForms
|
|||
species = 0; // get the egg name.
|
||||
|
||||
// If name is that of another language, don't replace the nickname
|
||||
if (species != 0 && !PKX.getIsNicknamedAnyLanguage(species, TB_Nickname.Text, SAV.Generation))
|
||||
if (sender != CB_Language && species != 0 && !PKX.getIsNicknamedAnyLanguage(species, TB_Nickname.Text, SAV.Generation))
|
||||
return;
|
||||
|
||||
TB_Nickname.Text = PKX.getSpeciesNameGeneration(species, lang, SAV.Generation);
|
||||
|
@ -2867,7 +2872,9 @@ namespace PKHeX.WinForms
|
|||
LegalityAnalysis la = new LegalityAnalysis(pk);
|
||||
if (!la.Parsed)
|
||||
{
|
||||
WinFormsUtil.Alert($"Checking legality of PK{pk.Format} files that originated from Gen{pk.GenNumber} is not supported.");
|
||||
WinFormsUtil.Alert(pk.Format < 3
|
||||
? $"Checking legality of PK{pk.Format} files is not supported."
|
||||
: $"Checking legality of PK{pk.Format} files that originated from Gen{pk.GenNumber} is not supported.");
|
||||
return;
|
||||
}
|
||||
if (tabs)
|
||||
|
@ -2876,53 +2883,48 @@ namespace PKHeX.WinForms
|
|||
}
|
||||
private void updateLegality(LegalityAnalysis la = null, bool skipMoveRepop = false)
|
||||
{
|
||||
if (pkm.GenNumber >= 6)
|
||||
if (!fieldsLoaded)
|
||||
return;
|
||||
|
||||
Legality = la ?? new LegalityAnalysis(pkm);
|
||||
if (!Legality.Parsed || HaX)
|
||||
{
|
||||
if (!fieldsLoaded)
|
||||
return;
|
||||
Legality = la ?? new LegalityAnalysis(pkm);
|
||||
if (!Legality.Parsed || HaX)
|
||||
{
|
||||
PB_Legal.Visible = false;
|
||||
return;
|
||||
}
|
||||
PB_Legal.Visible = true;
|
||||
|
||||
PB_Legal.Image = Legality.Valid ? Resources.valid : Resources.warn;
|
||||
|
||||
// Refresh Move Legality
|
||||
for (int i = 0; i < 4; i++)
|
||||
movePB[i].Visible = !Legality.vMoves[i].Valid && !HaX;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
relearnPB[i].Visible = !Legality.vRelearn[i].Valid && !HaX;
|
||||
|
||||
if (skipMoveRepop)
|
||||
return;
|
||||
// Resort moves
|
||||
bool tmp = fieldsLoaded;
|
||||
fieldsLoaded = false;
|
||||
var cb = new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4 };
|
||||
var moves = Legality.AllSuggestedMovesAndRelearn;
|
||||
var moveList = GameInfo.MoveDataSource.OrderByDescending(m => moves.Contains(m.Value)).ToList();
|
||||
foreach (ComboBox c in cb)
|
||||
{
|
||||
var index = WinFormsUtil.getIndex(c);
|
||||
c.DataSource = new BindingSource(moveList, null);
|
||||
c.SelectedValue = index;
|
||||
}
|
||||
fieldsLoaded |= tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
PB_Legal.Visible = PB_WarnMove1.Visible = PB_WarnMove2.Visible = PB_WarnMove3.Visible = PB_WarnMove4.Visible =
|
||||
PB_Legal.Visible =
|
||||
PB_WarnMove1.Visible = PB_WarnMove2.Visible = PB_WarnMove3.Visible = PB_WarnMove4.Visible =
|
||||
PB_WarnRelearn1.Visible = PB_WarnRelearn2.Visible = PB_WarnRelearn3.Visible = PB_WarnRelearn4.Visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
PB_Legal.Visible = true;
|
||||
PB_Legal.Image = Legality.Valid ? Resources.valid : Resources.warn;
|
||||
|
||||
// Refresh Move Legality
|
||||
for (int i = 0; i < 4; i++)
|
||||
movePB[i].Visible = !Legality.vMoves[i].Valid && !HaX;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
relearnPB[i].Visible = !Legality.vRelearn[i].Valid && !HaX && pkm.Format >= 6;
|
||||
|
||||
if (skipMoveRepop)
|
||||
return;
|
||||
// Resort moves
|
||||
bool tmp = fieldsLoaded;
|
||||
fieldsLoaded = false;
|
||||
var cb = new[] {CB_Move1, CB_Move2, CB_Move3, CB_Move4};
|
||||
var moves = Legality.AllSuggestedMovesAndRelearn;
|
||||
var moveList = GameInfo.MoveDataSource.OrderByDescending(m => moves.Contains(m.Value)).ToList();
|
||||
foreach (ComboBox c in cb)
|
||||
{
|
||||
var index = WinFormsUtil.getIndex(c);
|
||||
c.DataSource = new BindingSource(moveList, null);
|
||||
c.SelectedValue = index;
|
||||
}
|
||||
fieldsLoaded |= tmp;
|
||||
}
|
||||
|
||||
private void updateGender()
|
||||
{
|
||||
int cg = Array.IndexOf(gendersymbols, Label_Gender.Text);
|
||||
int cg = PKX.getGender(Label_Gender.Text);
|
||||
int gt = SAV.Personal.getFormeEntry(WinFormsUtil.getIndex(CB_Species), CB_Form.SelectedIndex).Gender;
|
||||
|
||||
int Gender;
|
||||
|
@ -3848,6 +3850,7 @@ namespace PKHeX.WinForms
|
|||
bool? noSetb = getPKMSetOverride();
|
||||
|
||||
SAV.loadBoxes(path, out result, CB_BoxSelect.SelectedIndex, clearAll, noSetb);
|
||||
setPKXBoxes();
|
||||
WinFormsUtil.Alert(result);
|
||||
}
|
||||
private void B_SaveBoxBin_Click(object sender, EventArgs e)
|
||||
|
@ -4121,7 +4124,12 @@ namespace PKHeX.WinForms
|
|||
pb.BackgroundImage = null;
|
||||
|
||||
if (DragInfo.SameBox && DragInfo.DestinationValid)
|
||||
SlotPictureBoxes[DragInfo.slotDestinationSlotNumber].Image = img;
|
||||
{
|
||||
if (SAV.getIsTeamSet(box, DragInfo.slotDestinationSlotNumber) ^ SAV.getIsTeamSet(box, DragInfo.slotSourceSlotNumber))
|
||||
getQuickFiller(SlotPictureBoxes[DragInfo.slotDestinationSlotNumber], SAV.getStoredSlot(DragInfo.slotDestinationOffset));
|
||||
else
|
||||
SlotPictureBoxes[DragInfo.slotDestinationSlotNumber].Image = img;
|
||||
}
|
||||
|
||||
if (result == DragDropEffects.Copy) // viewed in tabs, apply 'view' highlight
|
||||
getSlotColor(DragInfo.slotSourceSlotNumber, Resources.slotView);
|
||||
|
|
|
@ -29,16 +29,33 @@ namespace PKHeX.WinForms
|
|||
|
||||
try
|
||||
{
|
||||
if (GetFrameworkVersion() >= 393295)
|
||||
if (IsOnWindows())
|
||||
{
|
||||
StartPKHeX();
|
||||
if (GetFrameworkVersion() >= 393295)
|
||||
{
|
||||
StartPKHeX();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Todo: make this translatable
|
||||
MessageBox.Show(".NET Framework 4.6 needs to be installed for this version of PKHeX to run.", "PKHeX Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
|
||||
Process.Start(@"https://www.microsoft.com/download/details.aspx?id=48130");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Todo: make this translatable
|
||||
MessageBox.Show(".NET Framework 4.6 needs to be installed for this version of PKHeX to run.", "PKHeX Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
|
||||
Process.Start(@"https://www.microsoft.com/download/details.aspx?id=48130");
|
||||
//CLR Version 4.0.30319.42000 is equivalent to .NET Framework version 4.6
|
||||
if ((Environment.Version.CompareTo(Version.Parse("4.0.30319.42000"))) >= 0)
|
||||
{
|
||||
StartPKHeX();
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Your version of Mono needs to target the .NET Framework 4.6 or higher for this version of PKHeX to run.",
|
||||
"PKHeX Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
|
@ -49,11 +66,9 @@ namespace PKHeX.WinForms
|
|||
MessageBox.Show("Could not locate PKHeX.Core.dll. Make sure you're running PKHeX together with its code library. Usually caused when all files are not extracted.", "PKHeX Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Exception came from Main
|
||||
throw;
|
||||
}
|
||||
|
||||
// Exception came from Main
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +80,16 @@ namespace PKHeX.WinForms
|
|||
Application.Run(new Main());
|
||||
}
|
||||
|
||||
public static bool IsOnWindows()
|
||||
{
|
||||
// 4 -> UNIX, 6 -> Mac OSX, 128 -> UNIX (old)
|
||||
int p = (int)Environment.OSVersion.Platform;
|
||||
if ((p == 4) || (p == 6) || (p == 128))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static int GetFrameworkVersion()
|
||||
{
|
||||
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
|
||||
|
|
|
@ -32,17 +32,17 @@ namespace PKHeX.WinForms
|
|||
{
|
||||
var p = new string[types.Length][];
|
||||
for (int i = 0; i < p.Length; i++)
|
||||
p[i] = ReflectUtil.getPropertiesCanWritePublic(types[i]).ToArray();
|
||||
p[i] = ReflectUtil.getPropertiesCanWritePublic(types[i]).Concat(CustomProperties).OrderBy(a => a).ToArray();
|
||||
|
||||
IEnumerable<string> all = p.SelectMany(prop => prop).Distinct();
|
||||
IEnumerable<string> any = p[0];
|
||||
for (int i = 1; i < p.Length; i++)
|
||||
any = any.Union(p[i]);
|
||||
// Properties for any PKM
|
||||
var any = p.SelectMany(prop => prop).Distinct().ToArray();
|
||||
// Properties shared by all PKM
|
||||
var all = p.Skip(1).Aggregate(new HashSet<string>(p.First()), (h, e) => { h.IntersectWith(e); return h; }).ToArray();
|
||||
|
||||
var p1 = new string[types.Length + 2][];
|
||||
Array.Copy(p, 0, p1, 1, p.Length);
|
||||
p1[0] = all.ToArray();
|
||||
p1[p1.Length-1] = any.ToArray();
|
||||
p1[0] = all;
|
||||
p1[p1.Length - 1] = any;
|
||||
|
||||
return p1;
|
||||
}
|
||||
|
@ -50,6 +50,11 @@ namespace PKHeX.WinForms
|
|||
private readonly PKM pkmref;
|
||||
private const string CONST_RAND = "$rand";
|
||||
private const string CONST_SHINY = "$shiny";
|
||||
private const string CONST_SUGGEST = "$suggest";
|
||||
|
||||
private const string PROP_LEGAL = "Legal";
|
||||
private static readonly string[] CustomProperties = {PROP_LEGAL};
|
||||
|
||||
private int currentFormat = -1;
|
||||
private static readonly Type[] types = {typeof (PK7), typeof (PK6), typeof (PK5), typeof (PK4), typeof (PK3)};
|
||||
private static readonly string[][] properties = getPropArray();
|
||||
|
@ -80,15 +85,61 @@ namespace PKHeX.WinForms
|
|||
|
||||
runBackgroundWorker();
|
||||
}
|
||||
private void B_Add_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (CB_Property.SelectedIndex < 0)
|
||||
{ WinFormsUtil.Alert("Invalid property selected."); return; }
|
||||
|
||||
char[] prefix = { '.', '=', '!' };
|
||||
string s = prefix[CB_Require.SelectedIndex] + CB_Property.Items[CB_Property.SelectedIndex].ToString() + "=";
|
||||
if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines.Last().Length > 0)
|
||||
s = Environment.NewLine + s;
|
||||
|
||||
RTB_Instructions.AppendText(s);
|
||||
}
|
||||
private void CB_Format_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (currentFormat == CB_Format.SelectedIndex)
|
||||
return;
|
||||
|
||||
int format = CB_Format.SelectedIndex;
|
||||
CB_Property.Items.Clear();
|
||||
CB_Property.Items.AddRange(properties[format]);
|
||||
CB_Property.SelectedIndex = 0;
|
||||
currentFormat = format;
|
||||
}
|
||||
private void CB_Property_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
L_PropType.Text = getPropertyType(CB_Property.Text);
|
||||
L_PropValue.Text = pkmref.GetType().HasProperty(CB_Property.Text)
|
||||
? ReflectUtil.GetValue(pkmref, CB_Property.Text).ToString()
|
||||
: "";
|
||||
}
|
||||
private void tabMain_DragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
}
|
||||
private void tabMain_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
if (!Directory.Exists(files[0]))
|
||||
return;
|
||||
|
||||
TB_Folder.Text = files[0];
|
||||
TB_Folder.Visible = true;
|
||||
RB_SAV.Checked = false;
|
||||
RB_Path.Checked = true;
|
||||
}
|
||||
|
||||
private BackgroundWorker b = new BackgroundWorker { WorkerReportsProgress = true };
|
||||
private void runBackgroundWorker()
|
||||
{
|
||||
var Filters = getFilters().ToList();
|
||||
var Filters = StringInstruction.getFilters(RTB_Instructions.Lines).ToArray();
|
||||
if (Filters.Any(z => string.IsNullOrWhiteSpace(z.PropertyValue)))
|
||||
{ WinFormsUtil.Error("Empty Filter Value detected."); return; }
|
||||
|
||||
var Instructions = getInstructions().ToList();
|
||||
var Instructions = StringInstruction.getInstructions(RTB_Instructions.Lines).ToArray();
|
||||
var emptyVal = Instructions.Where(z => string.IsNullOrWhiteSpace(z.PropertyValue)).ToArray();
|
||||
if (emptyVal.Any())
|
||||
{
|
||||
|
@ -99,6 +150,9 @@ namespace PKHeX.WinForms
|
|||
return;
|
||||
}
|
||||
|
||||
if (!Instructions.Any())
|
||||
{ WinFormsUtil.Error("No instructions defined."); return; }
|
||||
|
||||
string destPath = "";
|
||||
if (RB_Path.Checked)
|
||||
{
|
||||
|
@ -118,11 +172,14 @@ namespace PKHeX.WinForms
|
|||
screenStrings(Instructions);
|
||||
|
||||
b.DoWork += (sender, e) => {
|
||||
|
||||
len = err = ctr = 0;
|
||||
if (RB_SAV.Checked)
|
||||
{
|
||||
var data = Main.SAV.BoxData;
|
||||
setupProgressBar(data.Length);
|
||||
processSAV(data, Filters, Instructions);
|
||||
Main.SAV.BoxData = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -164,100 +221,135 @@ namespace PKHeX.WinForms
|
|||
|
||||
// Mass Editing
|
||||
private int ctr, len, err;
|
||||
private IEnumerable<StringInstruction> getFilters()
|
||||
private void processSAV(PKM[] data, StringInstruction[] Filters, StringInstruction[] Instructions)
|
||||
{
|
||||
var raw =
|
||||
RTB_Instructions.Lines
|
||||
.Where(line => !string.IsNullOrWhiteSpace(line))
|
||||
.Where(line => new[] {'!','='}.Contains(line[0]));
|
||||
|
||||
return from line in raw
|
||||
let eval = line[0] == '='
|
||||
let split = line.Substring(1).Split('=')
|
||||
where split.Length == 2 && !string.IsNullOrWhiteSpace(split[0])
|
||||
select new StringInstruction {PropertyName = split[0], PropertyValue = split[1], Evaluator = eval};
|
||||
}
|
||||
private IEnumerable<StringInstruction> getInstructions()
|
||||
{
|
||||
var raw =
|
||||
RTB_Instructions.Lines
|
||||
.Where(line => !string.IsNullOrEmpty(line))
|
||||
.Where(line => new[] {'.'}.Contains(line[0]))
|
||||
.Select(line => line.Substring(1));
|
||||
|
||||
return from line in raw
|
||||
select line.Split('=') into split
|
||||
where split.Length == 2
|
||||
select new StringInstruction { PropertyName = split[0], PropertyValue = split[1] };
|
||||
}
|
||||
private void processSAV(PKM[] data, List<StringInstruction> Filters, List<StringInstruction> Instructions)
|
||||
{
|
||||
len = err = ctr = 0;
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var pkm = data[i];
|
||||
if (!pkm.Valid || pkm.Locked)
|
||||
{
|
||||
b.ReportProgress(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
ModifyResult r = ProcessPKM(pkm, Filters, Instructions);
|
||||
if (r != ModifyResult.Invalid)
|
||||
len++;
|
||||
if (r == ModifyResult.Error)
|
||||
err++;
|
||||
if (r == ModifyResult.Modified)
|
||||
{
|
||||
if (pkm.Species != 0)
|
||||
pkm.RefreshChecksum();
|
||||
ctr++;
|
||||
}
|
||||
|
||||
processPKM(data[i], Filters, Instructions);
|
||||
b.ReportProgress(i);
|
||||
}
|
||||
|
||||
Main.SAV.BoxData = data;
|
||||
}
|
||||
private void processFolder(string[] files, List<StringInstruction> Filters, List<StringInstruction> Instructions, string destPath)
|
||||
private void processFolder(string[] files, StringInstruction[] Filters, StringInstruction[] Instructions, string destPath)
|
||||
{
|
||||
len = err = ctr = 0;
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
string file = files[i];
|
||||
if (!PKX.getIsPKM(new FileInfo(file).Length))
|
||||
var fi = new FileInfo(file);
|
||||
if (!PKX.getIsPKM(fi.Length))
|
||||
{
|
||||
b.ReportProgress(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
int format = fi.Extension.Length > 0 ? (fi.Extension.Last() - 0x30) & 7 : Main.SAV.Generation;
|
||||
byte[] data = File.ReadAllBytes(file);
|
||||
var pkm = PKMConverter.getPKMfromBytes(data, prefer: Main.SAV.Generation);
|
||||
|
||||
if (!pkm.Valid)
|
||||
{
|
||||
b.ReportProgress(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
ModifyResult r = ProcessPKM(pkm, Filters, Instructions);
|
||||
if (r != ModifyResult.Invalid)
|
||||
len++;
|
||||
if (r == ModifyResult.Error)
|
||||
err++;
|
||||
if (r == ModifyResult.Modified)
|
||||
{
|
||||
if (pkm.Species > 0)
|
||||
{
|
||||
pkm.RefreshChecksum();
|
||||
File.WriteAllBytes(Path.Combine(destPath, Path.GetFileName(file)), pkm.DecryptedBoxData);
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
var pkm = PKMConverter.getPKMfromBytes(data, prefer: format);
|
||||
if (processPKM(pkm, Filters, Instructions))
|
||||
File.WriteAllBytes(Path.Combine(destPath, Path.GetFileName(file)), pkm.DecryptedBoxData);
|
||||
|
||||
b.ReportProgress(i);
|
||||
}
|
||||
}
|
||||
private bool processPKM(PKM pkm, IEnumerable<StringInstruction> Filters, IEnumerable<StringInstruction> Instructions)
|
||||
{
|
||||
if (!pkm.Valid || pkm.Locked)
|
||||
return false;
|
||||
|
||||
ModifyResult r = tryModifyPKM(pkm, Filters, Instructions);
|
||||
if (r != ModifyResult.Invalid)
|
||||
len++;
|
||||
if (r == ModifyResult.Error)
|
||||
err++;
|
||||
if (r != ModifyResult.Modified)
|
||||
return false;
|
||||
if (pkm.Species <= 0)
|
||||
return false;
|
||||
|
||||
pkm.RefreshChecksum();
|
||||
ctr++;
|
||||
return true;
|
||||
}
|
||||
|
||||
private string getPropertyType(string propertyName)
|
||||
{
|
||||
if (CustomProperties.Contains(propertyName))
|
||||
return "Custom";
|
||||
|
||||
int typeIndex = CB_Format.SelectedIndex;
|
||||
|
||||
if (typeIndex == 0) // All
|
||||
return types[0].GetProperty(propertyName).PropertyType.Name;
|
||||
|
||||
if (typeIndex == properties.Length - 1) // Any
|
||||
foreach (var p in types.Select(t => t.GetProperty(propertyName)).Where(p => p != null))
|
||||
return p.PropertyType.Name;
|
||||
|
||||
return types[typeIndex - 1].GetProperty(propertyName).PropertyType.Name;
|
||||
}
|
||||
|
||||
// Utility Methods
|
||||
private enum ModifyResult
|
||||
{
|
||||
Invalid,
|
||||
Error,
|
||||
Filtered,
|
||||
Modified,
|
||||
}
|
||||
public class StringInstruction
|
||||
{
|
||||
public string PropertyName;
|
||||
public string PropertyValue;
|
||||
public bool Evaluator;
|
||||
public void setScreenedValue(string[] arr)
|
||||
{
|
||||
int index = Array.IndexOf(arr, PropertyValue);
|
||||
PropertyValue = index > -1 ? index.ToString() : PropertyValue;
|
||||
}
|
||||
|
||||
// Extra Functionality
|
||||
public bool Random;
|
||||
public int Min, Max;
|
||||
public int RandomValue => Util.rand.Next(Min, Max + 1);
|
||||
|
||||
public static IEnumerable<StringInstruction> getFilters(IEnumerable<string> lines)
|
||||
{
|
||||
var raw = lines
|
||||
.Where(line => !string.IsNullOrWhiteSpace(line))
|
||||
.Where(line => new[] { '!', '=' }.Contains(line[0]));
|
||||
|
||||
return from line in raw
|
||||
let eval = line[0] == '='
|
||||
let split = line.Substring(1).Split('=')
|
||||
where split.Length == 2 && !string.IsNullOrWhiteSpace(split[0])
|
||||
select new StringInstruction { PropertyName = split[0], PropertyValue = split[1], Evaluator = eval };
|
||||
}
|
||||
public static IEnumerable<StringInstruction> getInstructions(IEnumerable<string> lines)
|
||||
{
|
||||
var raw = lines
|
||||
.Where(line => !string.IsNullOrEmpty(line))
|
||||
.Where(line => new[] { '.' }.Contains(line[0]))
|
||||
.Select(line => line.Substring(1));
|
||||
|
||||
return from line in raw
|
||||
select line.Split('=') into split
|
||||
where split.Length == 2
|
||||
select new StringInstruction { PropertyName = split[0], PropertyValue = split[1] };
|
||||
}
|
||||
}
|
||||
private class PKMInfo
|
||||
{
|
||||
private readonly PKM pkm;
|
||||
public PKMInfo(PKM pk) { pkm = pk; }
|
||||
|
||||
private LegalityAnalysis la;
|
||||
private LegalityAnalysis Legality => la ?? (la = new LegalityAnalysis(pkm));
|
||||
|
||||
public bool Legal => Legality.Valid;
|
||||
public int[] SuggestedRelearn => Legality.getSuggestedRelearn();
|
||||
public int[] SuggestedMoves => Legality.getSuggestedMoves(tm: true, tutor: true, reminder: false);
|
||||
public EncounterStatic SuggestedEncounter => Legality.getSuggestedMetInfo();
|
||||
}
|
||||
|
||||
public static void screenStrings(IEnumerable<StringInstruction> il)
|
||||
{
|
||||
foreach (var i in il.Where(i => !i.PropertyValue.All(char.IsDigit)))
|
||||
|
@ -298,77 +390,27 @@ namespace PKHeX.WinForms
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tabMain_DragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
|
||||
}
|
||||
private void tabMain_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
if (!Directory.Exists(files[0])) return;
|
||||
|
||||
TB_Folder.Text = files[0];
|
||||
TB_Folder.Visible = true;
|
||||
RB_SAV.Checked = false;
|
||||
RB_Path.Checked = true;
|
||||
}
|
||||
private void CB_Property_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
L_PropType.Text = getPropertyType(CB_Property.Text);
|
||||
L_PropValue.Text = pkmref.GetType().HasProperty(CB_Property.Text)
|
||||
? ReflectUtil.GetValue(pkmref, CB_Property.Text).ToString()
|
||||
: "";
|
||||
}
|
||||
private string getPropertyType(string propertyName)
|
||||
{
|
||||
int typeIndex = CB_Format.SelectedIndex;
|
||||
|
||||
if (typeIndex == 0) // All
|
||||
return types[0].GetProperty(propertyName).PropertyType.Name;
|
||||
|
||||
if (typeIndex == properties.Length - 1) // Any
|
||||
foreach (var p in types.Select(t => t.GetProperty(propertyName)).Where(p => p != null))
|
||||
return p.PropertyType.Name;
|
||||
|
||||
return types[typeIndex - 1].GetProperty(propertyName).PropertyType.Name;
|
||||
}
|
||||
|
||||
// Utility Methods
|
||||
public class StringInstruction
|
||||
{
|
||||
public string PropertyName;
|
||||
public string PropertyValue;
|
||||
public bool Evaluator;
|
||||
public void setScreenedValue(string[] arr)
|
||||
{
|
||||
int index = Array.IndexOf(arr, PropertyValue);
|
||||
PropertyValue = index > -1 ? index.ToString() : PropertyValue;
|
||||
}
|
||||
|
||||
// Extra Functionality
|
||||
public bool Random;
|
||||
public int Min, Max;
|
||||
public int RandomValue => Util.rand.Next(Min, Max + 1);
|
||||
}
|
||||
private enum ModifyResult
|
||||
{
|
||||
Invalid,
|
||||
Error,
|
||||
Filtered,
|
||||
Modified,
|
||||
}
|
||||
private static ModifyResult ProcessPKM(PKM PKM, IEnumerable<StringInstruction> Filters, IEnumerable<StringInstruction> Instructions)
|
||||
private static ModifyResult tryModifyPKM(PKM PKM, IEnumerable<StringInstruction> Filters, IEnumerable<StringInstruction> Instructions)
|
||||
{
|
||||
if (!PKM.ChecksumValid || PKM.Species == 0)
|
||||
return ModifyResult.Invalid;
|
||||
|
||||
Type pkm = PKM.GetType();
|
||||
PKMInfo info = new PKMInfo(PKM);
|
||||
|
||||
foreach (var cmd in Filters)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (cmd.PropertyName == PROP_LEGAL)
|
||||
{
|
||||
bool legal;
|
||||
if (!bool.TryParse(cmd.PropertyValue, out legal))
|
||||
return ModifyResult.Error;
|
||||
if (legal == info.Legal == cmd.Evaluator)
|
||||
continue;
|
||||
return ModifyResult.Filtered;
|
||||
}
|
||||
if (!pkm.HasProperty(cmd.PropertyName))
|
||||
return ModifyResult.Filtered;
|
||||
if (ReflectUtil.GetValueEquals(PKM, cmd.PropertyName, cmd.PropertyValue) != cmd.Evaluator)
|
||||
|
@ -386,76 +428,100 @@ namespace PKHeX.WinForms
|
|||
{
|
||||
try
|
||||
{
|
||||
if (cmd.PropertyName == nameof(PKM.MetDate))
|
||||
PKM.MetDate = DateTime.ParseExact(cmd.PropertyValue, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None);
|
||||
else if (cmd.PropertyName == nameof(PKM.EggMetDate))
|
||||
PKM.EggMetDate = DateTime.ParseExact(cmd.PropertyValue, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None);
|
||||
else if (cmd.PropertyName == nameof(PKM.EncryptionConstant) && cmd.PropertyValue == CONST_RAND)
|
||||
ReflectUtil.SetValue(PKM, cmd.PropertyName, Util.rnd32().ToString());
|
||||
else if ((cmd.PropertyName == nameof(PKM.Ability) || cmd.PropertyName == nameof(PKM.AbilityNumber)) && cmd.PropertyValue.StartsWith("$"))
|
||||
PKM.RefreshAbility(Convert.ToInt16(cmd.PropertyValue[1]) - 0x30);
|
||||
else if(cmd.PropertyName == nameof(PKM.PID) && cmd.PropertyValue == CONST_RAND)
|
||||
PKM.setPIDGender(PKM.Gender);
|
||||
else if (cmd.PropertyName == nameof(PKM.EncryptionConstant) && cmd.PropertyValue == nameof(PKM.PID))
|
||||
PKM.EncryptionConstant = PKM.PID;
|
||||
else if (cmd.PropertyName == nameof(PKM.PID) && cmd.PropertyValue == CONST_SHINY)
|
||||
PKM.setShinyPID();
|
||||
else if (cmd.PropertyName == nameof(PKM.Species) && cmd.PropertyValue == "0")
|
||||
PKM.Data = new byte[PKM.Data.Length];
|
||||
else if (cmd.PropertyName.StartsWith("IV") && cmd.PropertyValue == CONST_RAND)
|
||||
setRandomIVs(PKM, cmd);
|
||||
else if (cmd.Random)
|
||||
ReflectUtil.SetValue(PKM, cmd.PropertyName, cmd.RandomValue);
|
||||
if (cmd.PropertyValue == CONST_SUGGEST)
|
||||
{
|
||||
result = setSuggestedProperty(PKM, cmd, info)
|
||||
? ModifyResult.Modified
|
||||
: ModifyResult.Error;
|
||||
}
|
||||
else
|
||||
ReflectUtil.SetValue(PKM, cmd.PropertyName, cmd.PropertyValue);
|
||||
|
||||
result = ModifyResult.Modified;
|
||||
{
|
||||
setProperty(PKM, cmd);
|
||||
result = ModifyResult.Modified;
|
||||
}
|
||||
}
|
||||
catch { Console.WriteLine($"Unable to set {cmd.PropertyName} to {cmd.PropertyValue}."); }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private static bool setSuggestedProperty(PKM PKM, StringInstruction cmd, PKMInfo info)
|
||||
{
|
||||
switch (cmd.PropertyName)
|
||||
{
|
||||
case nameof(PKM.RelearnMoves):
|
||||
PKM.RelearnMoves = info.SuggestedRelearn;
|
||||
return true;
|
||||
case nameof(PKM.Met_Location):
|
||||
var encounter = info.SuggestedEncounter;
|
||||
if (encounter == null)
|
||||
return false;
|
||||
|
||||
int level = encounter.Level;
|
||||
int location = encounter.Location;
|
||||
int minlvl = Legal.getLowestLevel(PKM, encounter.Species);
|
||||
|
||||
PKM.Met_Level = level;
|
||||
PKM.Met_Location = location;
|
||||
PKM.CurrentLevel = Math.Max(minlvl, level);
|
||||
|
||||
return true;
|
||||
|
||||
case nameof(PKM.Moves):
|
||||
var moves = info.SuggestedMoves;
|
||||
Util.Shuffle(moves);
|
||||
Array.Resize(ref moves, 4);
|
||||
PKM.Moves = moves;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private static void setProperty(PKM PKM, StringInstruction cmd)
|
||||
{
|
||||
if (cmd.PropertyName == nameof(PKM.MetDate))
|
||||
PKM.MetDate = DateTime.ParseExact(cmd.PropertyValue, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None);
|
||||
else if (cmd.PropertyName == nameof(PKM.EggMetDate))
|
||||
PKM.EggMetDate = DateTime.ParseExact(cmd.PropertyValue, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None);
|
||||
else if (cmd.PropertyName == nameof(PKM.EncryptionConstant) && cmd.PropertyValue == CONST_RAND)
|
||||
ReflectUtil.SetValue(PKM, cmd.PropertyName, Util.rnd32().ToString());
|
||||
else if ((cmd.PropertyName == nameof(PKM.Ability) || cmd.PropertyName == nameof(PKM.AbilityNumber)) && cmd.PropertyValue.StartsWith("$"))
|
||||
PKM.RefreshAbility(Convert.ToInt16(cmd.PropertyValue[1]) - 0x30);
|
||||
else if (cmd.PropertyName == nameof(PKM.PID) && cmd.PropertyValue == CONST_RAND)
|
||||
PKM.setPIDGender(PKM.Gender);
|
||||
else if (cmd.PropertyName == nameof(PKM.EncryptionConstant) && cmd.PropertyValue == nameof(PKM.PID))
|
||||
PKM.EncryptionConstant = PKM.PID;
|
||||
else if (cmd.PropertyName == nameof(PKM.PID) && cmd.PropertyValue == CONST_SHINY)
|
||||
PKM.setShinyPID();
|
||||
else if (cmd.PropertyName == nameof(PKM.Species) && cmd.PropertyValue == "0")
|
||||
PKM.Data = new byte[PKM.Data.Length];
|
||||
else if (cmd.PropertyName.StartsWith("IV") && cmd.PropertyValue == CONST_RAND)
|
||||
setRandomIVs(PKM, cmd);
|
||||
else if (cmd.Random)
|
||||
ReflectUtil.SetValue(PKM, cmd.PropertyName, cmd.RandomValue);
|
||||
else if (cmd.PropertyName == nameof(PKM.IsNicknamed) && cmd.PropertyValue.ToLower() == "false")
|
||||
{ PKM.IsNicknamed = false; PKM.Nickname = PKX.getSpeciesName(PKM.Species, PKM.Language); }
|
||||
else
|
||||
ReflectUtil.SetValue(PKM, cmd.PropertyName, cmd.PropertyValue);
|
||||
}
|
||||
private static void setRandomIVs(PKM PKM, StringInstruction cmd)
|
||||
{
|
||||
int MaxIV = PKM.Format <= 2 ? 15 : 31;
|
||||
if (cmd.PropertyName == "IVs")
|
||||
{
|
||||
bool IV3 = Legal.Legends.Contains(PKM.Species) || Legal.SubLegends.Contains(PKM.Species);
|
||||
int[] IVs = new int[6];
|
||||
do
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
IVs[i] = (int)(Util.rnd32() & MaxIV);
|
||||
} while (IV3 && IVs.Where(i => i == MaxIV).Count() < 3);
|
||||
ReflectUtil.SetValue(PKM, cmd.PropertyName, IVs);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
IVs[i] = (int)(Util.rnd32() & MaxIV);
|
||||
if (Legal.Legends.Contains(PKM.Species) || Legal.SubLegends.Contains(PKM.Species))
|
||||
for (int i = 0; i < 3; i++)
|
||||
IVs[i] = MaxIV;
|
||||
|
||||
Util.Shuffle(IVs);
|
||||
PKM.IVs = IVs;
|
||||
}
|
||||
else
|
||||
ReflectUtil.SetValue(PKM, cmd.PropertyName, Util.rnd32() & MaxIV);
|
||||
}
|
||||
|
||||
private void B_Add_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (CB_Property.SelectedIndex < 0)
|
||||
{ WinFormsUtil.Alert("Invalid property selected."); return; }
|
||||
|
||||
char[] prefix = {'.', '=', '!'};
|
||||
string s = prefix[CB_Require.SelectedIndex] + CB_Property.Items[CB_Property.SelectedIndex].ToString() + "=";
|
||||
if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines.Last().Length > 0)
|
||||
s = Environment.NewLine + s;
|
||||
|
||||
RTB_Instructions.AppendText(s);
|
||||
}
|
||||
|
||||
private void CB_Format_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (currentFormat == CB_Format.SelectedIndex)
|
||||
return;
|
||||
|
||||
int format = CB_Format.SelectedIndex;
|
||||
CB_Property.Items.Clear();
|
||||
CB_Property.Items.AddRange(properties[format]);
|
||||
CB_Property.SelectedIndex = 0;
|
||||
currentFormat = format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -488,17 +488,7 @@ namespace PKHeX.WinForms
|
|||
|
||||
if (RTB_Instructions.Lines.Any(line => line.Length > 0))
|
||||
{
|
||||
var raw =
|
||||
RTB_Instructions.Lines
|
||||
.Where(line => !string.IsNullOrWhiteSpace(line))
|
||||
.Where(line => new[] { '!', '=' }.Contains(line[0]));
|
||||
|
||||
var filters = (from line in raw
|
||||
let eval = line[0] == '='
|
||||
let split = line.Substring(1).Split('=')
|
||||
where split.Length == 2 && !string.IsNullOrWhiteSpace(split[0])
|
||||
select new BatchEditor.StringInstruction { PropertyName = split[0], PropertyValue = split[1], Evaluator = eval }).ToArray();
|
||||
|
||||
var filters = BatchEditor.StringInstruction.getFilters(RTB_Instructions.Lines).ToArray();
|
||||
BatchEditor.screenStrings(filters);
|
||||
res = res.Where(pkm => // Compare across all filters
|
||||
{
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace PKHeX.WinForms
|
|||
CB_Move1.DisplayMember = CB_Move2.DisplayMember = CB_Move3.DisplayMember = CB_Move4.DisplayMember = "Text";
|
||||
CB_Move1.ValueMember = CB_Move2.ValueMember = CB_Move3.ValueMember = CB_Move4.ValueMember = "Value";
|
||||
|
||||
var MoveList = GameInfo.MoveDataSource.Where(m => m.Value <= SAV.MaxMoveID).ToList();
|
||||
var MoveList = GameInfo.MoveDataSource;
|
||||
CB_Move1.DataSource = new BindingSource(MoveList, null);
|
||||
CB_Move2.DataSource = new BindingSource(MoveList, null);
|
||||
CB_Move3.DataSource = new BindingSource(MoveList, null);
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace PKHeX.WinForms
|
|||
CB_Move1.DisplayMember = CB_Move2.DisplayMember = CB_Move3.DisplayMember = CB_Move4.DisplayMember = "Text";
|
||||
CB_Move1.ValueMember = CB_Move2.ValueMember = CB_Move3.ValueMember = CB_Move4.ValueMember = "Value";
|
||||
|
||||
var MoveList = GameInfo.MoveDataSource.Where(m => m.Value <= SAV.MaxMoveID).ToList();
|
||||
var MoveList = GameInfo.MoveDataSource;
|
||||
CB_Move1.DataSource = new BindingSource(MoveList, null);
|
||||
CB_Move2.DataSource = new BindingSource(MoveList, null);
|
||||
CB_Move3.DataSource = new BindingSource(MoveList, null);
|
||||
|
|
|
@ -39,6 +39,9 @@ namespace PKHeX.WinForms
|
|||
pba = new [] { PB_Badge1, PB_Badge2, PB_Badge3, PB_Badge4, PB_Badge5, PB_Badge6, PB_Badge7, PB_Badge8, };
|
||||
|
||||
L_MultiplayerSprite.Enabled = CB_MultiplayerSprite.Enabled = Main.SAV.ORAS;
|
||||
L_MultiplayerSprite.Visible = CB_MultiplayerSprite.Visible = Main.SAV.ORAS;
|
||||
PB_Sprite.Visible = Main.SAV.ORAS;
|
||||
|
||||
L_Style.Visible = TB_Style.Visible = SAV.XY;
|
||||
if (!SAV.XY)
|
||||
TC_Editor.TabPages.Remove(Tab_Appearance);
|
||||
|
|
|
@ -104,6 +104,9 @@ namespace PKHeX.WinForms
|
|||
this.L_SinglesC = new System.Windows.Forms.Label();
|
||||
this.TC_Editor = new System.Windows.Forms.TabControl();
|
||||
this.Tab_Overview = new System.Windows.Forms.TabPage();
|
||||
this.B_GenTID = new System.Windows.Forms.Button();
|
||||
this.L_G7TID = new System.Windows.Forms.Label();
|
||||
this.MT_G7TID = new System.Windows.Forms.MaskedTextBox();
|
||||
this.GB_Stats = new System.Windows.Forms.GroupBox();
|
||||
this.NUD_Stat = new System.Windows.Forms.NumericUpDown();
|
||||
this.NUD_FC = new System.Windows.Forms.NumericUpDown();
|
||||
|
@ -171,9 +174,8 @@ namespace PKHeX.WinForms
|
|||
this.NUD_ThumbsTotal = new System.Windows.Forms.NumericUpDown();
|
||||
this.L_ThumbsTotal = new System.Windows.Forms.Label();
|
||||
this.B_Fashion = new System.Windows.Forms.Button();
|
||||
this.L_G7TID = new System.Windows.Forms.Label();
|
||||
this.MT_G7TID = new System.Windows.Forms.MaskedTextBox();
|
||||
this.B_GenTID = new System.Windows.Forms.Button();
|
||||
this.TB_PlazaName = new System.Windows.Forms.TextBox();
|
||||
this.L_PlazaName = new System.Windows.Forms.Label();
|
||||
this.TC_Editor.SuspendLayout();
|
||||
this.Tab_Overview.SuspendLayout();
|
||||
this.GB_Stats.SuspendLayout();
|
||||
|
@ -847,6 +849,35 @@ namespace PKHeX.WinForms
|
|||
this.Tab_Overview.Text = "Overview";
|
||||
this.Tab_Overview.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// B_GenTID
|
||||
//
|
||||
this.B_GenTID.Location = new System.Drawing.Point(124, 75);
|
||||
this.B_GenTID.Name = "B_GenTID";
|
||||
this.B_GenTID.Size = new System.Drawing.Size(68, 20);
|
||||
this.B_GenTID.TabIndex = 63;
|
||||
this.B_GenTID.Text = "Generate";
|
||||
this.B_GenTID.UseVisualStyleBackColor = true;
|
||||
this.B_GenTID.Click += new System.EventHandler(this.B_GenTID_Click);
|
||||
//
|
||||
// L_G7TID
|
||||
//
|
||||
this.L_G7TID.Location = new System.Drawing.Point(-1, 78);
|
||||
this.L_G7TID.Name = "L_G7TID";
|
||||
this.L_G7TID.Size = new System.Drawing.Size(48, 13);
|
||||
this.L_G7TID.TabIndex = 61;
|
||||
this.L_G7TID.Text = "G7TID:";
|
||||
this.L_G7TID.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// MT_G7TID
|
||||
//
|
||||
this.MT_G7TID.Location = new System.Drawing.Point(53, 75);
|
||||
this.MT_G7TID.Mask = "000000";
|
||||
this.MT_G7TID.Name = "MT_G7TID";
|
||||
this.MT_G7TID.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
||||
this.MT_G7TID.Size = new System.Drawing.Size(65, 20);
|
||||
this.MT_G7TID.TabIndex = 62;
|
||||
this.MT_G7TID.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// GB_Stats
|
||||
//
|
||||
this.GB_Stats.Controls.Add(this.NUD_Stat);
|
||||
|
@ -1081,7 +1112,7 @@ namespace PKHeX.WinForms
|
|||
this.Tab_BadgeMap.Controls.Add(this.GB_Map);
|
||||
this.Tab_BadgeMap.Location = new System.Drawing.Point(4, 22);
|
||||
this.Tab_BadgeMap.Name = "Tab_BadgeMap";
|
||||
this.Tab_BadgeMap.Size = new System.Drawing.Size(386, 294);
|
||||
this.Tab_BadgeMap.Size = new System.Drawing.Size(386, 290);
|
||||
this.Tab_BadgeMap.TabIndex = 3;
|
||||
this.Tab_BadgeMap.Text = "Map";
|
||||
this.Tab_BadgeMap.UseVisualStyleBackColor = true;
|
||||
|
@ -1272,7 +1303,7 @@ namespace PKHeX.WinForms
|
|||
this.Tab_BattleTree.Location = new System.Drawing.Point(4, 22);
|
||||
this.Tab_BattleTree.Name = "Tab_BattleTree";
|
||||
this.Tab_BattleTree.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.Tab_BattleTree.Size = new System.Drawing.Size(386, 294);
|
||||
this.Tab_BattleTree.Size = new System.Drawing.Size(386, 290);
|
||||
this.Tab_BattleTree.TabIndex = 5;
|
||||
this.Tab_BattleTree.Text = "Battle Tree";
|
||||
this.Tab_BattleTree.UseVisualStyleBackColor = true;
|
||||
|
@ -1555,6 +1586,8 @@ namespace PKHeX.WinForms
|
|||
//
|
||||
// Tab_Misc
|
||||
//
|
||||
this.Tab_Misc.Controls.Add(this.L_PlazaName);
|
||||
this.Tab_Misc.Controls.Add(this.TB_PlazaName);
|
||||
this.Tab_Misc.Controls.Add(this.CB_Fashion);
|
||||
this.Tab_Misc.Controls.Add(this.L_SkinColor);
|
||||
this.Tab_Misc.Controls.Add(this.CB_SkinColor);
|
||||
|
@ -1563,7 +1596,7 @@ namespace PKHeX.WinForms
|
|||
this.Tab_Misc.Location = new System.Drawing.Point(4, 22);
|
||||
this.Tab_Misc.Name = "Tab_Misc";
|
||||
this.Tab_Misc.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.Tab_Misc.Size = new System.Drawing.Size(386, 294);
|
||||
this.Tab_Misc.Size = new System.Drawing.Size(386, 290);
|
||||
this.Tab_Misc.TabIndex = 4;
|
||||
this.Tab_Misc.Text = "Misc";
|
||||
this.Tab_Misc.UseVisualStyleBackColor = true;
|
||||
|
@ -1738,34 +1771,25 @@ namespace PKHeX.WinForms
|
|||
this.B_Fashion.UseVisualStyleBackColor = true;
|
||||
this.B_Fashion.Click += new System.EventHandler(this.B_Fashion_Click);
|
||||
//
|
||||
// L_G7TID
|
||||
// TB_PlazaName
|
||||
//
|
||||
this.L_G7TID.Location = new System.Drawing.Point(-1, 78);
|
||||
this.L_G7TID.Name = "L_G7TID";
|
||||
this.L_G7TID.Size = new System.Drawing.Size(48, 13);
|
||||
this.L_G7TID.TabIndex = 61;
|
||||
this.L_G7TID.Text = "G7TID:";
|
||||
this.L_G7TID.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.TB_PlazaName.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.TB_PlazaName.Location = new System.Drawing.Point(217, 139);
|
||||
this.TB_PlazaName.MaxLength = 20;
|
||||
this.TB_PlazaName.Name = "TB_PlazaName";
|
||||
this.TB_PlazaName.Size = new System.Drawing.Size(159, 20);
|
||||
this.TB_PlazaName.TabIndex = 61;
|
||||
this.TB_PlazaName.Text = "WWWWWWWWWWWWWWWWWWWW";
|
||||
//
|
||||
// MT_G7TID
|
||||
// L_PlazaName
|
||||
//
|
||||
this.MT_G7TID.Location = new System.Drawing.Point(53, 75);
|
||||
this.MT_G7TID.Mask = "000000";
|
||||
this.MT_G7TID.Name = "MT_G7TID";
|
||||
this.MT_G7TID.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
||||
this.MT_G7TID.Size = new System.Drawing.Size(65, 20);
|
||||
this.MT_G7TID.TabIndex = 62;
|
||||
this.MT_G7TID.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// B_GenTID
|
||||
//
|
||||
this.B_GenTID.Location = new System.Drawing.Point(124, 75);
|
||||
this.B_GenTID.Name = "B_GenTID";
|
||||
this.B_GenTID.Size = new System.Drawing.Size(68, 20);
|
||||
this.B_GenTID.TabIndex = 63;
|
||||
this.B_GenTID.Text = "Generate";
|
||||
this.B_GenTID.UseVisualStyleBackColor = true;
|
||||
this.B_GenTID.Click += new System.EventHandler(this.B_GenTID_Click);
|
||||
this.L_PlazaName.AutoSize = true;
|
||||
this.L_PlazaName.Location = new System.Drawing.Point(214, 119);
|
||||
this.L_PlazaName.Name = "L_PlazaName";
|
||||
this.L_PlazaName.Size = new System.Drawing.Size(106, 13);
|
||||
this.L_PlazaName.TabIndex = 62;
|
||||
this.L_PlazaName.Text = "Festival Plaza Name:";
|
||||
this.L_PlazaName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// SAV_Trainer7
|
||||
//
|
||||
|
@ -1813,6 +1837,7 @@ namespace PKHeX.WinForms
|
|||
((System.ComponentModel.ISupportInitialize)(this.NUD_RMStreak0)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.NUD_RCStreak0)).EndInit();
|
||||
this.Tab_Misc.ResumeLayout(false);
|
||||
this.Tab_Misc.PerformLayout();
|
||||
this.GB_PokeFinder.ResumeLayout(false);
|
||||
this.GB_PokeFinder.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.NUD_SnapCount)).EndInit();
|
||||
|
@ -1969,5 +1994,7 @@ namespace PKHeX.WinForms
|
|||
private System.Windows.Forms.Button B_GenTID;
|
||||
private System.Windows.Forms.Label L_G7TID;
|
||||
private System.Windows.Forms.MaskedTextBox MT_G7TID;
|
||||
private System.Windows.Forms.TextBox TB_PlazaName;
|
||||
private System.Windows.Forms.Label L_PlazaName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,6 +182,7 @@ namespace PKHeX.WinForms
|
|||
NUD_SMStreak2.Value = Math.Min(NUD_SMStreak2.Maximum, SAV.getTreeStreak(2, super: true, max: true));
|
||||
|
||||
CB_SkinColor.SelectedIndex = SAV.DressUpSkinColor;
|
||||
TB_PlazaName.Text = SAV.FestivalPlazaName;
|
||||
}
|
||||
private void save()
|
||||
{
|
||||
|
@ -262,6 +263,8 @@ namespace PKHeX.WinForms
|
|||
if (SAV.DressUpSkinColor != CB_SkinColor.SelectedIndex &&
|
||||
(SAV.Gender == skin || DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, $"Gender-Skin mismatch:\nGender: {gStr}, Skin: {sStr}", "Save selected Skin Color?")))
|
||||
SAV.DressUpSkinColor = CB_SkinColor.SelectedIndex;
|
||||
|
||||
SAV.FestivalPlazaName = TB_PlazaName.Text;
|
||||
}
|
||||
|
||||
private void clickOT(object sender, MouseEventArgs e)
|
||||
|
|
|
@ -203,7 +203,12 @@ namespace PKHeX.WinForms
|
|||
pb.BackgroundImage = null;
|
||||
|
||||
if (DragInfo.SameBox && DragInfo.DestinationValid)
|
||||
SlotPictureBoxes[DragInfo.slotDestinationSlotNumber].Image = img;
|
||||
{
|
||||
if (SAV.getIsTeamSet(box, DragInfo.slotDestinationSlotNumber) ^ SAV.getIsTeamSet(box, DragInfo.slotSourceSlotNumber))
|
||||
getQuickFiller(SlotPictureBoxes[DragInfo.slotDestinationSlotNumber], SAV.getStoredSlot(DragInfo.slotDestinationOffset));
|
||||
else
|
||||
SlotPictureBoxes[DragInfo.slotDestinationSlotNumber].Image = img;
|
||||
}
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
|
|
|
@ -104,6 +104,7 @@ namespace PKHeX.WinForms
|
|||
dgvIndex.DisplayIndex = c++;
|
||||
dgvIndex.Width = 45;
|
||||
dgvIndex.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
|
||||
((DataGridViewTextBoxColumn) dgvIndex).MaxInputLength = (int)(Math.Log10(Math.Max(1, pouch.MaxCount)) + 1);
|
||||
}
|
||||
|
||||
dgv.Columns.Add(dgvItemVal);
|
||||
|
|
|
@ -492,7 +492,17 @@ namespace PKHeX.WinForms
|
|||
string s = gift.getCardHeader() + Environment.NewLine;
|
||||
if (gift.IsItem)
|
||||
{
|
||||
s += "Item: " + GameInfo.Strings.itemlist[gift.Item] + Environment.NewLine + "Quantity: " + gift.Quantity + Environment.NewLine;
|
||||
s += $"Item: {GameInfo.Strings.itemlist[gift.Item]} (Quantity: {gift.Quantity})" + Environment.NewLine;
|
||||
if (gift is WC7)
|
||||
{
|
||||
var ind = 1;
|
||||
var wc7 = (WC7) gift;
|
||||
while (wc7.GetItem(ind) != 0)
|
||||
{
|
||||
s += $"Item: {GameInfo.Strings.itemlist[wc7.GetItem(ind)]} (Quantity: {wc7.GetQuantity(ind)})" + Environment.NewLine;
|
||||
ind++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gift.IsPokémon)
|
||||
{
|
||||
|
|
|
@ -20,23 +20,23 @@ namespace PKHeX.WinForms
|
|||
public string Position => pkm.Identifier;
|
||||
public Image Sprite => pkm.Sprite();
|
||||
public string Nickname => pkm.Nickname;
|
||||
public string Species => GameInfo.Strings.specieslist[pkm.Species];
|
||||
public string Nature => GameInfo.Strings.natures[pkm.Nature];
|
||||
public string Gender => Main.gendersymbols[pkm.Gender];
|
||||
public string Species => get(GameInfo.Strings.specieslist, pkm.Species);
|
||||
public string Nature => get(GameInfo.Strings.natures, pkm.Nature);
|
||||
public string Gender => get(Main.gendersymbols, pkm.Gender);
|
||||
public string ESV => pkm.PSV.ToString("0000");
|
||||
public string HP_Type => GameInfo.Strings.types[pkm.HPType+1];
|
||||
public string Ability => GameInfo.Strings.abilitylist[pkm.Ability];
|
||||
public string Move1 => GameInfo.Strings.movelist[pkm.Move1];
|
||||
public string Move2 => GameInfo.Strings.movelist[pkm.Move2];
|
||||
public string Move3 => GameInfo.Strings.movelist[pkm.Move3];
|
||||
public string Move4 => GameInfo.Strings.movelist[pkm.Move4];
|
||||
public string HeldItem => GameInfo.Strings.itemlist[pkm.HeldItem];
|
||||
public string HP_Type => get(GameInfo.Strings.types, pkm.HPType+1);
|
||||
public string Ability => get(GameInfo.Strings.abilitylist, pkm.Ability);
|
||||
public string Move1 => get(GameInfo.Strings.movelist, pkm.Move1);
|
||||
public string Move2 => get(GameInfo.Strings.movelist, pkm.Move2);
|
||||
public string Move3 => get(GameInfo.Strings.movelist, pkm.Move3);
|
||||
public string Move4 => get(GameInfo.Strings.movelist, pkm.Move4);
|
||||
public string HeldItem => get(GameInfo.Strings.itemlist, pkm.HeldItem);
|
||||
public string MetLoc => pkm.getLocation(eggmet: false);
|
||||
public string EggLoc => pkm.getLocation(eggmet: true);
|
||||
public string Ball => GameInfo.Strings.balllist[pkm.Ball];
|
||||
public string Ball => get(GameInfo.Strings.balllist, pkm.Ball);
|
||||
public string OT => pkm.OT_Name;
|
||||
public string Version => GameInfo.Strings.gamelist[pkm.Version];
|
||||
public string OTLang => GameInfo.Strings.gamelanguages[pkm.Language] ?? $"UNK {pkm.Language}";
|
||||
public string Version => get(GameInfo.Strings.gamelist, pkm.Version);
|
||||
public string OTLang => get(GameInfo.Strings.gamelanguages, pkm.Language) ?? $"UNK {pkm.Language}";
|
||||
public string CountryID => pkm.Format > 5 ? pkm.Country.ToString() : "N/A";
|
||||
public string RegionID => pkm.Format > 5 ? pkm.Region.ToString() : "N/A";
|
||||
public string DSRegionID => pkm.Format > 5 ? pkm.ConsoleRegion.ToString() : "N/A";
|
||||
|
@ -92,10 +92,10 @@ namespace PKHeX.WinForms
|
|||
public int Move2_PPUp => pkm.Move2_PPUps;
|
||||
public int Move3_PPUp => pkm.Move3_PPUps;
|
||||
public int Move4_PPUp => pkm.Move4_PPUps;
|
||||
public string Relearn1 => GameInfo.Strings.movelist[pkm.RelearnMove1];
|
||||
public string Relearn2 => GameInfo.Strings.movelist[pkm.RelearnMove2];
|
||||
public string Relearn3 => GameInfo.Strings.movelist[pkm.RelearnMove3];
|
||||
public string Relearn4 => GameInfo.Strings.movelist[pkm.RelearnMove4];
|
||||
public string Relearn1 => get(GameInfo.Strings.movelist, pkm.RelearnMove1);
|
||||
public string Relearn2 => get(GameInfo.Strings.movelist, pkm.RelearnMove2);
|
||||
public string Relearn3 => get(GameInfo.Strings.movelist, pkm.RelearnMove3);
|
||||
public string Relearn4 => get(GameInfo.Strings.movelist, pkm.RelearnMove4);
|
||||
public ushort Checksum => pkm.Checksum;
|
||||
public int mFriendship => pkm.OT_Friendship;
|
||||
public int OT_Affection => pkm.OT_Affection;
|
||||
|
@ -109,6 +109,8 @@ namespace PKHeX.WinForms
|
|||
|
||||
#endregion
|
||||
public Preview(PKM p) { pkm = p; }
|
||||
|
||||
private static string get(IReadOnlyList<string> arr, int val) => arr?.Count > val ? arr[val] : null;
|
||||
}
|
||||
public frmReport()
|
||||
{
|
||||
|
|
|
@ -267,8 +267,8 @@ namespace PKHeX.Core
|
|||
public static GameStrings Strings;
|
||||
|
||||
// DataSource providing
|
||||
public static List<ComboItem> MoveDataSource, ItemDataSource, SpeciesDataSource, BallDataSource, NatureDataSource, AbilityDataSource, VersionDataSource;
|
||||
public static List<ComboItem> HaXMoveDataSource;
|
||||
public static List<ComboItem> ItemDataSource, SpeciesDataSource, BallDataSource, NatureDataSource, AbilityDataSource, VersionDataSource;
|
||||
public static List<ComboItem> LegalMoveDataSource, HaXMoveDataSource, MoveDataSource;
|
||||
private static List<ComboItem> metGen2, metGen3, metGen3CXD, metGen4, metGen5, metGen6, metGen7;
|
||||
|
||||
public static void InitializeDataSources(GameStrings s)
|
||||
|
@ -284,7 +284,7 @@ namespace PKHeX.Core
|
|||
VersionDataSource.AddRange(Util.getCBList(s.gamelist, Legal.Games_7go).OrderBy(g => g.Value)); // stuff to end unsorted
|
||||
|
||||
HaXMoveDataSource = Util.getCBList(s.movelist, null);
|
||||
MoveDataSource = HaXMoveDataSource.Where(m => !Legal.Z_Moves.Contains(m.Value)).ToList();
|
||||
MoveDataSource = LegalMoveDataSource = HaXMoveDataSource.Where(m => !Legal.Z_Moves.Contains(m.Value)).ToList();
|
||||
#region Met Locations
|
||||
// Gen 2
|
||||
{
|
||||
|
@ -525,5 +525,56 @@ namespace PKHeX.Core
|
|||
}
|
||||
catch { return "Illegal"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the location names array for a specified generation.
|
||||
/// </summary>
|
||||
/// <param name="gen">Generation to get location names for.</param>
|
||||
/// <param name="bankID">BankID used to choose the text bank.</param>
|
||||
/// <returns>List of location names.</returns>
|
||||
public static string[] getLocationNames(int gen, int bankID)
|
||||
{
|
||||
switch (gen)
|
||||
{
|
||||
case 2: return Strings.metGSC_00000;
|
||||
case 3: return Strings.metRSEFRLG_00000;
|
||||
case 4:
|
||||
switch (bankID)
|
||||
{
|
||||
case 0: return Strings.metHGSS_00000;
|
||||
case 2: return Strings.metHGSS_02000;
|
||||
default: return null;
|
||||
}
|
||||
case 5:
|
||||
switch (bankID)
|
||||
{
|
||||
case 0: return Strings.metBW2_00000;
|
||||
case 3: return Strings.metBW2_30000;
|
||||
case 4: return Strings.metBW2_40000;
|
||||
case 6: return Strings.metBW2_60000;
|
||||
default: return null;
|
||||
}
|
||||
case 6:
|
||||
switch (bankID)
|
||||
{
|
||||
case 0: return Strings.metXY_00000;
|
||||
case 3: return Strings.metXY_30000;
|
||||
case 4: return Strings.metXY_40000;
|
||||
case 6: return Strings.metXY_60000;
|
||||
default: return null;
|
||||
}
|
||||
case 7:
|
||||
switch (bankID)
|
||||
{
|
||||
case 0: return Strings.metSM_00000;
|
||||
case 3: return Strings.metSM_30000;
|
||||
case 4: return Strings.metSM_40000;
|
||||
case 6: return Strings.metSM_60000;
|
||||
default: return null;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
/*Gen6*/ X = 24, Y = 25, AS = 26, OR = 27,
|
||||
/*Gen7*/ SN = 30, MN = 31,
|
||||
/* GO */ GO = 34,
|
||||
/* VC */ RD = 35, BU = 36, GN = 37, YW = 38,
|
||||
/* VC */ RD = 35, GN = 36, BU = 37, YW = 38, // GN = Blue for international release
|
||||
|
||||
// Game Groupings (SaveFile type)
|
||||
RBY = 98,
|
||||
|
@ -39,6 +39,7 @@
|
|||
SM = 109,
|
||||
|
||||
// Extra Game Groupings (Generation)
|
||||
Gen1, Gen2, Gen3, Gen4, Gen5, Gen6, Gen7
|
||||
Gen1, Gen2, Gen3, Gen4, Gen5, Gen6, Gen7,
|
||||
SPECIAL, // Stadium
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ namespace PKHeX.Core
|
|||
public partial class LegalityAnalysis
|
||||
{
|
||||
private PKM pkm;
|
||||
private DexLevel[] EvoChain;
|
||||
private DexLevel[][] EvoChainsAllGens;
|
||||
private readonly List<CheckResult> Parse = new List<CheckResult>();
|
||||
|
||||
private object EncounterMatch;
|
||||
private object EncounterMatch, EncounterOriginal;
|
||||
private Type EncounterType;
|
||||
private bool EncounterIsMysteryGift => EncounterType.IsSubclassOf(typeof (MysteryGift));
|
||||
private string EncounterName => Legal.getEncounterTypeName(pkm, EncounterMatch);
|
||||
private string EncounterName => Legal.getEncounterTypeName(pkm, EncounterOriginal ?? EncounterMatch);
|
||||
private List<MysteryGift> EventGiftMatch;
|
||||
private CheckResult Encounter, History;
|
||||
private int[] RelearnBase;
|
||||
|
@ -39,11 +39,18 @@ namespace PKHeX.Core
|
|||
|
||||
try
|
||||
{
|
||||
switch (pk.Format) // prior to storing GameVersion
|
||||
{
|
||||
case 1: parsePK1(pk); break;
|
||||
}
|
||||
|
||||
if (!Parse.Any())
|
||||
switch (pk.GenNumber)
|
||||
{
|
||||
case 6: parsePK6(pk); break;
|
||||
|
||||
case 1: parsePK7(pk); break;
|
||||
case 7: parsePK7(pk); break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
Valid = Parsed = Parse.Any();
|
||||
|
@ -59,10 +66,12 @@ namespace PKHeX.Core
|
|||
if (pkm.FatefulEncounter && vRelearn.Any(chk => !chk.Valid) && EncounterMatch == null)
|
||||
AddLine(Severity.Indeterminate, "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?", CheckIdentifier.Fateful);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
catch { Valid = false; }
|
||||
AllSuggestedMoves = !pkm.IsOriginValid() ? new int[4] : getSuggestedMoves(true, true, true);
|
||||
AllSuggestedRelearnMoves = !pkm.IsOriginValid() ? new int[4] : Legal.getValidRelearn(pkm, -1).ToArray();
|
||||
AllSuggestedMoves = !pkm.IsOriginValid ? new int[4] : getSuggestedMoves(true, true, true);
|
||||
AllSuggestedRelearnMoves = !pkm.IsOriginValid ? new int[4] : Legal.getValidRelearn(pkm, -1).ToArray();
|
||||
AllSuggestedMovesAndRelearn = AllSuggestedMoves.Concat(AllSuggestedRelearnMoves).ToArray();
|
||||
}
|
||||
|
||||
|
@ -74,26 +83,42 @@ namespace PKHeX.Core
|
|||
{
|
||||
Parse.Add(chk);
|
||||
}
|
||||
|
||||
private void parsePK1(PKM pk)
|
||||
{
|
||||
pkm = pk;
|
||||
if (!pkm.IsOriginValid)
|
||||
{ AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; }
|
||||
|
||||
updateEncounterChain();
|
||||
updateMoveLegality();
|
||||
updateEncounterInfo();
|
||||
verifyNickname();
|
||||
verifyDVs();
|
||||
verifyG1OT();
|
||||
}
|
||||
private void parsePK6(PKM pk)
|
||||
{
|
||||
pkm = pk;
|
||||
if (!pkm.IsOriginValid())
|
||||
if (!pkm.IsOriginValid)
|
||||
{ AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; }
|
||||
|
||||
updateRelearnLegality();
|
||||
updateEncounterChain();
|
||||
updateMoveLegality();
|
||||
updateEncounterInfo();
|
||||
updateChecks();
|
||||
}
|
||||
private void parsePK7(PKM pk)
|
||||
{
|
||||
pkm = pk;
|
||||
if (!pkm.IsOriginValid())
|
||||
if (!pkm.IsOriginValid)
|
||||
{ AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; }
|
||||
|
||||
updateRelearnLegality();
|
||||
updateEncounterChain();
|
||||
updateMoveLegality();
|
||||
updateEncounterInfo();
|
||||
updateChecks();
|
||||
}
|
||||
|
||||
|
@ -116,18 +141,20 @@ namespace PKHeX.Core
|
|||
EncounterMatch = EventGiftMatch.First(); // temporarily set one so that Encounter can be verified
|
||||
|
||||
Encounter = verifyEncounter();
|
||||
EvoChain = Legal.getEvolutionChain(pkm, EncounterMatch);
|
||||
Parse.Add(Encounter);
|
||||
EvoChainsAllGens = Legal.getEvolutionChainsAllGens(pkm, EncounterOriginal ?? EncounterMatch);
|
||||
}
|
||||
private void updateChecks()
|
||||
private void updateEncounterInfo()
|
||||
{
|
||||
EncounterMatch = EncounterMatch ?? pkm.Species;
|
||||
|
||||
EncounterType = EncounterMatch?.GetType();
|
||||
EncounterType = (EncounterOriginal ?? EncounterMatch)?.GetType();
|
||||
if (EncounterType == typeof (MysteryGift))
|
||||
EncounterType = EncounterType.BaseType;
|
||||
}
|
||||
private void updateChecks()
|
||||
{
|
||||
History = verifyHistory();
|
||||
|
||||
AddLine(Encounter);
|
||||
AddLine(History);
|
||||
|
||||
verifyECPID();
|
||||
|
@ -160,6 +187,8 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < 4; i++)
|
||||
if (!vMoves[i].Valid)
|
||||
r += $"{vMoves[i].Judgement} Move {i + 1}: {vMoves[i].Comment}" + Environment.NewLine;
|
||||
|
||||
if (pkm.Format >= 6)
|
||||
for (int i = 0; i < 4; i++)
|
||||
if (!vRelearn[i].Valid)
|
||||
r += $"{vRelearn[i].Judgement} Relearn Move {i + 1}: {vRelearn[i].Comment}" + Environment.NewLine;
|
||||
|
@ -186,7 +215,9 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < 4; i++)
|
||||
if (vMoves[i].Valid)
|
||||
r += $"{vMoves[i].Judgement} Move {i + 1}: {vMoves[i].Comment}" + Environment.NewLine;
|
||||
for (int i = 0; i < 4; i++)
|
||||
|
||||
if (pkm.Format >= 6)
|
||||
for (int i = 0; i < 4; i++)
|
||||
if (vRelearn[i].Valid)
|
||||
r += $"{vRelearn[i].Judgement} Relearn Move {i + 1}: {vRelearn[i].Comment}" + Environment.NewLine;
|
||||
|
||||
|
@ -204,7 +235,7 @@ namespace PKHeX.Core
|
|||
|
||||
public int[] getSuggestedRelearn()
|
||||
{
|
||||
if (RelearnBase == null || pkm.GenNumber < 6 || !pkm.IsOriginValid())
|
||||
if (RelearnBase == null || pkm.GenNumber < 6 || !pkm.IsOriginValid)
|
||||
return new int[4];
|
||||
|
||||
if (!pkm.WasEgg)
|
||||
|
@ -222,9 +253,11 @@ namespace PKHeX.Core
|
|||
}
|
||||
public int[] getSuggestedMoves(bool tm, bool tutor, bool reminder)
|
||||
{
|
||||
if (pkm == null || pkm.GenNumber < 6 || !pkm.IsOriginValid())
|
||||
if (pkm == null || !pkm.IsOriginValid)
|
||||
return null;
|
||||
return Legal.getValidMoves(pkm, EvoChain, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray(); // skip move 0
|
||||
if (!Parsed)
|
||||
return new int[4];
|
||||
return Legal.getValidMoves(pkm, EvoChainsAllGens, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray(); // skip move 0
|
||||
}
|
||||
|
||||
public EncounterStatic getSuggestedMetInfo()
|
||||
|
@ -232,24 +265,30 @@ namespace PKHeX.Core
|
|||
if (pkm == null)
|
||||
return null;
|
||||
|
||||
int loc = getSuggestedTransferLocation(pkm);
|
||||
if (pkm.WasEgg)
|
||||
return new EncounterStatic
|
||||
{
|
||||
Species = Legal.getBaseSpecies(pkm),
|
||||
Location = getSuggestedEggMetLocation(pkm),
|
||||
Location = loc != -1 ? loc : getSuggestedEggMetLocation(pkm),
|
||||
Level = 1,
|
||||
};
|
||||
|
||||
var capture = Legal.getCaptureLocation(pkm);
|
||||
if (capture != null)
|
||||
var area = Legal.getCaptureLocation(pkm);
|
||||
if (area != null)
|
||||
{
|
||||
var slots = area.Slots.OrderBy(s => s.LevelMin);
|
||||
return new EncounterStatic
|
||||
{
|
||||
Species = capture.Slots.First().Species,
|
||||
Location = capture.Location,
|
||||
Level = capture.Slots.First().LevelMin,
|
||||
Species = slots.First().Species,
|
||||
Location = loc != -1 ? loc : area.Location,
|
||||
Level = slots.First().LevelMin,
|
||||
};
|
||||
}
|
||||
|
||||
var encounter = Legal.getStaticLocation(pkm);
|
||||
if (loc != -1)
|
||||
encounter.Location = loc;
|
||||
return encounter;
|
||||
}
|
||||
private static int getSuggestedEggMetLocation(PKM pkm)
|
||||
|
@ -282,5 +321,18 @@ namespace PKHeX.Core
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
private static int getSuggestedTransferLocation(PKM pkm)
|
||||
{
|
||||
// Return one of legal hatch locations for game
|
||||
if (pkm.HasOriginalMetLocation)
|
||||
return -1;
|
||||
if (pkm.VC1)
|
||||
return 30013;
|
||||
if (pkm.Format == 4) // Pal Park
|
||||
return 0x37;
|
||||
if (pkm.Format == 5) // Transporter
|
||||
return 30001;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace PKHeX.Core
|
|||
Gender,
|
||||
EVs,
|
||||
Language,
|
||||
Nickname,
|
||||
Trainer,
|
||||
IVs,
|
||||
None,
|
||||
|
@ -50,7 +51,7 @@ namespace PKHeX.Core
|
|||
public bool Flag;
|
||||
private readonly CheckIdentifier Identifier;
|
||||
|
||||
internal CheckResult(CheckIdentifier i) { }
|
||||
internal CheckResult(CheckIdentifier i) { Identifier = i; }
|
||||
internal CheckResult(Severity s, string c, CheckIdentifier i)
|
||||
{
|
||||
Judgement = s;
|
||||
|
@ -115,12 +116,11 @@ namespace PKHeX.Core
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pkm.Format < 6)
|
||||
|
||||
// abort if specimen wasn't transferred x->6
|
||||
if (pkm.Format < 6 || !(3 <= pkm.GenNumber && pkm.GenNumber <= 5))
|
||||
return;
|
||||
|
||||
if (pkm.GenNumber >= 6)
|
||||
return;
|
||||
// When transferred to Generation 6, the Encryption Constant is copied from the PID.
|
||||
// The PID is then checked to see if it becomes shiny with the new Shiny rules (>>4 instead of >>3)
|
||||
// If the PID is nonshiny->shiny, the top bit is flipped.
|
||||
|
@ -144,12 +144,12 @@ namespace PKHeX.Core
|
|||
// If the Pokémon is not nicknamed, it should match one of the language strings.
|
||||
if (pkm.Nickname.Length == 0)
|
||||
{
|
||||
AddLine(Severity.Invalid, "Nickname is empty.", CheckIdentifier.EVs);
|
||||
AddLine(Severity.Invalid, "Nickname is empty.", CheckIdentifier.Nickname);
|
||||
return;
|
||||
}
|
||||
if (pkm.Species > PKX.SpeciesLang[0].Length)
|
||||
{
|
||||
AddLine(Severity.Indeterminate, "Species index invalid for Nickname comparison.", CheckIdentifier.EVs);
|
||||
AddLine(Severity.Indeterminate, "Species index invalid for Nickname comparison.", CheckIdentifier.Nickname);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ namespace PKHeX.Core
|
|||
int lang = Array.IndexOf(PKX.SpeciesLang, langset);
|
||||
|
||||
if (pk.Length > (lang == 2 ? 10 : 5))
|
||||
AddLine(Severity.Invalid, "Nickname too long.", CheckIdentifier.Trainer);
|
||||
AddLine(Severity.Invalid, "Nickname too long.", CheckIdentifier.Nickname);
|
||||
}
|
||||
|
||||
if (!Encounter.Valid)
|
||||
|
@ -194,7 +194,23 @@ namespace PKHeX.Core
|
|||
else if (pkm.SM)
|
||||
{
|
||||
// TODO
|
||||
AddLine(Severity.Valid, "Ingame Trade for Sun/Moon un-implemented.", CheckIdentifier.EVs);
|
||||
AddLine(Severity.Valid, "Ingame Trade for Sun/Moon not implemented.", CheckIdentifier.Nickname);
|
||||
return;
|
||||
}
|
||||
else if (pkm.Format <= 2 || pkm.VC)
|
||||
{
|
||||
var et = EncounterOriginal as EncounterTrade;
|
||||
if (et?.TID == 0) // Gen1 Trade
|
||||
{
|
||||
string ot = pkm.OT_Name;
|
||||
string tr = pkm.Format <= 2 ? "TRAINER" : "Trainer"; // decaps on transfer
|
||||
if (ot != "トレーナー" && ot != tr)
|
||||
AddLine(Severity.Invalid, "Incorrect OT name for RBY in-game trade.", CheckIdentifier.Trainer);
|
||||
}
|
||||
else // Gen2
|
||||
{
|
||||
AddLine(Severity.Valid, "Ingame Trade for GSC not implemented.", CheckIdentifier.Trainer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -213,11 +229,11 @@ namespace PKHeX.Core
|
|||
string OT = validOT[validOT.Length/2 + index];
|
||||
|
||||
if (nick != pkm.Nickname)
|
||||
AddLine(Severity.Fishy, "Ingame Trade nickname has been altered.", CheckIdentifier.EVs);
|
||||
AddLine(Severity.Fishy, "Ingame Trade nickname has been altered.", CheckIdentifier.Nickname);
|
||||
else if (OT != pkm.OT_Name)
|
||||
AddLine(Severity.Invalid, "Ingame Trade OT has been altered.", CheckIdentifier.Trainer);
|
||||
else
|
||||
AddLine(Severity.Valid, "Ingame Trade OT/Nickname have not been altered.", CheckIdentifier.EVs);
|
||||
AddLine(Severity.Valid, "Ingame Trade OT/Nickname have not been altered.", CheckIdentifier.Nickname);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -225,11 +241,11 @@ namespace PKHeX.Core
|
|||
if (pkm.IsEgg)
|
||||
{
|
||||
if (!pkm.IsNicknamed && (pkm.Format != 7))
|
||||
AddLine(Severity.Invalid, "Eggs must be nicknamed.", CheckIdentifier.EVs);
|
||||
AddLine(Severity.Invalid, "Eggs must be nicknamed.", CheckIdentifier.Egg);
|
||||
else if (PKX.SpeciesLang[pkm.Language][0] != pkm.Nickname)
|
||||
AddLine(Severity.Invalid, "Egg name does not match language Egg name.", CheckIdentifier.EVs);
|
||||
AddLine(Severity.Invalid, "Egg name does not match language Egg name.", CheckIdentifier.Egg);
|
||||
else
|
||||
AddLine(Severity.Valid, "Egg matches language Egg name.", CheckIdentifier.EVs);
|
||||
AddLine(Severity.Valid, "Egg matches language Egg name.", CheckIdentifier.Egg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -246,25 +262,31 @@ namespace PKHeX.Core
|
|||
|
||||
AddLine(Severity.Fishy, index == pkm.Species && i != pkm.Language
|
||||
? "Nickname matches another species name (+language)."
|
||||
: "Nickname flagged, matches species name.", CheckIdentifier.EVs);
|
||||
: "Nickname flagged, matches species name.", CheckIdentifier.Nickname);
|
||||
return;
|
||||
}
|
||||
AddLine(Severity.Valid, "Nickname does not match another species name.", CheckIdentifier.EVs);
|
||||
return;
|
||||
AddLine(Severity.Valid, "Nickname does not match another species name.", CheckIdentifier.Nickname);
|
||||
}
|
||||
|
||||
// else
|
||||
else if (pkm.Format < 3)
|
||||
{
|
||||
// pk1/pk2 IsNicknamed getter checks for match, logic should only reach here if matches.
|
||||
AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.Nickname);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't have another language name if it hasn't evolved or wasn't a language-traded egg.
|
||||
bool match = (pkm.WasTradedEgg || Legal.getHasEvolved(pkm)) && PKX.SpeciesLang.Any(lang => lang[pkm.Species] == nickname)
|
||||
|| PKX.SpeciesLang[pkm.Language][pkm.Species] == nickname;
|
||||
|
||||
if (!match)
|
||||
AddLine(Severity.Invalid, "Nickname does not match species name.", CheckIdentifier.EVs);
|
||||
{
|
||||
if ((EncounterMatch as MysteryGift)?.CardID == 2046 && (pkm.SID << 16 | pkm.TID) == 0x79F57B49)
|
||||
AddLine(Severity.Valid, "Nickname matches demo language name.", CheckIdentifier.Nickname);
|
||||
else
|
||||
AddLine(Severity.Invalid, "Nickname does not match species name.", CheckIdentifier.Nickname);
|
||||
}
|
||||
else
|
||||
AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.EVs);
|
||||
|
||||
// return;
|
||||
AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.Nickname);
|
||||
}
|
||||
}
|
||||
private void verifyEVs()
|
||||
|
@ -328,6 +350,10 @@ namespace PKHeX.Core
|
|||
else if (pkm.IVs[0] < 30 && pkm.IVs.All(iv => pkm.IVs[0] == iv))
|
||||
AddLine(Severity.Fishy, "All IVs are equal.", CheckIdentifier.IVs);
|
||||
}
|
||||
private void verifyDVs()
|
||||
{
|
||||
// todo
|
||||
}
|
||||
private void verifyOT()
|
||||
{
|
||||
if (EncounterType == typeof(EncounterTrade))
|
||||
|
@ -348,19 +374,21 @@ namespace PKHeX.Core
|
|||
AddLine(Severity.Fishy, "SID is zero.", CheckIdentifier.Trainer);
|
||||
|
||||
if (pkm.VC)
|
||||
{
|
||||
string tr = pkm.OT_Name;
|
||||
string pk = pkm.Nickname;
|
||||
var langset = PKX.SpeciesLang.FirstOrDefault(s => s.Contains(pk)) ?? PKX.SpeciesLang[2];
|
||||
int lang = Array.IndexOf(PKX.SpeciesLang, langset);
|
||||
verifyG1OT();
|
||||
}
|
||||
private void verifyG1OT()
|
||||
{
|
||||
string tr = pkm.OT_Name;
|
||||
string pk = pkm.Nickname;
|
||||
var langset = PKX.SpeciesLang.FirstOrDefault(s => s.Contains(pk)) ?? PKX.SpeciesLang[2];
|
||||
int lang = Array.IndexOf(PKX.SpeciesLang, langset);
|
||||
|
||||
if (tr.Length > (lang == 2 ? 7 : 5))
|
||||
AddLine(Severity.Invalid, "OT Name too long.", CheckIdentifier.Trainer);
|
||||
if (pkm.Species == 151)
|
||||
{
|
||||
if (tr != "GF" && tr != "ゲーフリ") // if there are more events with special OTs, may be worth refactoring
|
||||
AddLine(Severity.Invalid, "Incorrect event OT Name.", CheckIdentifier.Trainer);
|
||||
}
|
||||
if (tr.Length > (lang == 2 ? 7 : 5))
|
||||
AddLine(Severity.Invalid, "OT Name too long.", CheckIdentifier.Trainer);
|
||||
if (pkm.Species == 151)
|
||||
{
|
||||
if (tr != "GF" && tr != "ゲーフリ") // if there are more events with special OTs, may be worth refactoring
|
||||
AddLine(Severity.Invalid, "Incorrect event OT Name.", CheckIdentifier.Trainer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,158 +414,233 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CheckResult verifyEncounterLink()
|
||||
{
|
||||
// Should NOT be Fateful, and should be in Database
|
||||
EncounterLink enc = EncounterMatch as EncounterLink;
|
||||
if (enc == null)
|
||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: unable to find matching gift.", CheckIdentifier.Encounter);
|
||||
|
||||
if (pkm.XY && !enc.XY)
|
||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in XY.", CheckIdentifier.Encounter);
|
||||
if (pkm.AO && !enc.ORAS)
|
||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in ORAS.", CheckIdentifier.Encounter);
|
||||
if (pkm.SM && !enc.SM)
|
||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in SM.", CheckIdentifier.Encounter);
|
||||
|
||||
if (enc.Shiny != null && (bool)enc.Shiny ^ pkm.IsShiny)
|
||||
return new CheckResult(Severity.Invalid, "Shiny Link gift mismatch.", CheckIdentifier.Encounter);
|
||||
|
||||
return pkm.FatefulEncounter
|
||||
? new CheckResult(Severity.Invalid, "Invalid Link Gift: should not be Fateful Encounter.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, "Valid Link gift.", CheckIdentifier.Encounter);
|
||||
}
|
||||
private CheckResult verifyEncounterEvent()
|
||||
{
|
||||
MysteryGift MatchedGift = EncounterMatch as MysteryGift;
|
||||
if (MatchedGift != null)
|
||||
return new CheckResult(Severity.Valid, $"Matches #{MatchedGift.CardID:0000} ({MatchedGift.CardTitle})", CheckIdentifier.Encounter);
|
||||
return null;
|
||||
}
|
||||
private CheckResult verifyEncounterEgg()
|
||||
{
|
||||
// Check Hatch Locations
|
||||
if (pkm.Met_Level != 1)
|
||||
return new CheckResult(Severity.Invalid, "Invalid met level, expected 1.", CheckIdentifier.Encounter);
|
||||
// Check species
|
||||
if (Legal.NoHatchFromEgg.Contains(pkm.Species))
|
||||
return new CheckResult(Severity.Invalid, "Species cannot be hatched from an egg.", CheckIdentifier.Encounter);
|
||||
if (pkm.IsEgg)
|
||||
{
|
||||
if (pkm.Egg_Location == 30002)
|
||||
return new CheckResult(Severity.Invalid, "Egg location shouldn't be 'traded' for an un-hatched egg.", CheckIdentifier.Encounter);
|
||||
|
||||
if (pkm.Met_Location == 30002)
|
||||
return new CheckResult(Severity.Valid, "Valid traded un-hatched egg.", CheckIdentifier.Encounter);
|
||||
return pkm.Met_Location == 0
|
||||
? new CheckResult(Severity.Valid, "Valid un-hatched egg.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Invalid location for un-hatched egg (expected no met location).", CheckIdentifier.Encounter);
|
||||
}
|
||||
if (pkm.XY)
|
||||
{
|
||||
if (pkm.Egg_Location == 318)
|
||||
return new CheckResult(Severity.Invalid, "Invalid X/Y egg location.", CheckIdentifier.Encounter);
|
||||
return Legal.ValidMet_XY.Contains(pkm.Met_Location)
|
||||
? new CheckResult(Severity.Valid, "Valid X/Y hatched egg.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Invalid X/Y location for hatched egg.", CheckIdentifier.Encounter);
|
||||
}
|
||||
if (pkm.AO)
|
||||
{
|
||||
return Legal.ValidMet_AO.Contains(pkm.Met_Location)
|
||||
? new CheckResult(Severity.Valid, "Valid OR/AS hatched egg.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Invalid OR/AS location for hatched egg.", CheckIdentifier.Encounter);
|
||||
}
|
||||
if (pkm.SM)
|
||||
{
|
||||
return Legal.ValidMet_SM.Contains(pkm.Met_Location)
|
||||
? new CheckResult(Severity.Valid, "Valid S/M hatched egg.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Invalid S/M location for hatched egg.", CheckIdentifier.Encounter);
|
||||
}
|
||||
return new CheckResult(Severity.Invalid, "Invalid location for hatched egg.", CheckIdentifier.Encounter);
|
||||
}
|
||||
private CheckResult verifyEncounterSafari()
|
||||
{
|
||||
if (pkm.Species == 670 || pkm.Species == 671) // Floette
|
||||
if (!new[] {0, 1, 3}.Contains(pkm.AltForm)) // 0/1/3 - RBY
|
||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not valid color.", CheckIdentifier.Encounter);
|
||||
else if (pkm.Species == 710 || pkm.Species == 711) // Pumpkaboo
|
||||
if (pkm.AltForm != 1) // Average
|
||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not average sized.", CheckIdentifier.Encounter);
|
||||
else if (pkm.Species == 586) // Sawsbuck
|
||||
if (pkm.AltForm != 0)
|
||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not Spring form.", CheckIdentifier.Encounter);
|
||||
|
||||
return new CheckResult(Severity.Valid, "Valid Friend Safari encounter.", CheckIdentifier.Encounter);
|
||||
}
|
||||
private CheckResult verifyEncounterWild()
|
||||
{
|
||||
EncounterSlot[] enc = (EncounterSlot[])EncounterMatch;
|
||||
|
||||
if (enc.Any(slot => slot.Normal))
|
||||
return enc.All(slot => slot.Pressure)
|
||||
? new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, "Valid encounter at location.", CheckIdentifier.Encounter);
|
||||
|
||||
// Decreased Level Encounters
|
||||
if (enc.Any(slot => slot.WhiteFlute))
|
||||
return enc.All(slot => slot.Pressure)
|
||||
? new CheckResult(Severity.Valid, "Valid encounter at location (White Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, "Valid encounter at location (White Flute).", CheckIdentifier.Encounter);
|
||||
|
||||
// Increased Level Encounters
|
||||
if (enc.Any(slot => slot.BlackFlute))
|
||||
return enc.All(slot => slot.Pressure)
|
||||
? new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute).", CheckIdentifier.Encounter);
|
||||
|
||||
if (enc.Any(slot => slot.Pressure))
|
||||
return new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter);
|
||||
|
||||
return new CheckResult(Severity.Valid, "Valid encounter at location (DexNav).", CheckIdentifier.Encounter);
|
||||
}
|
||||
private CheckResult verifyEncounterStatic()
|
||||
{
|
||||
var s = (EncounterStatic)EncounterMatch;
|
||||
|
||||
// Re-parse relearn moves
|
||||
if (s.EggLocation != 60002 || vRelearn.Any(rl => !rl.Valid))
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
vRelearn[i] = pkm.RelearnMoves[i] != s.Relearn[i]
|
||||
? new CheckResult(Severity.Invalid, "Static encounter relearn move mismatch.", CheckIdentifier.RelearnMove)
|
||||
: new CheckResult(CheckIdentifier.RelearnMove);
|
||||
return new CheckResult(Severity.Valid, "Valid gift/static encounter.", CheckIdentifier.Encounter);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private CheckResult verifyEncounterTrade()
|
||||
{
|
||||
return new CheckResult(Severity.Valid, "Valid ingame trade.", CheckIdentifier.Encounter);
|
||||
}
|
||||
private CheckResult verifyEncounterG1()
|
||||
{
|
||||
// Since encounter matching is super weak due to limited stored data in the structure
|
||||
// Calculate all 3 at the same time and pick the best result (by species).
|
||||
// Favor special event move gifts as Static Encounters when applicable
|
||||
var s = Legal.getValidStaticEncounter(pkm, gen1Encounter: true);
|
||||
var e = Legal.getValidWildEncounters(pkm);
|
||||
var t = Legal.getValidIngameTrade(pkm, gen1Encounter: true);
|
||||
|
||||
const byte invalid = 255;
|
||||
|
||||
var sm = s?.Species ?? invalid;
|
||||
var em = e?.Min(slot => slot.Species) ?? invalid;
|
||||
var tm = t?.Species ?? invalid;
|
||||
|
||||
if (sm + em + tm == 3*invalid)
|
||||
return new CheckResult(Severity.Invalid, "Unknown encounter.", CheckIdentifier.Encounter);
|
||||
|
||||
if (s != null && s.Moves[0] != 0 && pkm.Moves.Contains(s.Moves[0]))
|
||||
{
|
||||
EncounterMatch = s;
|
||||
return verifyEncounterStatic();
|
||||
}
|
||||
if (em <= sm && em <= tm)
|
||||
{
|
||||
EncounterMatch = e;
|
||||
return verifyEncounterWild();
|
||||
}
|
||||
if (sm <= em && sm <= tm)
|
||||
{
|
||||
EncounterMatch = s;
|
||||
return verifyEncounterStatic();
|
||||
}
|
||||
if (tm <= sm && tm <= em)
|
||||
{
|
||||
EncounterMatch = t;
|
||||
return verifyEncounterTrade();
|
||||
}
|
||||
|
||||
// shouldn't ever hit, above 3*invalid check should abort
|
||||
Console.WriteLine($"Gen1 encounter fallthrough: {pkm.FileName}");
|
||||
return new CheckResult(Severity.Invalid, "Unknown encounter.", CheckIdentifier.Encounter);
|
||||
}
|
||||
private CheckResult verifyEncounter()
|
||||
{
|
||||
if (pkm.GenNumber < 6)
|
||||
return new CheckResult(Severity.NotImplemented, "Not Implemented.", CheckIdentifier.Encounter);
|
||||
|
||||
if (pkm.VC)
|
||||
if (pkm.VC || pkm.Format < 3)
|
||||
{
|
||||
int baseSpecies = Legal.getBaseSpecies(pkm);
|
||||
if ((pkm.VC1 && baseSpecies > Legal.MaxSpeciesID_1) ||
|
||||
(pkm.VC2 && baseSpecies > Legal.MaxSpeciesID_2))
|
||||
bool g1 = pkm.VC1 || pkm.Format == 1;
|
||||
|
||||
if ((g1 && baseSpecies > Legal.MaxSpeciesID_1) || (baseSpecies > Legal.MaxSpeciesID_2))
|
||||
return new CheckResult(Severity.Invalid, "VC: Unobtainable species.", CheckIdentifier.Encounter);
|
||||
|
||||
// Get EncounterMatch prior to parsing transporter legality
|
||||
var result = verifyEncounterG1();
|
||||
EncounterOriginal = EncounterMatch;
|
||||
|
||||
return verifyVCEncounter(baseSpecies);
|
||||
if (pkm.Format > 2) // transported to 7+
|
||||
AddLine(verifyVCEncounter(baseSpecies));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
if (pkm.WasLink)
|
||||
return verifyEncounterLink();
|
||||
|
||||
bool wasEvent = pkm.WasEvent || pkm.WasEventEgg;
|
||||
if (wasEvent)
|
||||
{
|
||||
// Should NOT be Fateful, and should be in Database
|
||||
EncounterLink enc = EncounterMatch as EncounterLink;
|
||||
if (enc == null)
|
||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: unable to find matching gift.", CheckIdentifier.Encounter);
|
||||
|
||||
if (pkm.XY && !enc.XY)
|
||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in XY.", CheckIdentifier.Encounter);
|
||||
if (pkm.AO && !enc.ORAS)
|
||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in ORAS.", CheckIdentifier.Encounter);
|
||||
if (pkm.SM && !enc.SM)
|
||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in SM.", CheckIdentifier.Encounter);
|
||||
|
||||
if (enc.Shiny != null && (bool)enc.Shiny ^ pkm.IsShiny)
|
||||
return new CheckResult(Severity.Invalid, "Shiny Link gift mismatch.", CheckIdentifier.Encounter);
|
||||
|
||||
return pkm.FatefulEncounter
|
||||
? new CheckResult(Severity.Invalid, "Invalid Link Gift: should not be Fateful Encounter.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, "Valid Link gift.", CheckIdentifier.Encounter);
|
||||
var result = verifyEncounterEvent();
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (pkm.WasEvent || pkm.WasEventEgg)
|
||||
|
||||
if (null != (EncounterMatch = Legal.getValidStaticEncounter(pkm)))
|
||||
{
|
||||
MysteryGift MatchedGift = EncounterMatch as MysteryGift;
|
||||
if (MatchedGift != null)
|
||||
return new CheckResult(Severity.Valid, $"Matches #{MatchedGift.CardID:0000} ({MatchedGift.CardTitle})", CheckIdentifier.Encounter);
|
||||
}
|
||||
var result = verifyEncounterStatic();
|
||||
if (result != null)
|
||||
return result;
|
||||
|
||||
EncounterMatch = Legal.getValidStaticEncounter(pkm);
|
||||
if (EncounterMatch != null)
|
||||
{
|
||||
// Re-parse relearn moves
|
||||
var s = (EncounterStatic)EncounterMatch;
|
||||
if (s.EggLocation != 60002 || vRelearn.Any(rl => !rl.Valid))
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
vRelearn[i] = pkm.RelearnMoves[i] != s.Relearn[i]
|
||||
? new CheckResult(Severity.Invalid, "Static encounter relearn move mismatch.", CheckIdentifier.RelearnMove)
|
||||
: new CheckResult(CheckIdentifier.RelearnMove);
|
||||
return new CheckResult(Severity.Valid, "Valid gift/static encounter.", CheckIdentifier.Encounter);
|
||||
}
|
||||
EncounterMatch = null; // Reset Encounter Object, test for remaining encounters
|
||||
}
|
||||
|
||||
EncounterMatch = null; // Reset object
|
||||
|
||||
if (pkm.WasEgg)
|
||||
{
|
||||
// Check Hatch Locations
|
||||
if (pkm.Met_Level != 1)
|
||||
return new CheckResult(Severity.Invalid, "Invalid met level, expected 1.", CheckIdentifier.Encounter);
|
||||
// Check species
|
||||
if (Legal.NoHatchFromEgg.Contains(pkm.Species))
|
||||
return new CheckResult(Severity.Invalid, "Species cannot be hatched from an egg.", CheckIdentifier.Encounter);
|
||||
if (pkm.IsEgg)
|
||||
{
|
||||
if (pkm.Egg_Location == 30002)
|
||||
return new CheckResult(Severity.Invalid, "Egg location shouldn't be 'traded' for an un-hatched egg.", CheckIdentifier.Encounter);
|
||||
return verifyEncounterEgg();
|
||||
|
||||
if (null != (EncounterMatch = Legal.getValidFriendSafari(pkm)))
|
||||
return verifyEncounterSafari();
|
||||
|
||||
if (null != (EncounterMatch = Legal.getValidWildEncounters(pkm)))
|
||||
return verifyEncounterWild();
|
||||
|
||||
if (null != (EncounterMatch = Legal.getValidIngameTrade(pkm)))
|
||||
return verifyEncounterTrade();
|
||||
|
||||
if (pkm.Met_Location == 30002)
|
||||
return new CheckResult(Severity.Valid, "Valid traded un-hatched egg.", CheckIdentifier.Encounter);
|
||||
return pkm.Met_Location == 0
|
||||
? new CheckResult(Severity.Valid, "Valid un-hatched egg.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Invalid location for un-hatched egg (expected no met location).", CheckIdentifier.Encounter);
|
||||
}
|
||||
if (pkm.XY)
|
||||
{
|
||||
if (pkm.Egg_Location == 318)
|
||||
return new CheckResult(Severity.Invalid, "Invalid X/Y egg location.", CheckIdentifier.Encounter);
|
||||
return Legal.ValidMet_XY.Contains(pkm.Met_Location)
|
||||
? new CheckResult(Severity.Valid, "Valid X/Y hatched egg.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Invalid X/Y location for hatched egg.", CheckIdentifier.Encounter);
|
||||
}
|
||||
if (pkm.AO)
|
||||
{
|
||||
return Legal.ValidMet_AO.Contains(pkm.Met_Location)
|
||||
? new CheckResult(Severity.Valid, "Valid OR/AS hatched egg.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Invalid OR/AS location for hatched egg.", CheckIdentifier.Encounter);
|
||||
}
|
||||
if (pkm.SM)
|
||||
{
|
||||
return Legal.ValidMet_SM.Contains(pkm.Met_Location)
|
||||
? new CheckResult(Severity.Valid, "Valid S/M hatched egg.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Invalid S/M location for hatched egg.", CheckIdentifier.Encounter);
|
||||
}
|
||||
return new CheckResult(Severity.Invalid, "Invalid location for hatched egg.", CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
EncounterMatch = Legal.getValidFriendSafari(pkm);
|
||||
if (EncounterMatch != null)
|
||||
{
|
||||
if (pkm.Species == 670 || pkm.Species == 671) // Floette
|
||||
if (!new[] {0, 1, 3}.Contains(pkm.AltForm)) // 0/1/3 - RBY
|
||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not valid color.", CheckIdentifier.Encounter);
|
||||
else if (pkm.Species == 710 || pkm.Species == 711) // Pumpkaboo
|
||||
if (pkm.AltForm != 1) // Average
|
||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not average sized.", CheckIdentifier.Encounter);
|
||||
else if (pkm.Species == 586) // Sawsbuck
|
||||
if (pkm.AltForm != 0)
|
||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not Spring form.", CheckIdentifier.Encounter);
|
||||
|
||||
return new CheckResult(Severity.Valid, "Valid Friend Safari encounter.", CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
EncounterMatch = Legal.getValidWildEncounters(pkm);
|
||||
if (EncounterMatch != null)
|
||||
{
|
||||
EncounterSlot[] enc = (EncounterSlot[])EncounterMatch;
|
||||
|
||||
if (enc.Any(slot => slot.Normal))
|
||||
return enc.All(slot => slot.Pressure)
|
||||
? new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, "Valid encounter at location.", CheckIdentifier.Encounter);
|
||||
|
||||
// Decreased Level Encounters
|
||||
if (enc.Any(slot => slot.WhiteFlute))
|
||||
return enc.All(slot => slot.Pressure)
|
||||
? new CheckResult(Severity.Valid, "Valid encounter at location (White Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, "Valid encounter at location (White Flute).", CheckIdentifier.Encounter);
|
||||
|
||||
// Increased Level Encounters
|
||||
if (enc.Any(slot => slot.BlackFlute))
|
||||
return enc.All(slot => slot.Pressure)
|
||||
? new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute).", CheckIdentifier.Encounter);
|
||||
|
||||
if (enc.Any(slot => slot.Pressure))
|
||||
return new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter);
|
||||
|
||||
return new CheckResult(Severity.Valid, "Valid encounter at location (DexNav).", CheckIdentifier.Encounter);
|
||||
}
|
||||
EncounterMatch = Legal.getValidIngameTrade(pkm);
|
||||
if (EncounterMatch != null)
|
||||
return new CheckResult(Severity.Valid, "Valid ingame trade.", CheckIdentifier.Encounter);
|
||||
|
||||
if (pkm.WasEvent || pkm.WasEventEgg)
|
||||
return new CheckResult(Severity.Invalid, "Unable to match to a Mystery Gift in the database.", CheckIdentifier.Encounter);
|
||||
return new CheckResult(Severity.Invalid, "Unknown encounter.", CheckIdentifier.Encounter);
|
||||
return wasEvent
|
||||
? new CheckResult(Severity.Invalid, "Unable to match to a Mystery Gift in the database.", CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, "Unknown encounter.", CheckIdentifier.Encounter);
|
||||
}
|
||||
private CheckResult verifyVCEncounter(int baseSpecies)
|
||||
{
|
||||
|
@ -546,6 +649,19 @@ namespace PKHeX.Core
|
|||
if ((pkm.VC1 && species > Legal.MaxSpeciesID_1) ||
|
||||
(pkm.VC2 && species > Legal.MaxSpeciesID_2))
|
||||
species = baseSpecies;
|
||||
|
||||
// Check existing EncounterMatch
|
||||
if ((EncounterOriginal ?? EncounterMatch) == null)
|
||||
return new CheckResult(Severity.Invalid, "Unable to match an encounter from origin game.", CheckIdentifier.Encounter);
|
||||
|
||||
var s = EncounterMatch as EncounterStatic;
|
||||
if (s != null && s.Version == GameVersion.SPECIAL)
|
||||
{
|
||||
bool exceptions = false;
|
||||
exceptions |= baseSpecies == 151 && pkm.TID == 22796;
|
||||
if (!exceptions)
|
||||
AddLine(new CheckResult(Severity.Invalid, "Special encounter is not available to Virtual Console games.", CheckIdentifier.Encounter));
|
||||
}
|
||||
|
||||
EncounterMatch = new EncounterStatic
|
||||
{
|
||||
|
@ -556,6 +672,7 @@ namespace PKHeX.Core
|
|||
Fateful = species == 151,
|
||||
Location = 30013,
|
||||
EggLocation = 0,
|
||||
Version = GameVersion.RBY
|
||||
};
|
||||
var ematch = (EncounterStatic) EncounterMatch;
|
||||
|
||||
|
@ -564,8 +681,12 @@ namespace PKHeX.Core
|
|||
if (pkm.Egg_Location != ematch.EggLocation)
|
||||
return new CheckResult(Severity.Invalid, "Should not have an egg location.", CheckIdentifier.Encounter);
|
||||
|
||||
if (species == 150 && pkm.Moves.Contains(6))
|
||||
return new CheckResult(Severity.Invalid, "Mewtwo cannot be transferred while knowing Pay Day.", CheckIdentifier.Encounter);
|
||||
|
||||
return new CheckResult(CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private void verifyLevel()
|
||||
{
|
||||
MysteryGift MatchedGift = EncounterMatch as MysteryGift;
|
||||
|
@ -832,13 +953,26 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
if (pkm.GenNumber >= 6 && abilities[pkm.AbilityNumber >> 1] != pkm.Ability)
|
||||
AddLine(Severity.Invalid, "Ability does not match ability number.", CheckIdentifier.Ability);
|
||||
else if (pkm.GenNumber <= 5 && pkm.Version != (int)GameVersion.CXD && abilities[0] != abilities[1] && pkm.PIDAbility != abilval)
|
||||
AddLine(Severity.Invalid, "Ability does not match PID.", CheckIdentifier.Ability);
|
||||
if (3 <= pkm.Format && pkm.Format <= 5) // 3-5
|
||||
{
|
||||
if (pkm.Version != (int) GameVersion.CXD && abilities[0] != abilities[1] && pkm.PIDAbility != abilval)
|
||||
{
|
||||
AddLine(Severity.Invalid, "Ability does not match PID.", CheckIdentifier.Ability);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
AddLine(Severity.Valid, "Ability matches ability number.", CheckIdentifier.Ability);
|
||||
{
|
||||
if (abilities[pkm.AbilityNumber >> 1] != pkm.Ability)
|
||||
{
|
||||
AddLine(Severity.Invalid, "Ability does not match ability number.", CheckIdentifier.Ability);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AddLine(Severity.Valid, "Ability matches ability number.", CheckIdentifier.Ability);
|
||||
}
|
||||
|
||||
private void verifyBall()
|
||||
{
|
||||
if (pkm.GenNumber < 6)
|
||||
|
@ -914,29 +1048,8 @@ namespace PKHeX.Core
|
|||
|
||||
if (pkm.WasEgg)
|
||||
{
|
||||
if (pkm.GenNumber < 6) // No inheriting Balls
|
||||
{
|
||||
if (pkm.Ball != 0x04)
|
||||
AddLine(Severity.Invalid, "Ball should be Pokéball.", CheckIdentifier.Ball);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pkm.Ball == 0x01) // Master Ball
|
||||
{ AddLine(Severity.Invalid, "Master Ball on egg origin.", CheckIdentifier.Ball); return; }
|
||||
if (pkm.Ball == 0x10) // Cherish Ball
|
||||
{ AddLine(Severity.Invalid, "Cherish Ball on non-event.", CheckIdentifier.Ball); return; }
|
||||
if (pkm.Ball == 0x04) // Poké Ball
|
||||
{ AddLine(Severity.Valid, "Standard Poké Ball.", CheckIdentifier.Ball); return; }
|
||||
|
||||
switch (pkm.GenNumber)
|
||||
{
|
||||
case 6: // Gen6 Inheritance Rules
|
||||
verifyEggBallGen6();
|
||||
return;
|
||||
case 7: // Gen7 Inheritance Rules
|
||||
verifyEggBallGen7();
|
||||
return;
|
||||
}
|
||||
verifyBallEgg();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pkm.Ball == 0x04) // Poké Ball
|
||||
|
@ -947,7 +1060,35 @@ namespace PKHeX.Core
|
|||
|
||||
AddLine(Severity.Invalid, "No ball check satisfied, assuming illegal.", CheckIdentifier.Ball);
|
||||
}
|
||||
private void verifyEggBallGen6()
|
||||
private void verifyBallEgg()
|
||||
{
|
||||
if (pkm.GenNumber < 6) // No inheriting Balls
|
||||
{
|
||||
if (pkm.Ball != 0x04) // Must be Pokéball -- no ball inheritance.
|
||||
AddLine(Severity.Invalid, "Ball should be Pokéball.", CheckIdentifier.Ball);
|
||||
else
|
||||
AddLine(Severity.Valid, "Pokéball on egg.", CheckIdentifier.Ball);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pkm.Ball == 0x01) // Master Ball
|
||||
{ AddLine(Severity.Invalid, "Master Ball on egg origin.", CheckIdentifier.Ball); return; }
|
||||
if (pkm.Ball == 0x10) // Cherish Ball
|
||||
{ AddLine(Severity.Invalid, "Cherish Ball on non-event.", CheckIdentifier.Ball); return; }
|
||||
if (pkm.Ball == 0x04) // Poké Ball
|
||||
{ AddLine(Severity.Valid, "Standard Poké Ball.", CheckIdentifier.Ball); return; }
|
||||
|
||||
switch (pkm.GenNumber)
|
||||
{
|
||||
case 6: // Gen6 Inheritance Rules
|
||||
verifyBallEggGen6();
|
||||
return;
|
||||
case 7: // Gen7 Inheritance Rules
|
||||
verifyBallEggGen7();
|
||||
return;
|
||||
}
|
||||
}
|
||||
private void verifyBallEggGen6()
|
||||
{
|
||||
if (pkm.Gender == 2) // Genderless
|
||||
{
|
||||
|
@ -1047,8 +1188,7 @@ namespace PKHeX.Core
|
|||
? "Ball unobtainable in origin generation."
|
||||
: "No ball check satisfied, assuming illegal.", CheckIdentifier.Ball);
|
||||
}
|
||||
|
||||
private void verifyEggBallGen7()
|
||||
private void verifyBallEggGen7()
|
||||
{
|
||||
var Lineage = Legal.getLineage(pkm).ToArray();
|
||||
if (722 <= pkm.Species && pkm.Species <= 730) // G7 Starters
|
||||
|
@ -1111,17 +1251,10 @@ namespace PKHeX.Core
|
|||
}
|
||||
if (0x02 <= pkm.Ball && pkm.Ball <= 0x0C) // Don't worry, Ball # 0x05 was already checked.
|
||||
{
|
||||
if (Legal.Ban_Gen3Ball_AllowG7.Contains(pkm.Species))
|
||||
{
|
||||
if (pkm.AbilityNumber == 4)
|
||||
AddLine(Severity.Invalid, "Ball not possible for species with hidden ability.", CheckIdentifier.Ball);
|
||||
else
|
||||
AddLine(Severity.Valid, "Obtainable capture for Gen3 Ball.", CheckIdentifier.Ball);
|
||||
}
|
||||
else if (Legal.Ban_Gen3Ball.Contains(pkm.Species))
|
||||
if (Legal.Ban_Gen3Ball_7.Contains(pkm.Species))
|
||||
AddLine(Severity.Invalid, "Unobtainable capture for Gen3 Ball.", CheckIdentifier.Ball);
|
||||
else
|
||||
AddLine(Severity.Valid, "Obtainable capture for Gen3Ball.", CheckIdentifier.Ball);
|
||||
AddLine(Severity.Valid, "Obtainable capture for Gen3 Ball.", CheckIdentifier.Ball);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1154,6 +1287,7 @@ namespace PKHeX.Core
|
|||
? "Ball unobtainable in origin generation."
|
||||
: "No ball check satisfied, assuming illegal.", CheckIdentifier.Ball);
|
||||
}
|
||||
|
||||
private CheckResult verifyHistory()
|
||||
{
|
||||
if (!Encounter.Valid)
|
||||
|
@ -1255,7 +1389,7 @@ namespace PKHeX.Core
|
|||
if (pkm.Species != 350) // Milotic
|
||||
return new CheckResult(Severity.Invalid, "Untraded -- requires a trade evolution.", CheckIdentifier.History);
|
||||
if (pkm.CNT_Beauty < 170) // Beauty Contest Stat Requirement
|
||||
return new CheckResult(Severity.Invalid, "Untraded -- Beauty is not high enough for Levelup Evolution.", CheckIdentifier.History);
|
||||
return new CheckResult(Severity.Invalid, "Untraded -- Beauty is not high enough for Level-up Evolution.", CheckIdentifier.History);
|
||||
if (pkm.CurrentLevel == 1)
|
||||
return new CheckResult(Severity.Invalid, "Untraded -- Beauty is high enough but still Level 1.", CheckIdentifier.History);
|
||||
}
|
||||
|
@ -1286,14 +1420,14 @@ namespace PKHeX.Core
|
|||
if (pkm.Species != 350) // Milotic
|
||||
return new CheckResult(Severity.Invalid, "Untraded -- requires a trade evolution.", CheckIdentifier.History);
|
||||
if (pkm.CNT_Beauty < 170) // Beauty Contest Stat Requirement
|
||||
return new CheckResult(Severity.Invalid, "Untraded -- Beauty is not high enough for Levelup Evolution.", CheckIdentifier.History);
|
||||
return new CheckResult(Severity.Invalid, "Untraded -- Beauty is not high enough for Level-up Evolution.", CheckIdentifier.History);
|
||||
if (pkm.CurrentLevel == 1)
|
||||
return new CheckResult(Severity.Invalid, "Untraded -- Beauty is high enough but still Level 1.", CheckIdentifier.History);
|
||||
}
|
||||
}
|
||||
else // Is Traded
|
||||
{
|
||||
if (pkm.HT_Memory == 0 && pkm.Format == 6)
|
||||
if (pkm.Format == 6 && pkm.HT_Memory == 0)
|
||||
return new CheckResult(Severity.Invalid, "Memory -- missing Handling Trainer Memory.", CheckIdentifier.History);
|
||||
}
|
||||
|
||||
|
@ -1335,27 +1469,22 @@ namespace PKHeX.Core
|
|||
break;
|
||||
}
|
||||
int matchingMoveMemory = Array.IndexOf(Legal.MoveSpecificMemories[0], m);
|
||||
if (matchingMoveMemory != -1 && pkm.Species != 235 && !Legal.getCanLearnMachineMove(pkm, Legal.MoveSpecificMemories[1][matchingMoveMemory]))
|
||||
{
|
||||
if (matchingMoveMemory != -1 && pkm.Species != 235 && !Legal.getCanLearnMachineMove(pkm, Legal.MoveSpecificMemories[1][matchingMoveMemory], 6))
|
||||
return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot learn this move.", CheckIdentifier.Memory);
|
||||
}
|
||||
|
||||
if (m == 6 && !Legal.LocationsWithPKCenter[0].Contains(t))
|
||||
{
|
||||
return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Location doesn't have a Pokemon Center.", CheckIdentifier.Memory);
|
||||
}
|
||||
|
||||
if (m == 21) // {0} saw {2} carrying {1} on its back. {4} that {3}.
|
||||
{
|
||||
if (!Legal.getCanLearnMachineMove(new PK6 {Species = t, EXP = PKX.getEXP(100, t)}, 19))
|
||||
if (!Legal.getCanLearnMachineMove(new PK6 {Species = t, EXP = PKX.getEXP(100, t)}, 19, 6))
|
||||
return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Argument Species cannot learn Fly.", CheckIdentifier.Memory);
|
||||
}
|
||||
if ((m == 16 || m == 48) && (t == 0 || !Legal.getCanKnowMove(pkm, t, GameVersion.Any)))
|
||||
{
|
||||
|
||||
if ((m == 16 || m == 48) && (t == 0 || !Legal.getCanKnowMove(pkm, t, 6)))
|
||||
return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot know this move.", CheckIdentifier.Memory);
|
||||
}
|
||||
if (m == 49 && (t == 0 || !Legal.getCanRelearnMove(pkm, t, GameVersion.Any))) // {0} was able to remember {2} at {1}'s instruction. {4} that {3}.
|
||||
{
|
||||
|
||||
if (m == 49 && (t == 0 || !Legal.getCanRelearnMove(pkm, t, 6))) // {0} was able to remember {2} at {1}'s instruction. {4} that {3}.
|
||||
return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot relearn this move.", CheckIdentifier.Memory);
|
||||
}
|
||||
|
||||
return new CheckResult(Severity.Valid, resultPrefix + "Memory is valid.", CheckIdentifier.Memory);
|
||||
}
|
||||
private void verifyOTMemory()
|
||||
|
@ -1466,7 +1595,7 @@ namespace PKHeX.Core
|
|||
if (!History.Valid)
|
||||
return;
|
||||
|
||||
if (pkm.GenNumber == 7)
|
||||
if (pkm.GenNumber == 7 || pkm.GenNumber == 1)
|
||||
{
|
||||
bool check = pkm.VC1 || pkm.HT_Memory != 0;
|
||||
if (!check)
|
||||
|
@ -1574,11 +1703,10 @@ namespace PKHeX.Core
|
|||
case 25: // Pikachu
|
||||
if (pkm.Format == 6 && pkm.AltForm != 0 ^ EncounterType == typeof(EncounterStatic))
|
||||
{
|
||||
if (EncounterType == typeof(EncounterStatic))
|
||||
AddLine(Severity.Invalid, "Cosplay Pikachu cannot have the default form.", CheckIdentifier.Form);
|
||||
else
|
||||
AddLine(Severity.Invalid, "Only Cosplay Pikachu can have this form.", CheckIdentifier.Form);
|
||||
|
||||
string msg = EncounterType == typeof (EncounterStatic)
|
||||
? "Cosplay Pikachu cannot have the default form."
|
||||
: "Only Cosplay Pikachu can have this form.";
|
||||
AddLine(Severity.Invalid, msg, CheckIdentifier.Form);
|
||||
return;
|
||||
}
|
||||
if (pkm.Format == 7 && pkm.AltForm != 0 ^ EncounterIsMysteryGift)
|
||||
|
@ -1612,6 +1740,19 @@ namespace PKHeX.Core
|
|||
AddLine(Severity.Valid, "Held item matches Form.", CheckIdentifier.Form);
|
||||
}
|
||||
break;
|
||||
case 649: // Genesect
|
||||
{
|
||||
int item = pkm.HeldItem;
|
||||
int form = 0;
|
||||
if (116 <= item && item <= 119)
|
||||
form = item - 115;
|
||||
|
||||
if (form != pkm.AltForm)
|
||||
AddLine(Severity.Invalid, "Held item does not match Form.", CheckIdentifier.Form);
|
||||
else
|
||||
AddLine(Severity.Valid, "Held item matches Form.", CheckIdentifier.Form);
|
||||
}
|
||||
break;
|
||||
case 658: // Greninja
|
||||
if (pkm.AltForm > 1) // Ash Battle Bond active
|
||||
{
|
||||
|
@ -1784,10 +1925,10 @@ namespace PKHeX.Core
|
|||
CheckResult[] res = new CheckResult[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
res[i] = new CheckResult(CheckIdentifier.Move);
|
||||
if (pkm.GenNumber < 6 || pkm.VC1)
|
||||
return res;
|
||||
|
||||
var validMoves = Legal.getValidMoves(pkm, EvoChain).ToArray();
|
||||
|
||||
var validMoves = Legal.getValidMoves(pkm, EvoChainsAllGens, Tutor: false, Machine: false).ToArray();
|
||||
var validTMHM = Legal.getValidMoves(pkm, EvoChainsAllGens, Tutor: false, MoveReminder: false).ToArray();
|
||||
var validTutor = Legal.getValidMoves(pkm, EvoChainsAllGens, Machine: false, MoveReminder: false).ToArray();
|
||||
if (pkm.Species == 235) // Smeargle
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
|
@ -1800,19 +1941,8 @@ namespace PKHeX.Core
|
|||
int[] RelearnMoves = pkm.RelearnMoves;
|
||||
foreach (MysteryGift mg in EventGiftMatch)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (Moves[i] == Legal.Struggle)
|
||||
res[i] = new CheckResult(Severity.Invalid, "Invalid Move: Struggle.", CheckIdentifier.Move);
|
||||
else if (validMoves.Contains(Moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, Moves[i] == 0 ? "Empty" : "Level-up.", CheckIdentifier.Move);
|
||||
else if (RelearnMoves.Contains(Moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, Moves[i] == 0 ? "Empty" : "Relearn Move.", CheckIdentifier.Move) { Flag = true };
|
||||
else if (mg.Moves.Contains(Moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, "Wonder Card Non-Relearn Move.", CheckIdentifier.Move);
|
||||
else
|
||||
res[i] = new CheckResult(Severity.Invalid, "Invalid Move.", CheckIdentifier.Move);
|
||||
}
|
||||
int[] SpecialMoves = mg.Moves;
|
||||
res = parseMoves(Moves, validMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves);
|
||||
if (res.Any(r => !r.Valid))
|
||||
continue;
|
||||
|
||||
|
@ -1824,21 +1954,12 @@ namespace PKHeX.Core
|
|||
else
|
||||
{
|
||||
int[] RelearnMoves = pkm.RelearnMoves;
|
||||
MysteryGift MatchedGift = EncounterMatch as MysteryGift;
|
||||
int[] GiftMoves = MatchedGift?.Moves ?? new int[0];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (Moves[i] == Legal.Struggle)
|
||||
res[i] = new CheckResult(Severity.Invalid, "Invalid Move: Struggle.", CheckIdentifier.Move);
|
||||
else if (validMoves.Contains(Moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, Moves[i] == 0 ? "Empty" : "Level-up.", CheckIdentifier.Move);
|
||||
else if (RelearnMoves.Contains(Moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, Moves[i] == 0 ? "Empty" : "Relearn Move.", CheckIdentifier.Move) { Flag = true };
|
||||
else if (GiftMoves.Contains(Moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, "Wonder Card Non-Relearn Move.", CheckIdentifier.Move);
|
||||
else
|
||||
res[i] = new CheckResult(Severity.Invalid, "Invalid Move.", CheckIdentifier.Move);
|
||||
}
|
||||
int[] SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ??
|
||||
(EncounterMatch as EncounterStatic)?.Moves ??
|
||||
(EncounterMatch as EncounterTrade)?.Moves ??
|
||||
new int[0];
|
||||
|
||||
res = parseMoves(Moves, validMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves);
|
||||
}
|
||||
if (Moves[0] == 0) // None
|
||||
res[0] = new CheckResult(Severity.Invalid, "Invalid Move.", CheckIdentifier.Move);
|
||||
|
@ -1854,6 +1975,28 @@ namespace PKHeX.Core
|
|||
|
||||
return res;
|
||||
}
|
||||
private static CheckResult[] parseMoves(int[] moves, int[] learn, int[] relearn, int[] tmhm, int[] tutor, int[] special)
|
||||
{
|
||||
CheckResult[] res = new CheckResult[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (moves[i] == 0)
|
||||
res[i] = new CheckResult(Severity.Valid, "Empty", CheckIdentifier.Move);
|
||||
else if (learn.Contains(moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, "Level-up.", CheckIdentifier.Move);
|
||||
else if (relearn.Contains(moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, "Relearn Move.", CheckIdentifier.Move) { Flag = true };
|
||||
else if (tmhm.Contains(moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, "TM/HM.", CheckIdentifier.Move);
|
||||
else if (tutor.Contains(moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, "Tutor.", CheckIdentifier.Move);
|
||||
else if (special.Contains(moves[i]))
|
||||
res[i] = new CheckResult(Severity.Valid, "Special Non-Relearn Move.", CheckIdentifier.Move);
|
||||
else
|
||||
res[i] = new CheckResult(Severity.Invalid, "Invalid Move.", CheckIdentifier.Move);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
private CheckResult[] verifyRelearn()
|
||||
{
|
||||
RelearnBase = null;
|
||||
|
@ -1907,7 +2050,7 @@ namespace PKHeX.Core
|
|||
|
||||
if (pkm.WasEgg && !Legal.NoHatchFromEgg.Contains(pkm.Species))
|
||||
{
|
||||
GameVersion[] Games = { GameVersion.XY };
|
||||
GameVersion[] Games = {};
|
||||
switch (pkm.GenNumber)
|
||||
{
|
||||
case 6:
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
{
|
||||
public int Species;
|
||||
public int Level;
|
||||
public int MinLevel;
|
||||
public bool RequiresLvlUp;
|
||||
public int Form = -1;
|
||||
public int Flag = -1;
|
||||
|
||||
public DexLevel Copy(int lvl)
|
||||
{
|
||||
return new DexLevel {Species = Species, Level = lvl, Form = Form, Flag = -1};
|
||||
return new DexLevel {Species = Species, Level = lvl, MinLevel = MinLevel, RequiresLvlUp = RequiresLvlUp, Form = Form, Flag = -1};
|
||||
}
|
||||
public bool Matches(int species, int form)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -24,6 +25,117 @@ namespace PKHeX.Core
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static EncounterSlot1[] getSlots1_GW(byte[] data, ref int ofs, SlotType t)
|
||||
{
|
||||
int rate = data[ofs++];
|
||||
return rate == 0 ? new EncounterSlot1[0] : readSlots(data, ref ofs, 10, t, rate);
|
||||
}
|
||||
private static EncounterSlot1[] getSlots1_F(byte[] data, ref int ofs)
|
||||
{
|
||||
int count = data[ofs++];
|
||||
return readSlots(data, ref ofs, count, SlotType.Super_Rod, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RBY Format Slot Getter from data.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing complete slot data table.</param>
|
||||
/// <param name="ofs">Offset to start reading from.</param>
|
||||
/// <param name="count">Amount of slots to read.</param>
|
||||
/// <param name="t">Type of encounter slot.</param>
|
||||
/// <param name="rate">Slot type encounter rate.</param>
|
||||
/// <returns>Array of encounter slots.</returns>
|
||||
private static EncounterSlot1[] readSlots(byte[] data, ref int ofs, int count, SlotType t, int rate)
|
||||
{
|
||||
EncounterSlot1[] slots = new EncounterSlot1[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int lvl = data[ofs++];
|
||||
int spec = data[ofs++];
|
||||
|
||||
slots[i] = new EncounterSlot1
|
||||
{
|
||||
LevelMax = lvl,
|
||||
LevelMin = lvl,
|
||||
Species = spec,
|
||||
Type = t,
|
||||
Rate = rate,
|
||||
};
|
||||
}
|
||||
return slots;
|
||||
}
|
||||
public static EncounterArea[] getArray1_GW(byte[] data)
|
||||
{
|
||||
// RBY Format
|
||||
var ptr = new int[255];
|
||||
int count = 0;
|
||||
for (int i = 0; i < ptr.Length; i++)
|
||||
{
|
||||
ptr[i] = BitConverter.ToInt16(data, i*2);
|
||||
if (ptr[i] != -1)
|
||||
continue;
|
||||
|
||||
count = i;
|
||||
break;
|
||||
}
|
||||
|
||||
EncounterArea[] areas = new EncounterArea[count];
|
||||
for (int i = 0; i < areas.Length; i++)
|
||||
{
|
||||
var grass = getSlots1_GW(data, ref ptr[i], SlotType.Grass);
|
||||
var water = getSlots1_GW(data, ref ptr[i], SlotType.Surf);
|
||||
areas[i] = new EncounterArea
|
||||
{
|
||||
Location = i,
|
||||
Slots = grass.Concat(water).ToArray()
|
||||
};
|
||||
}
|
||||
return areas.Where(area => area.Slots.Any()).ToArray();
|
||||
}
|
||||
public static EncounterArea[] getArray1_FY(byte[] data)
|
||||
{
|
||||
const int size = 9;
|
||||
int count = data.Length/size;
|
||||
EncounterArea[] areas = new EncounterArea[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int ofs = i*size + 1;
|
||||
areas[i] = new EncounterArea
|
||||
{
|
||||
Location = data[i*size + 0],
|
||||
Slots = readSlots(data, ref ofs, 4, SlotType.Super_Rod, -1)
|
||||
};
|
||||
}
|
||||
return areas;
|
||||
}
|
||||
public static EncounterArea[] getArray1_F(byte[] data)
|
||||
{
|
||||
var ptr = new int[255];
|
||||
var map = new int[255];
|
||||
int count = 0;
|
||||
for (int i = 0; i < ptr.Length; i++)
|
||||
{
|
||||
map[i] = data[i*3 + 0];
|
||||
if (map[i] == 0xFF)
|
||||
{
|
||||
count = i;
|
||||
break;
|
||||
}
|
||||
ptr[i] = BitConverter.ToInt16(data, i * 3 + 1);
|
||||
}
|
||||
|
||||
EncounterArea[] areas = new EncounterArea[count];
|
||||
for (int i = 0; i < areas.Length; i++)
|
||||
{
|
||||
areas[i] = new EncounterArea
|
||||
{
|
||||
Location = map[i],
|
||||
Slots = getSlots1_F(data, ref ptr[i])
|
||||
};
|
||||
}
|
||||
return areas;
|
||||
}
|
||||
public static EncounterArea[] getArray(byte[][] entries)
|
||||
{
|
||||
if (entries == null)
|
||||
|
@ -35,5 +147,4 @@ namespace PKHeX.Core
|
|||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,28 @@
|
|||
Pressure = template.Pressure;
|
||||
}
|
||||
|
||||
public string Name => "Wild Encounter";
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
const string wild = "Wild Encounter";
|
||||
if (Type == SlotType.Any)
|
||||
return wild;
|
||||
return wild + " " + $"{Type.ToString().Replace("_", " ")}";
|
||||
}
|
||||
}
|
||||
}
|
||||
public class EncounterSlot1 : EncounterSlot
|
||||
{
|
||||
public int Rate;
|
||||
public EncounterSlot1() { }
|
||||
public EncounterSlot1(EncounterSlot1 template)
|
||||
{
|
||||
Species = template.Species;
|
||||
LevelMax = template.LevelMax;
|
||||
LevelMin = template.LevelMin;
|
||||
Type = template.Type;
|
||||
Rate = template.Rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
public int Form = 0;
|
||||
public bool? Shiny = null; // false = never, true = always, null = possible
|
||||
public int[] Relearn = new int[4];
|
||||
public int[] Moves = new int[4];
|
||||
public int Gender = -1;
|
||||
public int EggLocation = 0;
|
||||
public Nature Nature = Nature.Random;
|
||||
|
@ -25,6 +26,15 @@
|
|||
public bool RibbonWishing = false;
|
||||
public bool SkipFormCheck = false;
|
||||
|
||||
public string Name => "Static Encounter";
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
const string game = "Static Encounter";
|
||||
if (Version == GameVersion.Any)
|
||||
return game;
|
||||
return game + " " + $"({Version})";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,18 @@ namespace PKHeX.Core
|
|||
MaxSpeciesTree = maxSpeciesTree;
|
||||
switch (game)
|
||||
{
|
||||
case GameVersion.SM:
|
||||
Entries.AddRange(data.Select(d => new EvolutionSet7(d)));
|
||||
case GameVersion.RBY:
|
||||
Entries = EvolutionSet1.getArray(data[0], maxSpeciesTree);
|
||||
break;
|
||||
case GameVersion.GSC:
|
||||
Entries = EvolutionSet2.getArray(data[0], maxSpeciesTree);
|
||||
break;
|
||||
case GameVersion.ORAS:
|
||||
Entries.AddRange(data.Select(d => new EvolutionSet6(d)));
|
||||
break;
|
||||
case GameVersion.SM:
|
||||
Entries.AddRange(data.Select(d => new EvolutionSet7(d)));
|
||||
break;
|
||||
}
|
||||
|
||||
// Create Lineages
|
||||
|
@ -32,7 +38,7 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < Entries.Count; i++)
|
||||
Lineage[i] = new EvolutionLineage();
|
||||
if (Game == GameVersion.ORAS)
|
||||
Array.Resize(ref Lineage, maxSpeciesTree + 1);
|
||||
Array.Resize(ref Lineage, MaxSpeciesTree + 1);
|
||||
|
||||
// Populate Lineages
|
||||
for (int i = 1; i < Lineage.Length; i++)
|
||||
|
@ -162,6 +168,94 @@ namespace PKHeX.Core
|
|||
{
|
||||
public EvolutionMethod[] PossibleEvolutions;
|
||||
}
|
||||
public class EvolutionSet1 : EvolutionSet
|
||||
{
|
||||
private static EvolutionMethod getMethod(byte[] data, ref int offset)
|
||||
{
|
||||
switch (data[offset])
|
||||
{
|
||||
case 1: // Level
|
||||
var m1 = new EvolutionMethod
|
||||
{
|
||||
Method = 1, // Level Up
|
||||
Level = data[offset + 1],
|
||||
Species = data[offset + 2]
|
||||
};
|
||||
offset += 3;
|
||||
return m1;
|
||||
case 2: // Use Item
|
||||
var m2 = new EvolutionMethod
|
||||
{
|
||||
Method = 8, // Use Item
|
||||
Argument = data[offset + 1],
|
||||
// 1
|
||||
Species = data[offset + 3],
|
||||
};
|
||||
offset += 4;
|
||||
return m2;
|
||||
case 3: // Trade
|
||||
var m3 = new EvolutionMethod
|
||||
{
|
||||
Method = 5, // Trade
|
||||
// 1
|
||||
Species = data[offset + 2]
|
||||
};
|
||||
offset += 3;
|
||||
return m3;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static List<EvolutionSet> getArray(byte[] data, int maxSpecies)
|
||||
{
|
||||
var evos = new List<EvolutionSet>();
|
||||
int offset = 0;
|
||||
for (int i = 0; i <= maxSpecies; i++)
|
||||
{
|
||||
var m = new List<EvolutionMethod>();
|
||||
while (data[offset] != 0)
|
||||
m.Add(getMethod(data, ref offset));
|
||||
++offset;
|
||||
evos.Add(new EvolutionSet1 { PossibleEvolutions = m.ToArray() });
|
||||
}
|
||||
return evos;
|
||||
}
|
||||
}
|
||||
public class EvolutionSet2 : EvolutionSet
|
||||
{
|
||||
private static EvolutionMethod getMethod(byte[] data, ref int offset)
|
||||
{
|
||||
int method = data[offset];
|
||||
int arg = data[offset + 1];
|
||||
int species = data[offset + 2];
|
||||
offset += 3;
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case 1: /* Level Up */ return new EvolutionMethod { Method = 1, Species = species, Level = arg };
|
||||
case 2: /* Use Item */ return new EvolutionMethod { Method = 8, Species = species, Argument = arg };
|
||||
case 3: /* Trade */ return new EvolutionMethod { Method = 5, Species = species };
|
||||
case 4: /*Friendship*/ return new EvolutionMethod { Method = 1, Species = species };
|
||||
case 5: /* Stats */
|
||||
// species is currently stat ID, we don't care about evo type as stats can be changed after evo
|
||||
return new EvolutionMethod { Method = 1, Species = data[offset++], Level = arg }; // Tyrogue stats
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static List<EvolutionSet> getArray(byte[] data, int maxSpecies)
|
||||
{
|
||||
var evos = new List<EvolutionSet>();
|
||||
int offset = 0;
|
||||
for (int i = 0; i <= maxSpecies; i++)
|
||||
{
|
||||
var m = new List<EvolutionMethod>();
|
||||
while (data[offset] != 0)
|
||||
m.Add(getMethod(data, ref offset));
|
||||
++offset;
|
||||
evos.Add(new EvolutionSet2 { PossibleEvolutions = m.ToArray() });
|
||||
}
|
||||
return evos;
|
||||
}
|
||||
}
|
||||
public class EvolutionSet6 : EvolutionSet
|
||||
{
|
||||
private const int SIZE = 6;
|
||||
|
@ -172,7 +266,7 @@ namespace PKHeX.Core
|
|||
PossibleEvolutions = new EvolutionMethod[data.Length / SIZE];
|
||||
for (int i = 0; i < data.Length; i += SIZE)
|
||||
{
|
||||
PossibleEvolutions[i/SIZE] = new EvolutionMethod
|
||||
var evo = new EvolutionMethod
|
||||
{
|
||||
Method = BitConverter.ToUInt16(data, i + 0),
|
||||
Argument = BitConverter.ToUInt16(data, i + 2),
|
||||
|
@ -183,8 +277,10 @@ namespace PKHeX.Core
|
|||
};
|
||||
|
||||
// Argument is used by both Level argument and Item/Move/etc. Clear if appropriate.
|
||||
if (argEvos.Contains(PossibleEvolutions[i/SIZE].Method))
|
||||
PossibleEvolutions[i/SIZE].Level = 0;
|
||||
if (argEvos.Contains(evo.Method))
|
||||
evo.Level = 0;
|
||||
|
||||
PossibleEvolutions[i/SIZE] = evo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,6 +455,7 @@ namespace PKHeX.Core
|
|||
continue;
|
||||
|
||||
oneValid = true;
|
||||
updateMinValues(dl, evo);
|
||||
int species = evo.Species;
|
||||
|
||||
// Gen7 Personal Formes -- unmap the forme personal entry ID to the actual species ID since species are consecutive
|
||||
|
@ -366,7 +463,7 @@ namespace PKHeX.Core
|
|||
species = pkm.Species - Chain.Count + i;
|
||||
|
||||
dl.Add(evo.GetDexLevel(species, lvl));
|
||||
|
||||
|
||||
if (evo.RequiresLevelUp)
|
||||
lvl--;
|
||||
break;
|
||||
|
@ -379,8 +476,43 @@ namespace PKHeX.Core
|
|||
if (dl.Any(d => d.Species <= maxSpeciesOrigin) && dl.Last().Species > maxSpeciesOrigin)
|
||||
dl.RemoveAt(dl.Count - 1);
|
||||
|
||||
// Last species is the wild/hatched species, the minimum is 1 because it has not evolved from previous species
|
||||
dl.Last().MinLevel = 1;
|
||||
dl.Last().RequiresLvlUp = false;
|
||||
return dl;
|
||||
}
|
||||
private static void updateMinValues(IReadOnlyCollection<DexLevel> dl, EvolutionMethod evo)
|
||||
{
|
||||
var last = dl.Last();
|
||||
if (evo.Level == 0) // Evolutions like elemental stones, trade, etc
|
||||
{
|
||||
if (!evo.RequiresLevelUp)
|
||||
last.MinLevel = 1;
|
||||
else
|
||||
{
|
||||
// Evolutions like frienship, pichu -> pikachu, eevee -> umbreon, etc
|
||||
last.MinLevel = 2;
|
||||
|
||||
var first = dl.First();
|
||||
if (dl.Count > 1 && !first.RequiresLvlUp)
|
||||
first.MinLevel = 2; // Raichu from Pikachu would have minimum level 1, but with Pichu included Raichu minimum level is 2
|
||||
}
|
||||
}
|
||||
else // level up evolutions
|
||||
{
|
||||
last.MinLevel = evo.Level;
|
||||
|
||||
var first = dl.First();
|
||||
if (dl.Count > 1)
|
||||
{
|
||||
if (first.MinLevel < evo.Level && !first.RequiresLvlUp)
|
||||
first.MinLevel = evo.Level; // Pokemon like Nidoqueen, its minimum level is Nidorina minimum level
|
||||
if (first.MinLevel <= evo.Level && first.RequiresLvlUp)
|
||||
first.MinLevel = evo.Level + 1; // Pokemon like Crobat, its minimum level is Golbat minimum level + 1
|
||||
}
|
||||
}
|
||||
last.RequiresLvlUp = evo.RequiresLevelUp;
|
||||
}
|
||||
}
|
||||
public class EvolutionStage
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
|
@ -17,6 +18,35 @@ namespace PKHeX.Core
|
|||
return Moves;
|
||||
}
|
||||
}
|
||||
|
||||
public class Learnset1 : Learnset
|
||||
{
|
||||
private Learnset1(byte[] data, ref int offset)
|
||||
{
|
||||
var moves = new List<int>();
|
||||
var levels = new List<int>();
|
||||
while (data[offset] != 0)
|
||||
{
|
||||
levels.Add(data[offset++]);
|
||||
moves.Add(data[offset++]);
|
||||
}
|
||||
++offset;
|
||||
|
||||
Moves = moves.ToArray();
|
||||
Levels = levels.ToArray();
|
||||
Count = Moves.Length;
|
||||
}
|
||||
public static Learnset[] getArray(byte[] input, int maxSpecies)
|
||||
{
|
||||
var data = new Learnset[maxSpecies + 1];
|
||||
|
||||
int offset = 0;
|
||||
for (int s = 0; s < data.Length; s++)
|
||||
data[s] = new Learnset1(input, ref offset);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
public class Learnset6 : Learnset
|
||||
{
|
||||
private Learnset6(byte[] data)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace PKHeX.Core
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public static partial class Legal
|
||||
{
|
||||
|
@ -197,6 +199,7 @@
|
|||
695, 696, 697, 698, 699, 700, 701, 702, 703,
|
||||
719,
|
||||
};
|
||||
internal static readonly int[] InvalidSketch = new[] { 165, 448 }.Concat(Z_Moves).ToArray(); // Struggle & Chatter
|
||||
|
||||
public static readonly int[] Legends =
|
||||
{
|
||||
|
@ -219,7 +222,7 @@
|
|||
#region Games
|
||||
|
||||
public static readonly int[] Games_7vc2 = { 39, 40, 41 }; // Gold, Silver, Crystal
|
||||
public static readonly int[] Games_7vc1 = { 35, 36, 37, 38 }; // Red, Blue, Green, Yellow
|
||||
public static readonly int[] Games_7vc1 = { 35, 36, 37, 38 }; // Red, Green, Blue, Yellow
|
||||
public static readonly int[] Games_7go = { 34 };
|
||||
public static readonly int[] Games_7sm = { 30, 31 };
|
||||
public static readonly int[] Games_6xy = { 24, 25 };
|
||||
|
|
|
@ -30,5 +30,129 @@ namespace PKHeX.Core
|
|||
};
|
||||
|
||||
internal static readonly int[] TransferSpeciesDefaultAbility_1 = {92, 93, 94, 109, 110, 151};
|
||||
|
||||
internal static readonly int[] TMHM_RBY =
|
||||
{
|
||||
005, 013, 014, 018, 025, 092, 032, 034, 036, 038,
|
||||
061, 055, 058, 059, 063, 006, 066, 068, 069, 099,
|
||||
072, 076, 082, 085, 087, 089, 090, 091, 094, 100,
|
||||
102, 104, 115, 117, 118, 120, 121, 126, 129, 130,
|
||||
135, 138, 143, 156, 086, 149, 153, 157, 161, 164,
|
||||
|
||||
015, 019, 057, 070, 148
|
||||
};
|
||||
internal static readonly int[] WildPokeBalls1 = {4};
|
||||
|
||||
internal static readonly EncounterStatic[] Encounter_RBY =
|
||||
{
|
||||
new EncounterStatic { Species = 001, Level = 05, Version = GameVersion.RBY }, // Bulbasaur
|
||||
new EncounterStatic { Species = 004, Level = 05, Version = GameVersion.RBY }, // Charmander
|
||||
new EncounterStatic { Species = 007, Level = 05, Version = GameVersion.RBY }, // Squirtle
|
||||
new EncounterStatic { Species = 025, Level = 05, Version = GameVersion.YW }, // Pikachu
|
||||
|
||||
// Game Corner
|
||||
new EncounterStatic { Species = 030, Level = 17, Version = GameVersion.RBY }, // Nidorina (Red Game Corner)
|
||||
new EncounterStatic { Species = 033, Level = 17, Version = GameVersion.RBY }, // Nidorino (Blue[EN] / Green[JP] Game Corner)
|
||||
new EncounterStatic { Species = 035, Level = 08, Version = GameVersion.RBY }, // Clefairy (Red Game Corner)
|
||||
new EncounterStatic { Species = 036, Level = 24, Version = GameVersion.RBY }, // Clefable (Blue[JP] Game Corner)
|
||||
new EncounterStatic { Species = 037, Level = 18, Version = GameVersion.RBY }, // Vulpix (Yellow Game Corner)
|
||||
new EncounterStatic { Species = 040, Level = 22, Version = GameVersion.RBY }, // Wigglytuff (Yellow Game Corner)
|
||||
new EncounterStatic { Species = 063, Level = 06, Version = GameVersion.RBY }, // Abra (Blue[EN] / Green[JP] Game Corner)
|
||||
new EncounterStatic { Species = 116, Level = 18, Version = GameVersion.RBY }, // Horsea (Blue[JP] Game Corner)
|
||||
new EncounterStatic { Species = 123, Level = 25, Version = GameVersion.RBY }, // Scyther (Red Game Corner)
|
||||
new EncounterStatic { Species = 127, Level = 20, Version = GameVersion.RBY }, // Pinsir (Blue[EN] / Green[JP] Game Corner)
|
||||
new EncounterStatic { Species = 137, Level = 18, Version = GameVersion.RBY }, // Porygon (Blue[EN] / Green[JP] Game Corner)
|
||||
new EncounterStatic { Species = 147, Level = 18, Version = GameVersion.RBY }, // Dratini (Red Game Corner)
|
||||
new EncounterStatic { Species = 148, Level = 30, Version = GameVersion.RBY }, // Dragonair (Blue[JP] Game Corner)
|
||||
|
||||
// Lower level less ideal matches; best match is from above.
|
||||
// new EncounterStatic { Species = 025, Level = 12 }, // Pikachu (Blue[JP] Game Corner)
|
||||
// new EncounterStatic { Species = 035, Level = 12 }, // Clefairy (Blue[EN] / Green[JP] Game Corner)
|
||||
// new EncounterStatic { Species = 063, Level = 09 }, // Abra (Red Game Corner)
|
||||
// new EncounterStatic { Species = 063, Level = 08 }, // Abra (Blue[JP] Game Corner)
|
||||
// new EncounterStatic { Species = 063, Level = 15 }, // Abra (Yellow Game Corner)
|
||||
// new EncounterStatic { Species = 123, Level = 30 }, // Scyther (Yellow Game Corner)
|
||||
// new EncounterStatic { Species = 127, Level = 30 }, // Pinsir (Yellow Game Corner)
|
||||
// new EncounterStatic { Species = 137, Level = 22 }, // Porygon (Blue[JP] Game Corner)
|
||||
// new EncounterStatic { Species = 137, Level = 26 }, // Porygon (Red Game Corner)
|
||||
// new EncounterStatic { Species = 137, Level = 26 }, // Porygon (Yellow Game Corner)
|
||||
// new EncounterStatic { Species = 147, Level = 24 }, // Dratini (Blue[EN] / Green[JP] Game Corner)
|
||||
|
||||
new EncounterStatic { Species = 129, Level = 05, Version = GameVersion.RBY }, // Magikarp
|
||||
new EncounterStatic { Species = 143, Level = 30, Version = GameVersion.RBY }, // Snorlax
|
||||
new EncounterStatic { Species = 106, Level = 30, Version = GameVersion.RBY }, // Hitmonlee
|
||||
new EncounterStatic { Species = 107, Level = 30, Version = GameVersion.RBY }, // Hitmonchan
|
||||
|
||||
new EncounterStatic { Species = 131, Level = 15, Version = GameVersion.RBY }, // Lapras
|
||||
new EncounterStatic { Species = 138, Level = 30, Version = GameVersion.RBY }, // Omanyte
|
||||
new EncounterStatic { Species = 140, Level = 30, Version = GameVersion.RBY }, // Kabuto
|
||||
new EncounterStatic { Species = 142, Level = 30, Version = GameVersion.RBY }, // Aerodactyl
|
||||
|
||||
new EncounterStatic { Species = 144, Level = 50, Version = GameVersion.RBY }, // Articuno
|
||||
new EncounterStatic { Species = 145, Level = 50, Version = GameVersion.RBY }, // Zapdos
|
||||
new EncounterStatic { Species = 146, Level = 50, Version = GameVersion.RBY }, // Moltres
|
||||
|
||||
new EncounterStatic { Species = 150, Level = 70, Version = GameVersion.RBY }, // Mewtwo
|
||||
|
||||
new EncounterStatic { Species = 133, Level = 25, Version = GameVersion.RBY }, // Eevee
|
||||
|
||||
// Yellow Only -- duplicate encounters with a higher level
|
||||
// new EncounterStatic { Species = 133, Level = 25, Version = GameVersion.YW }, // Eevee (Celadon City)
|
||||
// new EncounterStatic { Species = 001, Level = 10, Version = GameVersion.YW }, // Bulbasaur (Cerulean City)
|
||||
// new EncounterStatic { Species = 004, Level = 10, Version = GameVersion.YW }, // Charmander (Route 24)
|
||||
// new EncounterStatic { Species = 007, Level = 10, Version = GameVersion.YW }, // Squirtle (Vermillion City)
|
||||
|
||||
new EncounterStatic { Species = 054, Level = 15, Moves = new [] { 133, 10 }, Version = GameVersion.SPECIAL }, // Stadium Psyduck (Amnesia)
|
||||
new EncounterStatic { Species = 151, Level = 5, IVs = new [] {15,15,15,15,15,15}, Version = GameVersion.SPECIAL }, // Event Mew
|
||||
};
|
||||
internal static readonly EncounterTrade[] TradeGift_RBY =
|
||||
{
|
||||
// Species & Minimum level (legal) possible to acquire at.
|
||||
new EncounterTrade { Species = 122, Level = 06 }, // Mr. Mime - Game Corner Abra
|
||||
new EncounterTrade { Species = 032, Level = 02 }, // Nidoran♂ - Wild Nidoran♀
|
||||
new EncounterTrade { Species = 029, Level = 02 }, // Nidoran♀ - Wild Nidoran♂
|
||||
new EncounterTrade { Species = 030, Level = 16 }, // Nidorina - Evolve Nidorino
|
||||
new EncounterTrade { Species = 108, Level = 15 }, // Lickitung - Surf Slowbro
|
||||
new EncounterTrade { Species = 124, Level = 15 }, // Jynx - Fish Poliwhirl (GSC: 10)
|
||||
new EncounterTrade { Species = 083, Level = 02 }, // Farfetch’d - Wild Spearow
|
||||
new EncounterTrade { Species = 101, Level = 03 }, // Electrode - Wild Raichu
|
||||
new EncounterTrade { Species = 114, Level = 13 }, // Tangela - Wild Venonat (GSC: 5)
|
||||
new EncounterTrade { Species = 086, Level = 28 }, // Seel - Wild Ponyta (GSC: 6)
|
||||
|
||||
//new EncounterTrade { Species = 122, Level = 03 }, // Mr. Mime - Wild Jigglypuff
|
||||
new EncounterTrade { Species = 060, Level = 02 }, // Poliwag - Wild Rattata
|
||||
new EncounterTrade { Species = 115, Level = 42 }, // Kangaskhan - Evolve Rhydon (GSC: 30)
|
||||
new EncounterTrade { Species = 128, Level = 28 }, // Tauros - Evolve Persian (GSC: 18)
|
||||
new EncounterTrade { Species = 093, Level = 20 }, // Haunter - Trade Machoke (GSC: 10)
|
||||
//new EncounterTrade { Species = 083, Level = 02 }, // Farfetch’d - Wild Pidgey
|
||||
new EncounterTrade { Species = 075, Level = 16 }, // Graveler - Evolve Kadabra (GSC: 15)
|
||||
new EncounterTrade { Species = 079, Level = 22 }, // Slowpoke - Wild Seel
|
||||
new EncounterTrade { Species = 098, Level = 15 }, // Krabby - Wild Growlithe (GSC: 5)
|
||||
|
||||
//new EncounterTrade { Species = 122, Level = 08 }, // Mr. Mime - Wild Clefairy (GSC: 6)
|
||||
new EncounterTrade { Species = 067, Level = 20 }, // Machoke - Wild Cubone (GSC: 10)
|
||||
new EncounterTrade { Species = 051, Level = 15 }, // Dugtrio - Trade Lickitung
|
||||
new EncounterTrade { Species = 047, Level = 13 }, // Parasect - Trade Tangela
|
||||
new EncounterTrade { Species = 112, Level = 15 }, // Rhydon - Surf Golduck (GSC: 10)
|
||||
new EncounterTrade { Species = 087, Level = 15 }, // Dewgong - Wild Growlithe (GSC: 5)
|
||||
new EncounterTrade { Species = 089, Level = 25 }, // Muk - Wild Kangaskhan (GSC: 14)
|
||||
};
|
||||
internal static readonly EncounterArea FishOldGood_RBY = new EncounterArea { Location = -1, Slots = new EncounterSlot[]
|
||||
{
|
||||
new EncounterSlot1 {Species = 129, LevelMin = 05, LevelMax = 05, Type = SlotType.Old_Rod, Rate = -1, }, // Magikarp
|
||||
new EncounterSlot1 {Species = 118, LevelMin = 10, LevelMax = 10, Type = SlotType.Good_Rod, Rate = -1, }, // Goldeen
|
||||
new EncounterSlot1 {Species = 060, LevelMin = 10, LevelMax = 10, Type = SlotType.Good_Rod, Rate = -1, }, // Poliwag
|
||||
}};
|
||||
|
||||
internal static readonly int[] FutureEvolutionsGen1 =
|
||||
{
|
||||
169,182,186,196,197,199,208,212,230,233,242,462,463,464,465,466,467,470,471,474,700
|
||||
};
|
||||
|
||||
internal static readonly int[] FutureEvolutionsGen1_Gen2LevelUp =
|
||||
{
|
||||
169,196,197,242
|
||||
};
|
||||
//Crobat Espeon Umbreon Blissey
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace PKHeX.Core
|
|||
3, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 51, 52, 53, 57, 60, 62, 63, 64, 65, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 117, 118, 119, 121, 122, 123, 124, 125, 126, 131, 132, 138, 139, 140, 143, 144, 146, 150, 151, 152, 156, 158, 163, 168, 169, 170, 172, 173, 174, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189
|
||||
};
|
||||
internal static readonly ushort[] Pouch_Ball_GSC = {
|
||||
1, 2, 4, 5, 157, 159, 160, 161, 164, 165, 166, 167
|
||||
1, 2, 4, 5, 157, 159, 160, 161, 164, 165, 166
|
||||
};
|
||||
internal static readonly ushort[] Pouch_Key_GS = {
|
||||
7, 54, 55, 58, 59, 61, 66, 67, 68 , 69, 71, 127, 128, 130, 133, 134, 175, 178
|
||||
|
@ -35,5 +35,15 @@ namespace PKHeX.Core
|
|||
10, 05, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 15, 15, 15,
|
||||
10, 00, 00, 00, 00
|
||||
};
|
||||
internal static readonly int[] WildPokeBalls2 = { 4 };
|
||||
|
||||
internal static readonly int[] FutureEvolutionsGen2 =
|
||||
{
|
||||
424,429,430,461,462,463,464,465,466,467,468,469,470,471,472,473,474,700
|
||||
};
|
||||
internal static readonly EncounterTrade[] TradeGift_GSC =
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,5 +81,18 @@ namespace PKHeX.Core
|
|||
580, 581, 582, 583, 584, 585, 586, 587, 588, 589,
|
||||
590, 591, 592, 593
|
||||
};
|
||||
internal static readonly int[] WildPokeBalls3 = {1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12};
|
||||
|
||||
internal static readonly int[] FutureEvolutionsGen3 =
|
||||
{
|
||||
407,424,429,430,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,700
|
||||
};
|
||||
|
||||
internal static readonly int[] FutureEvolutionsGen3_LevelUp =
|
||||
{
|
||||
424, 461, 462, 463, 465, 469, 470, 471, 472, 473, 476
|
||||
};
|
||||
// Ambipom Weavile Magnezone Lickilicky Tangrowth
|
||||
// Yanmega Leafeon Glaceon Mamoswine Gliscor Probopass
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,5 +118,22 @@ namespace PKHeX.Core
|
|||
10, 15, 20, 15, 10, 10, 10, 20, 05, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20,
|
||||
10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05,
|
||||
};
|
||||
internal static readonly int[] WildPokeBalls4_DPPt =
|
||||
{
|
||||
1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
// Cherish ball not usable
|
||||
};
|
||||
internal static readonly int[] WildPokeBalls4_HGSS =
|
||||
{
|
||||
1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
// Cherish ball not usable
|
||||
17, 18, 19, 20, 21, 22,
|
||||
// Comp Ball not usable in wild
|
||||
};
|
||||
|
||||
internal static readonly int[] FutureEvolutionsGen4 =
|
||||
{
|
||||
700
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,5 +82,17 @@ namespace PKHeX.Core
|
|||
15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 20, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05,
|
||||
05, 10, 05, 05, 15, 10, 05, 05, 05,
|
||||
};
|
||||
internal static readonly int[] WildPokeBalls5 =
|
||||
{
|
||||
1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
// Cherish ball not usable
|
||||
// HGSS balls not usable
|
||||
// Dream ball not usable in wild
|
||||
};
|
||||
|
||||
internal static readonly int[] FutureEvolutionsGen5 =
|
||||
{
|
||||
700
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,17 +225,7 @@ namespace PKHeX.Core
|
|||
};
|
||||
|
||||
#endregion
|
||||
|
||||
// Legality
|
||||
internal const int Struggle = 165;
|
||||
internal const int Chatter = 448;
|
||||
internal static readonly int[] InvalidSketch =
|
||||
{
|
||||
// Regular Moves
|
||||
Struggle, Chatter
|
||||
// Z-Moves
|
||||
// TODO
|
||||
};
|
||||
|
||||
internal static readonly int[] EggLocations = {60002, 30002};
|
||||
internal static readonly int[] ValidMet_XY =
|
||||
{
|
||||
|
@ -633,6 +623,9 @@ namespace PKHeX.Core
|
|||
577, // Solosis
|
||||
582, // Vanillite
|
||||
595, // Joltik
|
||||
|
||||
// Via Incense Breeding
|
||||
298, 360, 406, 433, 438, 439, 440, 446, 458,
|
||||
};
|
||||
internal static readonly int[] Ban_DreamHidden =
|
||||
{
|
||||
|
|
|
@ -470,17 +470,9 @@ namespace PKHeX.Core
|
|||
599, // Klink
|
||||
622, // Golett
|
||||
};
|
||||
internal static readonly int[] Ban_Gen3Ball_AllowG7 =
|
||||
internal static readonly int[] Ban_Gen3Ball_7 =
|
||||
{
|
||||
252, 255, 258, //1 - Treeko, Torchic, Mudkip
|
||||
253, 256, 259, //2
|
||||
254, 257, 260, //3
|
||||
387, 390, 393, //1 - Turtwig, Chimchar, Piplup
|
||||
388, 391, 394, //2
|
||||
389, 392, 395, //3
|
||||
495, 498, 501, //1 - Snivy, Tepig, Oshawott
|
||||
496, 499, 502, //2
|
||||
497, 500, 503, //3
|
||||
566, 567, 696, 697, 698, 699 // Fossil Only obtain
|
||||
};
|
||||
internal static readonly int[] Ban_Gen4Ball_7 =
|
||||
{
|
||||
|
@ -1173,7 +1165,7 @@ namespace PKHeX.Core
|
|||
new EncounterStatic { Species = 422, Relearn = new[] {124}}, // Shellos: Sludge
|
||||
new EncounterStatic { Species = 131, Relearn = new[] {419}}, // Lapras: Avalanche
|
||||
new EncounterStatic { Species = 102, Relearn = new[] {335,285,384,381,267,246}},// Exeggcute: Block, Skill Swap, Power Swap, Lucky Chant, Nature Power, Ancient Power
|
||||
new EncounterStatic { Species = 123, Relearn = new[] {211,501,432,179,68}}, // Scyther: Steel Wing, Quick Guard, Defog, Reversal, Counter
|
||||
new EncounterStatic { Species = 123, Relearn = new[] {211,501,432,179,68}}, // Scyther: Steel Wing, Quick Guard, Defog, Reversal, Counter
|
||||
new EncounterStatic { Species = 198, Relearn = new[] {375,260,195}}, // Murkrow: Psycho Shift, Flatter, Perish Song
|
||||
new EncounterStatic { Species = 447, Relearn = new[] {299}}, // Riolu: Blaze Kick
|
||||
new EncounterStatic { Species = 147, Relearn = new[] {245}}, // Dratini: Extreme Speed
|
||||
|
|
|
@ -21,31 +21,31 @@ namespace PKHeX.Core
|
|||
public bool PL_enabled { get { return PL_Flag != 0; } set { PL_Flag = (byte)(value ? 1 << 7 : 0); } }
|
||||
|
||||
//Name of data source
|
||||
public string Origin_app {
|
||||
public string Origin_app {
|
||||
get { return Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0x01, 0x6E)); }
|
||||
set { Encoding.Unicode.GetBytes(value.PadRight(54 + 1, '\0')).CopyTo(Data, 0x01); } }
|
||||
|
||||
//Pokemon transfer flags?
|
||||
public uint PKM1_flags {
|
||||
get { return BitConverter.ToUInt32(Data, 0x99); }
|
||||
get { return BitConverter.ToUInt32(Data, 0x99); }
|
||||
set { BitConverter.GetBytes(value).CopyTo(Data, 0x99); } }
|
||||
public uint PKM2_flags {
|
||||
get { return BitConverter.ToUInt32(Data, 0x141); }
|
||||
get { return BitConverter.ToUInt32(Data, 0x141); }
|
||||
set { BitConverter.GetBytes(value).CopyTo(Data, 0x141); } }
|
||||
public uint PKM3_flags {
|
||||
get { return BitConverter.ToUInt32(Data, 0x1E9); }
|
||||
get { return BitConverter.ToUInt32(Data, 0x1E9); }
|
||||
set { BitConverter.GetBytes(value).CopyTo(Data, 0x1E9); } }
|
||||
public uint PKM4_flags {
|
||||
get { return BitConverter.ToUInt32(Data, 0x291); }
|
||||
get { return BitConverter.ToUInt32(Data, 0x291); }
|
||||
set { BitConverter.GetBytes(value).CopyTo(Data, 0x291); } }
|
||||
public uint PKM5_flags {
|
||||
get { return BitConverter.ToUInt32(Data, 0x339); }
|
||||
get { return BitConverter.ToUInt32(Data, 0x339); }
|
||||
set { BitConverter.GetBytes(value).CopyTo(Data, 0x339); } }
|
||||
public uint PKM6_flags {
|
||||
get { return BitConverter.ToUInt32(Data, 0x3E1); }
|
||||
get { return BitConverter.ToUInt32(Data, 0x3E1); }
|
||||
set { BitConverter.GetBytes(value).CopyTo(Data, 0x3E1); } }
|
||||
|
||||
public uint[] Flags
|
||||
public uint[] Flags
|
||||
{
|
||||
get { return new[] {PKM1_flags, PKM2_flags, PKM3_flags, PKM4_flags, PKM5_flags, PKM6_flags}; }
|
||||
set
|
||||
|
@ -58,29 +58,29 @@ namespace PKHeX.Core
|
|||
if (value.Length > 5) PKM6_flags = value[5];
|
||||
}
|
||||
}
|
||||
|
||||
//Pokémon
|
||||
|
||||
public PL6_PKM poke1 {
|
||||
get { return new PL6_PKM(Data.Skip(0x9D).Take(PL6_PKM.Size).ToArray()); }
|
||||
|
||||
//Pokémon
|
||||
|
||||
public PL6_PKM poke1 {
|
||||
get { return new PL6_PKM(Data.Skip(0x9D).Take(PL6_PKM.Size).ToArray()); }
|
||||
set { value.Data.CopyTo(Data, 0x9D); } }
|
||||
public PL6_PKM poke2 {
|
||||
get { return new PL6_PKM(Data.Skip(0x145).Take(PL6_PKM.Size).ToArray()); }
|
||||
public PL6_PKM poke2 {
|
||||
get { return new PL6_PKM(Data.Skip(0x145).Take(PL6_PKM.Size).ToArray()); }
|
||||
set { value.Data.CopyTo(Data, 0x145); } }
|
||||
public PL6_PKM poke3 {
|
||||
get { return new PL6_PKM(Data.Skip(0x1ED).Take(PL6_PKM.Size).ToArray()); }
|
||||
public PL6_PKM poke3 {
|
||||
get { return new PL6_PKM(Data.Skip(0x1ED).Take(PL6_PKM.Size).ToArray()); }
|
||||
set { value.Data.CopyTo(Data, 0x1ED); } }
|
||||
public PL6_PKM poke4 {
|
||||
get { return new PL6_PKM(Data.Skip(0x295).Take(PL6_PKM.Size).ToArray()); }
|
||||
public PL6_PKM poke4 {
|
||||
get { return new PL6_PKM(Data.Skip(0x295).Take(PL6_PKM.Size).ToArray()); }
|
||||
set { value.Data.CopyTo(Data, 0x295); } }
|
||||
public PL6_PKM poke5 {
|
||||
get { return new PL6_PKM(Data.Skip(0x33D).Take(PL6_PKM.Size).ToArray()); }
|
||||
public PL6_PKM poke5 {
|
||||
get { return new PL6_PKM(Data.Skip(0x33D).Take(PL6_PKM.Size).ToArray()); }
|
||||
set { value.Data.CopyTo(Data, 0x33D); } }
|
||||
public PL6_PKM poke6 {
|
||||
get { return new PL6_PKM(Data.Skip(0x3E5).Take(PL6_PKM.Size).ToArray()); }
|
||||
public PL6_PKM poke6 {
|
||||
get { return new PL6_PKM(Data.Skip(0x3E5).Take(PL6_PKM.Size).ToArray()); }
|
||||
set { value.Data.CopyTo(Data, 0x3E5); } }
|
||||
|
||||
public PL6_PKM[] Pokes
|
||||
public PL6_PKM[] Pokes
|
||||
{
|
||||
get { return new[] {poke1, poke2, poke3, poke4, poke5, poke6}; }
|
||||
set
|
||||
|
@ -132,7 +132,7 @@ namespace PKHeX.Core
|
|||
get { return BitConverter.ToUInt16(Data, 0x49F); }
|
||||
set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x49F); } }
|
||||
|
||||
public int[] Items
|
||||
public int[] Items
|
||||
{
|
||||
get { return new[] {Item_1, Item_2, Item_3, Item_4, Item_5, Item_6}; }
|
||||
set
|
||||
|
@ -145,8 +145,8 @@ namespace PKHeX.Core
|
|||
if (value.Length > 5) Item_6 = value[5];
|
||||
}
|
||||
}
|
||||
|
||||
public int[] Quantities
|
||||
|
||||
public int[] Quantities
|
||||
{
|
||||
get { return new[] {Quantity_1, Quantity_2, Quantity_3, Quantity_4, Quantity_5, Quantity_6}; }
|
||||
set
|
||||
|
@ -169,7 +169,7 @@ namespace PKHeX.Core
|
|||
public int Pokemiles {
|
||||
get { return BitConverter.ToUInt16(Data, 0x4A3); }
|
||||
set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x4A3); } }
|
||||
}
|
||||
}
|
||||
|
||||
public class PL6_PKM : IEncounterable
|
||||
{
|
||||
|
@ -242,7 +242,7 @@ namespace PKHeX.Core
|
|||
public int MetLocation {
|
||||
get { return BitConverter.ToUInt16(Data, 0x3E); }
|
||||
set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x3F); } }
|
||||
public int MetLevel {
|
||||
public int MetLevel {
|
||||
get { return Data[0x40]; }
|
||||
set { Data[0x40] = (byte)value; } }
|
||||
|
||||
|
|
|
@ -278,6 +278,7 @@ namespace PKHeX.Core
|
|||
return null;
|
||||
|
||||
int currentLevel = Level > 0 ? Level : (int)(Util.rnd32()%100 + 1);
|
||||
var pi = PersonalTable.AO[Species];
|
||||
PK6 pk = new PK6
|
||||
{
|
||||
Species = Species,
|
||||
|
@ -286,11 +287,11 @@ namespace PKHeX.Core
|
|||
SID = SID,
|
||||
Met_Level = currentLevel,
|
||||
Nature = Nature != 0xFF ? Nature : (int)(Util.rnd32() % 25),
|
||||
Gender = PersonalTable.AO[Species].Gender == 255 ? 2 : (Gender != 3 ? Gender : PersonalTable.AO[Species].RandomGender),
|
||||
Gender = Gender != 3 ? Gender : pi.RandomGender,
|
||||
AltForm = Form,
|
||||
EncryptionConstant = EncryptionConstant == 0 ? Util.rnd32() : EncryptionConstant,
|
||||
Version = OriginGame == 0 ? SAV.Game : OriginGame,
|
||||
Language = Language == 0 ? SAV.Language : Language,
|
||||
EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.rnd32(),
|
||||
Version = OriginGame != 0 ? OriginGame : SAV.Game,
|
||||
Language = Language != 0 ? Language : SAV.Language,
|
||||
Ball = Ball,
|
||||
Country = SAV.Country,
|
||||
Region = SAV.SubRegion,
|
||||
|
@ -334,7 +335,7 @@ namespace PKHeX.Core
|
|||
RibbonChampionNational = RibbonChampionNational,
|
||||
RibbonChampionWorld = RibbonChampionWorld,
|
||||
|
||||
OT_Friendship = PersonalTable.AO[Species].BaseFriendship,
|
||||
OT_Friendship = pi.BaseFriendship,
|
||||
OT_Intensity = OT_Intensity,
|
||||
OT_Memory = OT_Memory,
|
||||
OT_TextVar = OT_TextVar,
|
||||
|
|
|
@ -108,10 +108,32 @@ namespace PKHeX.Core
|
|||
public override int Item {
|
||||
get { return BitConverter.ToUInt16(Data, 0x68); }
|
||||
set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x68); } }
|
||||
|
||||
public int GetItem(int index)
|
||||
{
|
||||
return BitConverter.ToUInt16(Data, 0x68 + 0x4*index);
|
||||
}
|
||||
|
||||
public void SetItem(int index, ushort item)
|
||||
{
|
||||
BitConverter.GetBytes(item).CopyTo(Data, 0x68 + 4*index);
|
||||
}
|
||||
|
||||
public override int Quantity {
|
||||
get { return BitConverter.ToUInt16(Data, 0x6A); }
|
||||
set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6A); } }
|
||||
|
||||
|
||||
public int GetQuantity(int index)
|
||||
{
|
||||
return BitConverter.ToUInt16(Data, 0x6A + 0x4 * index);
|
||||
}
|
||||
|
||||
public void SetQuantity(int index, ushort quantity)
|
||||
{
|
||||
BitConverter.GetBytes(quantity).CopyTo(Data, 0x6A + 4 * index);
|
||||
}
|
||||
|
||||
|
||||
// Pokémon Properties
|
||||
public override bool IsPokémon { get { return CardType == 0; } set { if (value) CardType = 0; } }
|
||||
public override bool IsShiny => PIDType == 2;
|
||||
|
@ -297,6 +319,7 @@ namespace PKHeX.Core
|
|||
|
||||
int currentLevel = Level > 0 ? Level : (int)(Util.rnd32()%100 + 1);
|
||||
int metLevel = MetLevel > 0 ? MetLevel : currentLevel;
|
||||
var pi = PersonalTable.SM[Species];
|
||||
PK7 pk = new PK7
|
||||
{
|
||||
Species = Species,
|
||||
|
@ -305,11 +328,11 @@ namespace PKHeX.Core
|
|||
SID = SID,
|
||||
Met_Level = metLevel,
|
||||
Nature = Nature != 0xFF ? Nature : (int)(Util.rnd32() % 25),
|
||||
Gender = PersonalTable.AO[Species].Gender == 255 ? 2 : (Gender != 3 ? Gender : PersonalTable.AO[Species].RandomGender),
|
||||
Gender = Gender != 3 ? Gender : pi.RandomGender,
|
||||
AltForm = Form,
|
||||
EncryptionConstant = EncryptionConstant == 0 ? Util.rnd32() : EncryptionConstant,
|
||||
Version = OriginGame == 0 ? SAV.Game : OriginGame,
|
||||
Language = Language == 0 ? SAV.Language : Language,
|
||||
EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.rnd32(),
|
||||
Version = OriginGame != 0 ? OriginGame : SAV.Game,
|
||||
Language = Language != 0 ? Language : SAV.Language,
|
||||
Ball = Ball,
|
||||
Country = SAV.Country,
|
||||
Region = SAV.SubRegion,
|
||||
|
@ -353,7 +376,7 @@ namespace PKHeX.Core
|
|||
RibbonChampionNational = RibbonChampionNational,
|
||||
RibbonChampionWorld = RibbonChampionWorld,
|
||||
|
||||
OT_Friendship = PersonalTable.AO[Species].BaseFriendship,
|
||||
OT_Friendship = pi.BaseFriendship,
|
||||
OT_Intensity = OT_Intensity,
|
||||
OT_Memory = OT_Memory,
|
||||
OT_TextVar = OT_TextVar,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{B4EFF030-C75A-49F9-A4BC-738D1B61C4AF}</ProjectGuid>
|
||||
|
@ -261,17 +261,31 @@
|
|||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<None Include="Resources\byte\eggmove_sm.pkl" />
|
||||
<None Include="Resources\byte\encounter_blue.pkl" />
|
||||
<None Include="Resources\byte\encounter_mn.pkl" />
|
||||
<None Include="Resources\byte\encounter_mn_sos.pkl" />
|
||||
<None Include="Resources\byte\encounter_rb_f.pkl" />
|
||||
<None Include="Resources\byte\encounter_red.pkl" />
|
||||
<None Include="Resources\byte\encounter_sn.pkl" />
|
||||
<None Include="Resources\byte\encounter_sn_sos.pkl" />
|
||||
<None Include="Resources\byte\encounter_yellow.pkl" />
|
||||
<None Include="Resources\byte\encounter_yellow_f.pkl" />
|
||||
<None Include="Resources\byte\evos_gsc.pkl" />
|
||||
<None Include="Resources\byte\evos_rby.pkl" />
|
||||
<None Include="Resources\byte\evos_sm.pkl" />
|
||||
<None Include="Resources\byte\fashion_f_sm" />
|
||||
<None Include="Resources\byte\fashion_f_sm_illegal" />
|
||||
<None Include="Resources\byte\fashion_m_sm" />
|
||||
<None Include="Resources\byte\fashion_m_sm_illegal" />
|
||||
<None Include="Resources\byte\lvlmove_c.pkl" />
|
||||
<None Include="Resources\byte\lvlmove_gs.pkl" />
|
||||
<None Include="Resources\byte\lvlmove_rb.pkl" />
|
||||
<None Include="Resources\byte\lvlmove_rby.pkl" />
|
||||
<None Include="Resources\byte\lvlmove_sm.pkl" />
|
||||
<None Include="Resources\byte\lvlmove_y.pkl" />
|
||||
<None Include="Resources\byte\personal_rb" />
|
||||
<None Include="Resources\byte\personal_sm" />
|
||||
<None Include="Resources\byte\personal_y" />
|
||||
<None Include="Resources\byte\wc7.pkl" />
|
||||
<None Include="Resources\byte\wc7full.pkl" />
|
||||
<None Include="Resources\text\gen3\text_gsc_00000_es.txt" />
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core
|
|||
// Internal use only
|
||||
protected internal byte[] otname;
|
||||
protected internal byte[] nick;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.RBY[Species];
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.Y[Species];
|
||||
|
||||
public byte[] OT_Name_Raw => (byte[])otname.Clone();
|
||||
public byte[] Nickname_Raw => (byte[])nick.Clone();
|
||||
|
@ -259,7 +259,7 @@ namespace PKHeX.Core
|
|||
public override int OT_Friendship { get { return 0; } set { } }
|
||||
public override int OT_Gender { get { return 0; } set { } }
|
||||
public override int Ball { get { return 0; } set { } }
|
||||
public override int Version { get { return 0; } set { } }
|
||||
public override int Version { get { return (int)GameVersion.RBY; } set { } }
|
||||
public override int SID { get { return 0; } set { } }
|
||||
public override int PKRS_Strain { get { return 0; } set { } }
|
||||
public override int PKRS_Days { get { return 0; } set { } }
|
||||
|
@ -353,6 +353,11 @@ namespace PKHeX.Core
|
|||
Geo1_Region = PKMConverter.Region
|
||||
};
|
||||
pk7.Nickname = PKX.getSpeciesNameGeneration(pk7.Species, pk7.Language, pk7.Format);
|
||||
if (otname[0] == 0x5D) // Ingame Trade
|
||||
{
|
||||
var s = PKX.getG1Char(0x5D, Japanese);
|
||||
pk7.OT_Name = s.Substring(0, 1) + s.Substring(1).ToLower();
|
||||
}
|
||||
pk7.OT_Friendship = pk7.HT_Friendship = PersonalTable.SM[Species].BaseFriendship;
|
||||
|
||||
// IVs
|
||||
|
@ -381,6 +386,18 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
pk7.TradeMemory(Bank:true); // oh no, memories on gen7 pkm
|
||||
|
||||
if (pk7.Species == 150) // Pay Day Mewtwo
|
||||
{
|
||||
var moves = pk7.Moves;
|
||||
var index = Array.IndexOf(moves, 6);
|
||||
if (index != -1)
|
||||
{
|
||||
moves[index] = 0;
|
||||
pk7.Moves = moves;
|
||||
pk7.FixMoves();
|
||||
}
|
||||
}
|
||||
|
||||
pk7.RefreshChecksum();
|
||||
return pk7;
|
||||
|
|
|
@ -306,7 +306,7 @@ namespace PKHeX.Core
|
|||
|
||||
public override int HPType
|
||||
{
|
||||
get { return 4 * IV_ATK % 4 + IV_DEF % 4; }
|
||||
get { return ((IV_ATK & 3) << 2) | (IV_DEF & 3); }
|
||||
set
|
||||
{
|
||||
|
||||
|
@ -327,7 +327,7 @@ namespace PKHeX.Core
|
|||
public override int Egg_Location { get { return 0; } set { } }
|
||||
public override int OT_Friendship { get { return 0; } set { } }
|
||||
public override int Ball { get { return 0; } set { } }
|
||||
public override int Version { get { return 0; } set { } }
|
||||
public override int Version { get { return (int)GameVersion.GSC; } set { } }
|
||||
public override int SID { get { return 0; } set { } }
|
||||
public override int CNT_Cool { get { return 0; } set { } }
|
||||
public override int CNT_Beauty { get { return 0; } set { } }
|
||||
|
|
|
@ -268,24 +268,28 @@ namespace PKHeX.Core
|
|||
public bool AO => Version == (int)GameVersion.AS || Version == (int)GameVersion.OR;
|
||||
public bool SM => Version == (int)GameVersion.SN || Version == (int)GameVersion.MN;
|
||||
protected bool PtHGSS => GameVersion.Pt == (GameVersion)Version || HGSS;
|
||||
protected bool HGSS => new[] {GameVersion.HG, GameVersion.SS}.Contains((GameVersion)Version);
|
||||
public bool HGSS => new[] {GameVersion.HG, GameVersion.SS}.Contains((GameVersion)Version);
|
||||
public bool VC => VC1 || VC2;
|
||||
public bool Gen7 => Version >= 30 && Version <= 33;
|
||||
public bool Gen6 => Version >= 24 && Version <= 29;
|
||||
public bool Gen5 => Version >= 20 && Version <= 23;
|
||||
public bool Gen4 => Version >= 7 && Version <= 12 && Version != 9;
|
||||
public bool Gen3 => Version >= 1 && Version <= 5 || Version == 15;
|
||||
public bool GenU => !(Gen7 || Gen6 || Gen5 || Gen4 || Gen3);
|
||||
public bool Gen2 => Version == (int)GameVersion.GSC;
|
||||
public bool Gen1 => Version == (int)GameVersion.RBY;
|
||||
public bool GenU => !(Gen7 || Gen6 || Gen5 || Gen4 || Gen3 || Gen2 || Gen1 || VC);
|
||||
public int GenNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VC) return 7;
|
||||
if (Gen7) return 7;
|
||||
if (Gen6) return 6;
|
||||
if (Gen5) return 5;
|
||||
if (Gen4) return 4;
|
||||
if (Gen3) return 3;
|
||||
if (Gen2) return Format; // 2
|
||||
if (Gen1) return Format; // 1
|
||||
if (VC) return 1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -399,28 +403,17 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
// Legality Extensions
|
||||
private int MaxSpeciesID => Legal.getMaxSpeciesOrigin(Format);
|
||||
public virtual bool WasLink => false;
|
||||
public virtual bool WasEgg => Egg_Location > 0;
|
||||
public virtual bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter;
|
||||
public virtual bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location > 0)) && Met_Level == 1;
|
||||
public virtual bool WasTradedEgg => Egg_Location == 30002;
|
||||
public virtual bool WasIngameTrade => Met_Location == 30001;
|
||||
public virtual bool IsUntraded => string.IsNullOrWhiteSpace(HT_Name) && GenNumber == Format;
|
||||
public virtual bool IsUntraded => Format >= 6 && string.IsNullOrWhiteSpace(HT_Name) && GenNumber == Format;
|
||||
public virtual bool IsNative => GenNumber == Format;
|
||||
public virtual bool IsOriginValid()
|
||||
{
|
||||
switch (GenNumber)
|
||||
{
|
||||
case 1: return Species <= Legal.MaxSpeciesID_1;
|
||||
case 2: return Species <= Legal.MaxSpeciesID_2;
|
||||
case 3: return Species <= Legal.MaxSpeciesID_3;
|
||||
case 4: return Species <= Legal.MaxSpeciesID_4;
|
||||
case 5: return Species <= Legal.MaxSpeciesID_5;
|
||||
case 6: return Species <= Legal.MaxSpeciesID_6;
|
||||
case 7: return Species <= Legal.MaxSpeciesID_7;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
public virtual bool IsOriginValid => Species <= Legal.getMaxSpeciesOrigin(Format);
|
||||
|
||||
public virtual bool SecretSuperTrainingUnlocked { get { return false; } set { } }
|
||||
public virtual bool SecretSuperTrainingComplete { get { return false; } set { } }
|
||||
|
||||
|
@ -453,31 +446,47 @@ namespace PKHeX.Core
|
|||
/// Checks if the <see cref="PKM"/> could inhabit a set of games.
|
||||
/// </summary>
|
||||
/// <param name="Generation">Set of games.</param>
|
||||
/// <param name="species"></param>
|
||||
/// <returns>True if could inhabit, False if not.</returns>
|
||||
public bool InhabitedGeneration(int Generation)
|
||||
public bool InhabitedGeneration(int Generation, int species = -1)
|
||||
{
|
||||
if (VC1 && Generation == 1)
|
||||
return true; // Virtual Console Gen1
|
||||
if (species < 0)
|
||||
species = Species;
|
||||
|
||||
if (Format == Generation)
|
||||
return true;
|
||||
|
||||
if (Format < Generation)
|
||||
return false; // Future
|
||||
if (GenNumber > Generation)
|
||||
return false; // Past
|
||||
|
||||
switch (Generation) // Sanity Check Species ID
|
||||
if (!IsOriginValid)
|
||||
return false;
|
||||
|
||||
// Sanity Check Species ID
|
||||
if (Legal.getMaxSpeciesOrigin(GenNumber) < species && !Legal.getFutureGenEvolutions(GenNumber).Contains(species))
|
||||
return false;
|
||||
|
||||
int gen = GenNumber;
|
||||
switch (Generation)
|
||||
{
|
||||
case 1: return Species <= Legal.MaxSpeciesID_1;
|
||||
case 2: return Species <= Legal.MaxSpeciesID_2;
|
||||
case 3: return Species <= Legal.MaxSpeciesID_3;
|
||||
case 4: return Species <= Legal.MaxSpeciesID_4;
|
||||
case 5: return Species <= Legal.MaxSpeciesID_5;
|
||||
case 6: return Species <= Legal.MaxSpeciesID_6;
|
||||
case 7: return Species <= Legal.MaxSpeciesID_7;
|
||||
case 1:
|
||||
case 2: return Format <= 2 || VC;
|
||||
case 3: return Gen3;
|
||||
case 4: return 3 <= gen && gen <= 4;
|
||||
case 5: return 3 <= gen && gen <= 5;
|
||||
case 6: return 3 <= gen && gen <= 6;
|
||||
case 7: return VC || 3 <= gen && gen <= 7;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PKM has its original met location.
|
||||
/// </summary>
|
||||
/// <returns>Returns false if the Met Location has been overwritten via generational transfer.</returns>
|
||||
public bool HasOriginalMetLocation => !(Format < 3 || VC || GenNumber <= 4 && Format != GenNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current <see cref="Gender"/> is valid.
|
||||
/// </summary>
|
||||
|
|
|
@ -2017,7 +2017,7 @@ namespace PKHeX.Core
|
|||
#region Gen 1 Character Tables
|
||||
private static Dictionary<byte, string> RBY2U_U => new Dictionary<byte, string>{
|
||||
{0x50, "\0"},
|
||||
{0x5D, "[TRAINER]"},
|
||||
{0x5D, "TRAINER"},
|
||||
{0x7F, " "},
|
||||
{0x80, "A"},
|
||||
{0x81, "B"},
|
||||
|
@ -2103,7 +2103,7 @@ namespace PKHeX.Core
|
|||
|
||||
private static Dictionary<string, byte> U2RBY_U => new Dictionary<string, byte> {
|
||||
{"\0", 0x50},
|
||||
{"[TRAINER]", 0x5D},
|
||||
{"TRAINER", 0x5D},
|
||||
{" ", 0x7F},
|
||||
{"A", 0x80},
|
||||
{"B", 0x81},
|
||||
|
@ -2562,6 +2562,18 @@ namespace PKHeX.Core
|
|||
.Aggregate("", (current, cur) => current + cur);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Generation 1 encoded character to string.
|
||||
/// </summary>
|
||||
/// <param name="key">Encoded character.</param>
|
||||
/// <param name="jp">Data source is Japanese.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string getG1Char(byte key, bool jp)
|
||||
{
|
||||
Dictionary<byte, string> dict = jp ? RBY2U_J : RBY2U_U;
|
||||
return dict.ContainsKey(key) ? dict[key] : "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Generation 1 encoded data the same way Bank converts.
|
||||
/// </summary>
|
||||
|
@ -2573,7 +2585,7 @@ namespace PKHeX.Core
|
|||
var us_table = new ushort[] { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x0028, 0x0029, 0x003A, 0x003B, 0x0028, 0x0029, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00C4, 0x00D6, 0x00DC, 0x00E4, 0x00F6, 0x00FC, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0050, 0x004D, 0x002D, 0x0020, 0x0020, 0x003F, 0x0021, 0x002D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0xE08E, 0x0020, 0x0078, 0x002E, 0x002F, 0x002C, 0xE08F, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
|
||||
var jp_table = new ushort[] { 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30AC, 0x30AE, 0x30B0, 0x30B2, 0x30B4, 0x30B6, 0x30B8, 0x30BA, 0x30BC, 0x30BE, 0x30C0, 0x30C2, 0x30C5, 0x30C7, 0x30C9, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30D0, 0x30D3, 0x30D6, 0x30DC, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x304C, 0x304E, 0x3050, 0x3052, 0x3054, 0x3056, 0x3058, 0x305A, 0x305C, 0x305E, 0x3060, 0x3062, 0x3065, 0x3067, 0x3069, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3070, 0x3073, 0x3076, 0x30D9, 0x307C, 0x3000, 0x30D1, 0x30D4, 0x30D7, 0x30DD, 0x3071, 0x3074, 0x3077, 0x30DA, 0x307D, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F2, 0x30F3, 0x30C3, 0x30E3, 0x30E5, 0x30E7, 0x30A3, 0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D, 0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, 0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x30D8, 0x307B, 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086, 0x3088, 0x3089, 0x30EA, 0x308B, 0x308C, 0x308D, 0x308F, 0x3092, 0x3093, 0x3063, 0x3083, 0x3085, 0x3087, 0x30FC, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30A1, 0x30A5, 0x30A7, 0x3000, 0x3000, 0x3000, 0x2642, 0x3000, 0x3000, 0x3000, 0x3000, 0x30A9, 0x2640, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000 };
|
||||
var table = jp ? jp_table : us_table;
|
||||
return Util.TrimFromZero(new string(strdata.Select(b => (char)table[b]).ToArray()));
|
||||
return Util.TrimFromZero(new string(strdata.TakeWhile(b => b != 0).Select(b => (char)table[b]).ToArray()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2640,43 +2652,44 @@ namespace PKHeX.Core
|
|||
// Extensions
|
||||
public static string getLocation(this PKM pk, bool eggmet)
|
||||
{
|
||||
if (pk.Format <= 2)
|
||||
if (pk.Format < 2)
|
||||
return "";
|
||||
|
||||
int gen = -1;
|
||||
int bankID = 0;
|
||||
int locval = eggmet ? pk.Egg_Location : pk.Met_Location;
|
||||
|
||||
if (pk.Format == 2)
|
||||
return GameInfo.Strings.metGSC_00000[locval];
|
||||
if (pk.Format == 3)
|
||||
return GameInfo.Strings.metRSEFRLG_00000[locval % 0x100];
|
||||
if (pk.Gen4 && (eggmet || pk.Format == 4))
|
||||
gen = 2;
|
||||
else if (pk.Format == 3)
|
||||
gen = 3;
|
||||
else if (pk.Gen4 && (eggmet || pk.Format == 4)) // 4
|
||||
{
|
||||
if (locval < 2000) return GameInfo.Strings.metHGSS_00000[locval];
|
||||
if (locval < 3000) return GameInfo.Strings.metHGSS_02000[locval % 2000];
|
||||
return GameInfo.Strings.metHGSS_03000[locval % 3000];
|
||||
const int size = 1000;
|
||||
bankID = locval/size;
|
||||
gen = 4;
|
||||
locval %= size;
|
||||
}
|
||||
if (pk.Gen5 || pk.Format <= 5)
|
||||
else // 5-7+
|
||||
{
|
||||
if (locval < 30000) return GameInfo.Strings.metBW2_00000[locval];
|
||||
if (locval < 40000) return GameInfo.Strings.metBW2_30000[locval % 10000 - 1];
|
||||
if (locval < 60000) return GameInfo.Strings.metBW2_40000[locval % 10000 - 1];
|
||||
return GameInfo.Strings.metBW2_60000[locval % 10000 - 1];
|
||||
const int size = 10000;
|
||||
bankID = locval/size;
|
||||
|
||||
int g = pk.GenNumber;
|
||||
if (g >= 5)
|
||||
gen = g;
|
||||
else if (pk.Format >= 5)
|
||||
gen = pk.Format;
|
||||
|
||||
locval %= size;
|
||||
if (bankID >= 3)
|
||||
locval -= 1;
|
||||
}
|
||||
if (pk.Gen6 || pk.Format <= 6)
|
||||
{
|
||||
if (locval < 30000) return GameInfo.Strings.metXY_00000[locval];
|
||||
if (locval < 40000) return GameInfo.Strings.metXY_30000[locval % 10000 - 1];
|
||||
if (locval < 60000) return GameInfo.Strings.metXY_40000[locval % 10000 - 1];
|
||||
return GameInfo.Strings.metXY_60000[locval % 10000 - 1];
|
||||
}
|
||||
if (pk.Gen7 || pk.Format <= 7)
|
||||
{
|
||||
if (locval < 30000) return GameInfo.Strings.metSM_00000[locval];
|
||||
if (locval < 40000) return GameInfo.Strings.metSM_30000[locval % 10000 - 1];
|
||||
if (locval < 60000) return GameInfo.Strings.metSM_40000[locval % 10000 - 1];
|
||||
return GameInfo.Strings.metSM_60000[locval % 10000 - 1];
|
||||
}
|
||||
return null; // Shouldn't happen for gen 3+
|
||||
|
||||
var bank = GameInfo.getLocationNames(gen, bankID);
|
||||
if (bank == null || bank.Length <= locval)
|
||||
return "";
|
||||
return bank[locval];
|
||||
}
|
||||
public static string[] getQRText(this PKM pkm)
|
||||
{
|
||||
|
|
|
@ -40,10 +40,10 @@ namespace PKHeX.Core
|
|||
}
|
||||
public override int CatchRate { get { return Data[0x08]; } set { Data[0x08] = (byte)value; } }
|
||||
public override int BaseEXP { get { return Data[0x09]; } set { Data[0x09] = (byte)value; } }
|
||||
public int Move1 { get { return Data[0x0A]; } set { Data[0x0A] = (byte)value; } }
|
||||
public int Move2 { get { return Data[0x0B]; } set { Data[0x0B] = (byte)value; } }
|
||||
public int Move3 { get { return Data[0x0C]; } set { Data[0x0C] = (byte)value; } }
|
||||
public int Move4 { get { return Data[0x0D]; } set { Data[0x0D] = (byte)value; } }
|
||||
public int Move1 { get { return Data[0x0F]; } set { Data[0x0F] = (byte)value; } }
|
||||
public int Move2 { get { return Data[0x10]; } set { Data[0x10] = (byte)value; } }
|
||||
public int Move3 { get { return Data[0x11]; } set { Data[0x11] = (byte)value; } }
|
||||
public int Move4 { get { return Data[0x12]; } set { Data[0x12] = (byte)value; } }
|
||||
public override int EXPGrowth { get { return Data[0x13]; } set { Data[0x13] = (byte)value; } }
|
||||
|
||||
// EV Yields are just aliases for base stats in Gen I
|
||||
|
@ -64,5 +64,11 @@ namespace PKHeX.Core
|
|||
public override int BaseFriendship { get { return 0; } set { } }
|
||||
public override int EscapeRate { get { return 0; } set { } }
|
||||
public override int Color { get { return 0; } set { } }
|
||||
|
||||
public int[] Moves
|
||||
{
|
||||
get { return new[] { Move1, Move2, Move3, Move4 }; }
|
||||
set { if (value?.Length != 4) return; Move1 = value[0]; Move2 = value[1]; Move3 = value[2]; Move4 = value[3]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ namespace PKHeX.Core
|
|||
public static readonly PersonalTable RS = new PersonalTable(Properties.Resources.personal_rs, GameVersion.RS);
|
||||
public static readonly PersonalTable C = new PersonalTable(Properties.Resources.personal_c, GameVersion.C);
|
||||
public static readonly PersonalTable GS = new PersonalTable(Properties.Resources.personal_c, GameVersion.GS);
|
||||
public static readonly PersonalTable RBY = new PersonalTable(Properties.Resources.personal_rby, GameVersion.RBY);
|
||||
public static readonly PersonalTable RB = new PersonalTable(Properties.Resources.personal_rb, GameVersion.RBY);
|
||||
public static readonly PersonalTable Y = new PersonalTable(Properties.Resources.personal_y, GameVersion.RBY);
|
||||
|
||||
private static byte[][] splitBytes(byte[] data, int size)
|
||||
{
|
||||
|
|
181
PKHeX/Properties/Resources.Designer.cs
generated
|
@ -12324,12 +12324,15 @@ namespace PKHeX.Core.Properties {
|
|||
/// Looks up a localized string similar to PKHeX - By Kaphotics
|
||||
///http://projectpokemon.org/pkhex
|
||||
///
|
||||
///17/01/30 - New Update:
|
||||
/// - Added: Control right-clicking a PKM slot (box, party, etc) now allows direct legality checking.
|
||||
/// - Added: 6/7 detection preferential treatment & other detection methods. Thanks sora10pls!
|
||||
/// - Added: Remove All medals button now clears Unlocked/Complete flags even if not visible.
|
||||
/// - Fixed: Badly constructed ShowdownSets throw less exceptions (hopefully none). Thanks Sonic Blader!
|
||||
/// - Fixed: Cloning to all slots in a Gen1/2 [rest of string was truncated]";.
|
||||
///17/02/25 - New Update:
|
||||
/// - Legality:
|
||||
/// - - Added: Legality checking for RBY Pokémon as pk1 and pk7+.
|
||||
/// - - Fixed: More edge cases for legality checks.
|
||||
/// - Batch Editor:
|
||||
/// - - Added: Nickname clearing to batch editor (via .IsNicknamed=False).
|
||||
/// - - Added: Legality filtering and bulk suggestions for Met Location, Current Moves & Relearn Moves.
|
||||
/// - - - Use $suggest to use suggested result from the legality analysis.
|
||||
/// - - Changed: Properties are now sort [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
public static string changelog {
|
||||
get {
|
||||
|
@ -12459,6 +12462,16 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] encounter_blue {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("encounter_blue", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -12489,6 +12502,26 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] encounter_rb_f {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("encounter_rb_f", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] encounter_red {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("encounter_red", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -12529,6 +12562,26 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] encounter_yellow {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("encounter_yellow", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] encounter_yellow_f {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("encounter_yellow_f", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -12539,6 +12592,26 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] evos_gsc {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("evos_gsc", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] evos_rby {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("evos_rby", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -17761,6 +17834,36 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] lvlmove_c {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("lvlmove_c", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] lvlmove_gs {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("lvlmove_gs", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] lvlmove_rb {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("lvlmove_rb", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -17781,6 +17884,16 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] lvlmove_y {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("lvlmove_y", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
@ -17944,9 +18057,9 @@ namespace PKHeX.Core.Properties {
|
|||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] personal_rby {
|
||||
public static byte[] personal_rb {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("personal_rby", resourceCulture);
|
||||
object obj = ResourceManager.GetObject("personal_rb", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
@ -17981,6 +18094,16 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] personal_y {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("personal_y", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -17992,7 +18115,7 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 20170130.
|
||||
/// Looks up a localized string similar to 20170225.
|
||||
/// </summary>
|
||||
public static string ProgramVersion {
|
||||
get {
|
||||
|
@ -19071,7 +19194,7 @@ namespace PKHeX.Core.Properties {
|
|||
///// Main Window
|
||||
///
|
||||
///CTRL-O: Open
|
||||
///CTRL-S: Export PK6
|
||||
///CTRL-S: Export PKM
|
||||
///CTRL-E: Export SAV
|
||||
///CTRL-B: Export BAK
|
||||
///CTRL-Q: Quit
|
||||
|
@ -26683,8 +26806,8 @@ namespace PKHeX.Core.Properties {
|
|||
///
|
||||
///Go
|
||||
///Rote
|
||||
///Blaue[INT]/Grüne[JP]
|
||||
///Blaue
|
||||
///Grüne
|
||||
///Gelbe.
|
||||
/// </summary>
|
||||
public static string text_games_de {
|
||||
|
@ -26730,8 +26853,8 @@ namespace PKHeX.Core.Properties {
|
|||
///
|
||||
///Go
|
||||
///Red
|
||||
///Blue
|
||||
///Green
|
||||
///Blue[INT]/Green[JP]
|
||||
///Blue[JP]
|
||||
///Yellow.
|
||||
/// </summary>
|
||||
public static string text_games_en {
|
||||
|
@ -26777,8 +26900,8 @@ namespace PKHeX.Core.Properties {
|
|||
///
|
||||
///Go
|
||||
///Roja
|
||||
///Azul
|
||||
///Verde
|
||||
///Azul[INT]/Verde[JP]
|
||||
///Azul[JP]
|
||||
///Amarilla.
|
||||
/// </summary>
|
||||
public static string text_games_es {
|
||||
|
@ -26824,8 +26947,8 @@ namespace PKHeX.Core.Properties {
|
|||
///
|
||||
///Go
|
||||
///Rouge
|
||||
///Bleue
|
||||
///Vert
|
||||
///Bleue[INT]/Vert[JP]
|
||||
///Bleue[JP]
|
||||
///Jaune.
|
||||
/// </summary>
|
||||
public static string text_games_fr {
|
||||
|
@ -26871,8 +26994,8 @@ namespace PKHeX.Core.Properties {
|
|||
///
|
||||
///Go
|
||||
///Rossa
|
||||
///Blu
|
||||
///Verde
|
||||
///Blu[INT]/Verde[JP]
|
||||
///Blu[JP]
|
||||
///Gialla.
|
||||
/// </summary>
|
||||
public static string text_games_it {
|
||||
|
@ -26918,8 +27041,8 @@ namespace PKHeX.Core.Properties {
|
|||
///
|
||||
///Go
|
||||
///赤
|
||||
///青
|
||||
///緑
|
||||
///青[INT]/緑[JP]
|
||||
///青[JP]
|
||||
///黄.
|
||||
/// </summary>
|
||||
public static string text_games_ja {
|
||||
|
@ -26965,8 +27088,8 @@ namespace PKHeX.Core.Properties {
|
|||
///
|
||||
///고
|
||||
///레드
|
||||
///블루
|
||||
///그린
|
||||
///블루[INT]/그린[JP]
|
||||
///블루[JP]
|
||||
///옐로.
|
||||
/// </summary>
|
||||
public static string text_games_ko {
|
||||
|
@ -27012,8 +27135,8 @@ namespace PKHeX.Core.Properties {
|
|||
///
|
||||
///Go
|
||||
///紅
|
||||
///藍色
|
||||
///綠色
|
||||
///藍色[INT]/綠色[JP]
|
||||
///藍色[JP]
|
||||
///黃色.
|
||||
/// </summary>
|
||||
public static string text_games_zh {
|
||||
|
@ -28889,7 +29012,7 @@ namespace PKHeX.Core.Properties {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Ningún objeto
|
||||
/// Looks up a localized string similar to Ninguno
|
||||
///Master Ball
|
||||
///Ultra Ball
|
||||
///Super Ball
|
||||
|
@ -28930,7 +29053,7 @@ namespace PKHeX.Core.Properties {
|
|||
///Éter
|
||||
///Éter Máximo
|
||||
///Elixir
|
||||
///Elixir M [rest of string was truncated]";.
|
||||
///Elixir Máximo
/// [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
public static string text_items_es {
|
||||
get {
|
||||
|
@ -34182,8 +34305,8 @@ namespace PKHeX.Core.Properties {
|
|||
///小磁怪
|
||||
///三合一磁怪
|
||||
///大蔥鴨
|
||||
///都都
|
||||
///都都利
|
||||
///嘟嘟
|
||||
///嘟嘟利
|
||||
///小海獅
|
||||
///白海獅
|
||||
///臭泥
|
||||
|
|
|
@ -6388,9 +6388,6 @@
|
|||
<data name="ProgramVersion" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\text\version.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="personal_rby" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\personal_rby;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="text_gsc_00000_en" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\text\gen3\text_gsc_00000_en.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
||||
</data>
|
||||
|
@ -7384,4 +7381,43 @@
|
|||
<data name="fashion_m_sm_illegal" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\fashion_m_sm_illegal;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="evos_rby" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\evos_rby.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="encounter_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\encounter_blue.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="encounter_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\encounter_red.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="encounter_yellow" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\encounter_yellow.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="encounter_rb_f" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\encounter_rb_f.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="encounter_yellow_f" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\encounter_yellow_f.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="lvlmove_rb" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\lvlmove_rb.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="lvlmove_y" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\lvlmove_y.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="personal_rb" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\personal_rb;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="personal_y" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\personal_y;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="evos_gsc" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\evos_gsc.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="lvlmove_c" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\lvlmove_c.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="lvlmove_gs" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\byte\lvlmove_gs.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
BIN
PKHeX/Resources/byte/encounter_blue.pkl
Normal file
BIN
PKHeX/Resources/byte/encounter_rb_f.pkl
Normal file
BIN
PKHeX/Resources/byte/encounter_red.pkl
Normal file
BIN
PKHeX/Resources/byte/encounter_yellow.pkl
Normal file
BIN
PKHeX/Resources/byte/encounter_yellow_f.pkl
Normal file
BIN
PKHeX/Resources/byte/evos_gsc.pkl
Normal file
BIN
PKHeX/Resources/byte/evos_rby.pkl
Normal file
BIN
PKHeX/Resources/byte/lvlmove_c.pkl
Normal file
BIN
PKHeX/Resources/byte/lvlmove_gs.pkl
Normal file
BIN
PKHeX/Resources/byte/lvlmove_rb.pkl
Normal file
BIN
PKHeX/Resources/byte/lvlmove_y.pkl
Normal file
BIN
PKHeX/Resources/byte/personal_y
Normal file
Before Width: | Height: | Size: 533 B After Width: | Height: | Size: 571 B |
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 444 B |
Before Width: | Height: | Size: 461 B After Width: | Height: | Size: 488 B |
Before Width: | Height: | Size: 577 B After Width: | Height: | Size: 554 B |
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 528 B |
Before Width: | Height: | Size: 408 B After Width: | Height: | Size: 424 B |
Before Width: | Height: | Size: 552 B After Width: | Height: | Size: 564 B |
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 429 B |
|
@ -1,7 +1,24 @@
|
|||
PKHeX - By Kaphotics
|
||||
http://projectpokemon.org/pkhex
|
||||
|
||||
17/02/07 - New Update:
|
||||
17/02/25 - New Update:
|
||||
- Legality:
|
||||
- - Added: Legality checking for RBY Pokémon as pk1 and pk7+.
|
||||
- - Fixed: More edge cases for legality checks.
|
||||
- Batch Editor:
|
||||
- - Added: Nickname clearing to batch editor (via .IsNicknamed=False).
|
||||
- - Added: Legality filtering and bulk suggestions for Met Location, Current Moves & Relearn Moves.
|
||||
- - - Use $suggest to use suggested result from the legality analysis.
|
||||
- - Changed: Properties are now sorted alphabetically.
|
||||
- Added: WC7 parsing for multiple-item gifts. Thanks SciresM!
|
||||
- Added: X/Y Trainer Nickname editing (via Current Appearance tab).
|
||||
- Added: S/M Festival Plaza name editing.
|
||||
- Fixed: Gen4 Pokédex bitflag setting no longer sets invalid data for single-gender species.
|
||||
- Fixed: wc7->pk7 base friendship fixed. Thanks T.O.R.N.A.D.O & Odaxis!
|
||||
- Fixed: Gen1/2 Money/Coin editing & inventory editing edge cases.
|
||||
- Updated: Menu sprites to use Sun/Moon sprites for some species (like Steelix).
|
||||
|
||||
17/02/07 - New Update: (64480) [360228]
|
||||
- Legality:
|
||||
- - Added: Legality indication for exported QR images (if legality check is available for origin).
|
||||
- - Added: Legality indication for Box/Party pkm slots (^ + opt-in via Options->Set to SAV).
|
||||
|
|
|
@ -34,6 +34,6 @@ Mond
|
|||
|
||||
Go
|
||||
Rote
|
||||
Blaue[INT]/Grüne[JP]
|
||||
Blaue
|
||||
Grüne
|
||||
Gelbe
|
|
@ -34,6 +34,6 @@ Moon
|
|||
|
||||
Go
|
||||
Red
|
||||
Blue
|
||||
Green
|
||||
Blue[INT]/Green[JP]
|
||||
Blue[JP]
|
||||
Yellow
|
|
@ -34,6 +34,6 @@ Luna
|
|||
|
||||
Go
|
||||
Roja
|
||||
Azul
|
||||
Verde
|
||||
Azul[INT]/Verde[JP]
|
||||
Azul[JP]
|
||||
Amarilla
|
|
@ -34,6 +34,6 @@ Lune
|
|||
|
||||
Go
|
||||
Rouge
|
||||
Bleue
|
||||
Vert
|
||||
Bleue[INT]/Vert[JP]
|
||||
Bleue[JP]
|
||||
Jaune
|
|
@ -34,6 +34,6 @@ Luna
|
|||
|
||||
Go
|
||||
Rossa
|
||||
Blu
|
||||
Verde
|
||||
Blu[INT]/Verde[JP]
|
||||
Blu[JP]
|
||||
Gialla
|
|
@ -34,6 +34,6 @@ OR
|
|||
|
||||
Go
|
||||
赤
|
||||
青
|
||||
緑
|
||||
青[INT]/緑[JP]
|
||||
青[JP]
|
||||
黄
|
|
@ -34,6 +34,6 @@ OR
|
|||
|
||||
고
|
||||
레드
|
||||
블루
|
||||
그린
|
||||
블루[INT]/그린[JP]
|
||||
블루[JP]
|
||||
옐로
|
|
@ -38,7 +38,7 @@ Hold Control when dragging to save encrypted (ekx).
|
|||
|
||||
Click on...
|
||||
- OT label: Set save file details to relevant properties.
|
||||
- Met Location label: Suggest encounter information for relevant properties.
|
||||
- Level / Met Location label: Suggest encounter information for relevant properties.
|
||||
- Moves groupbox: Suggest legal moves.
|
||||
- Relearn Moves groupbox: Suggest legal relearn moves.
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
20170207
|
||||
20170225
|
|
@ -34,6 +34,6 @@ Y
|
|||
|
||||
Go
|
||||
紅
|
||||
藍色
|
||||
綠色
|
||||
藍色[INT]/綠色[JP]
|
||||
藍色[JP]
|
||||
黃色
|
|
@ -82,8 +82,8 @@
|
|||
小磁怪
|
||||
三合一磁怪
|
||||
大蔥鴨
|
||||
都都
|
||||
都都利
|
||||
嘟嘟
|
||||
嘟嘟利
|
||||
小海獅
|
||||
白海獅
|
||||
臭泥
|
||||
|
@ -110,7 +110,7 @@
|
|||
瓦斯彈
|
||||
雙彈瓦斯
|
||||
獨角犀牛
|
||||
鉆角犀獸
|
||||
鑽角犀獸
|
||||
吉利蛋
|
||||
蔓藤怪
|
||||
袋獸
|
||||
|
@ -120,7 +120,7 @@
|
|||
金魚王
|
||||
海星星
|
||||
寶石海星
|
||||
魔墻人偶
|
||||
魔牆人偶
|
||||
飛天螳螂
|
||||
迷唇姐
|
||||
電擊獸
|
||||
|
@ -213,7 +213,7 @@
|
|||
巨鉗螳螂
|
||||
壺壺
|
||||
赫拉克羅斯
|
||||
紐拉
|
||||
狃拉
|
||||
熊寶寶
|
||||
圈圈熊
|
||||
熔岩蟲
|
||||
|
@ -262,7 +262,7 @@
|
|||
土狼犬
|
||||
大狼犬
|
||||
蛇紋熊
|
||||
直沖熊
|
||||
直衝熊
|
||||
刺尾蟲
|
||||
甲殼繭
|
||||
狩獵鳳蝶
|
||||
|
@ -387,7 +387,7 @@
|
|||
代歐奇希斯
|
||||
草苗龜
|
||||
樹林龜
|
||||
土臺龜
|
||||
土台龜
|
||||
小火焰猴
|
||||
猛火猴
|
||||
烈焰猴
|
||||
|
@ -425,7 +425,7 @@
|
|||
雙尾怪手
|
||||
飄飄球
|
||||
隨風球
|
||||
卷卷耳
|
||||
捲捲耳
|
||||
長耳兔
|
||||
夢妖魔
|
||||
烏鴉頭頭
|
||||
|
@ -454,12 +454,12 @@
|
|||
不良蛙
|
||||
毒骷蛙
|
||||
尖牙籠
|
||||
熒光魚
|
||||
螢光魚
|
||||
霓虹魚
|
||||
小球飛魚
|
||||
雪笠怪
|
||||
暴雪王
|
||||
瑪紐拉
|
||||
瑪狃拉
|
||||
自爆磁怪
|
||||
大舌舔
|
||||
超甲狂犀
|
||||
|
@ -519,7 +519,7 @@
|
|||
夢夢蝕
|
||||
豆豆鴿
|
||||
咕咕鴿
|
||||
高傲稚雞
|
||||
高傲雉雞
|
||||
斑斑馬
|
||||
雷電斑馬
|
||||
石丸子
|
||||
|
@ -542,7 +542,7 @@
|
|||
寶包繭
|
||||
保母蟲
|
||||
百足蜈蚣
|
||||
車輪球
|
||||
車輪毬
|
||||
蜈蚣王
|
||||
木棉球
|
||||
風妖精
|
||||
|
@ -559,7 +559,7 @@
|
|||
岩殿居蟹
|
||||
滑滑小子
|
||||
頭巾混混
|
||||
象征鳥
|
||||
象徵鳥
|
||||
哭哭面具
|
||||
死神棺
|
||||
原蓋海龜
|
||||
|
@ -639,7 +639,7 @@
|
|||
勾帕路翁
|
||||
代拉基翁
|
||||
畢力吉翁
|
||||
龍卷雲
|
||||
龍捲雲
|
||||
雷電雲
|
||||
萊希拉姆
|
||||
捷克羅姆
|
||||
|
@ -701,7 +701,7 @@
|
|||
仙子伊布
|
||||
摔角鷹人
|
||||
咚咚鼠
|
||||
小碎鉆
|
||||
小碎鑽
|
||||
黏黏寶
|
||||
黏美兒
|
||||
黏美龍
|
||||
|
@ -768,8 +768,8 @@
|
|||
膽小蟲
|
||||
具甲武者
|
||||
沙丘娃
|
||||
噬沙堡爷
|
||||
拳海参
|
||||
噬沙堡爺
|
||||
拳海參
|
||||
屬性:空
|
||||
銀伴戰獸
|
||||
小隕星
|
||||
|
@ -785,7 +785,7 @@
|
|||
杖尾鱗甲龍
|
||||
卡璞・鳴鳴
|
||||
卡璞・蝶蝶
|
||||
卡璞・牟牟
|
||||
卡璞・哞哞
|
||||
卡璞・鰭鰭
|
||||
科斯莫古
|
||||
科斯莫姆
|
||||
|
@ -796,7 +796,7 @@
|
|||
費洛美螂
|
||||
電束木
|
||||
鐵火輝夜
|
||||
紙禦劍
|
||||
紙御劍
|
||||
惡食大王
|
||||
奈克洛茲瑪
|
||||
瑪機雅娜
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace PKHeX.Core
|
|||
Party = getPartyOffset(0);
|
||||
|
||||
Japanese = SaveUtil.getIsG1SAVJ(Data);
|
||||
Personal = PersonalTable.RBY;
|
||||
Personal = PersonalTable.Y;
|
||||
|
||||
// Stash boxes after the save file's end.
|
||||
byte[] TempBox = new byte[SIZE_STOREDBOX];
|
||||
|
@ -318,22 +318,23 @@ namespace PKHeX.Core
|
|||
}
|
||||
public override uint Money
|
||||
{
|
||||
get { return uint.Parse((BigEndian.ToUInt32(Data, Japanese ? 0x25EE : 0x25F3) >> 8).ToString("X6")); }
|
||||
get { return (uint)BigEndian.BCDToInt32(Data, Japanese ? 0x25EE : 0x25F3, 3); }
|
||||
set
|
||||
{
|
||||
BigEndian.GetBytes(Convert.ToUInt32(value.ToString("000000"), 16)).Skip(1).ToArray().CopyTo(Data, Japanese ? 0x25EE : 0x25F3);
|
||||
value = (uint)Math.Min(value, MaxMoney);
|
||||
BigEndian.Int32ToBCD((int)value, 3).CopyTo(Data, Japanese ? 0x25EE : 0x25F3);
|
||||
}
|
||||
}
|
||||
public uint Coin
|
||||
{
|
||||
get
|
||||
{
|
||||
return uint.Parse(BigEndian.ToUInt16(Data, Japanese ? 0x2846 : 0x2850).ToString("X4"));
|
||||
return (uint)BigEndian.BCDToInt32(Data, Japanese ? 0x2846 : 0x2850, 2);
|
||||
}
|
||||
set
|
||||
{
|
||||
ushort val = (ushort)Math.Min(value, MaxCoins);
|
||||
BigEndian.GetBytes(val).CopyTo(Data, Japanese ? 0x2846 : 0x2850);
|
||||
value = (ushort)Math.Min(value, MaxCoins);
|
||||
BigEndian.Int32ToBCD((int)value, 2).CopyTo(Data, Japanese ? 0x2846 : 0x2850);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
if (Version == GameVersion.C && Japanese)
|
||||
{
|
||||
Array.Copy(Data, 0x2009, Data, 0x7209, 0xB32);
|
||||
Array.Copy(Data, 0x2009, Data, 0x7209, 0xADA);
|
||||
}
|
||||
if (Version == GameVersion.GS && !Japanese)
|
||||
{
|
||||
|
@ -257,96 +257,45 @@ namespace PKHeX.Core
|
|||
private int GenderOffset { get; set; } = int.MinValue;
|
||||
|
||||
// Checksums
|
||||
private ushort getChecksum()
|
||||
{
|
||||
int end;
|
||||
switch (Version)
|
||||
{
|
||||
case GameVersion.C:
|
||||
end = Japanese ? 0x2AE2 : 0x2B82;
|
||||
break;
|
||||
default: // GS
|
||||
end = Japanese ? 0x2C8B : 0x2D68;
|
||||
break;
|
||||
}
|
||||
return (ushort)Data.Skip(0x2009).Take(end - 0x2009 + 1).Sum(a => a);
|
||||
}
|
||||
protected override void setChecksums()
|
||||
{
|
||||
ushort accum = 0;
|
||||
for (int i = 0x2009; i <= 0x2B3A; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && Japanese)
|
||||
{
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x2D0D);
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x7F0D);
|
||||
}
|
||||
|
||||
for (int i = 0x2B3B; i <= 0x2B82; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && !Japanese)
|
||||
{
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x2D0D);
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x1F0D);
|
||||
}
|
||||
|
||||
for (int i = 0x2B83; i <= 0x2C8B; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.GS && Japanese)
|
||||
{
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x2D0D);
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x7F0D);
|
||||
}
|
||||
|
||||
for (int i = 0x2C8C; i <= 0x2D68; i++)
|
||||
accum += Data[i];
|
||||
ushort accum = getChecksum();
|
||||
if (Version == GameVersion.GS && !Japanese)
|
||||
{
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x2D69);
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x7E6D);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x2D0D);
|
||||
BitConverter.GetBytes(accum).CopyTo(Data, 0x7F0D);
|
||||
}
|
||||
}
|
||||
public override bool ChecksumsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort accum = 0;
|
||||
for (int i = 0x2009; i <= 0x2B3A; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && Japanese)
|
||||
return accum == BitConverter.ToUInt16(Data, 0x2D0D); // Japanese Crystal
|
||||
|
||||
for (int i = 0x2B3B; i <= 0x2B82; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && !Japanese)
|
||||
return accum == BitConverter.ToUInt16(Data, 0x2D0D); // US Crystal
|
||||
|
||||
for (int i = 0x2B83; i <= 0x2C8B; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.GS && Japanese)
|
||||
return accum == BitConverter.ToUInt16(Data, 0x2D69); // Japanese Gold/Silver
|
||||
|
||||
for (int i = 0x2C8C; i <= 0x2D68; i++)
|
||||
accum += Data[i];
|
||||
ushort accum = getChecksum();
|
||||
if (Version == GameVersion.GS && !Japanese)
|
||||
return accum == BitConverter.ToUInt16(Data, 0x2D69); // US Gold/Silver
|
||||
|
||||
return false;
|
||||
return accum == BitConverter.ToUInt16(Data, 0x2D0D); // Japanese Crystal
|
||||
}
|
||||
}
|
||||
|
||||
private int getChecksum()
|
||||
{
|
||||
ushort accum = 0;
|
||||
for (int i = 0x2009; i <= 0x2B3A; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && Japanese)
|
||||
return accum; // Japanese Crystal
|
||||
|
||||
for (int i = 0x2B3B; i <= 0x2B82; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && !Japanese)
|
||||
return accum; // US Crystal
|
||||
|
||||
for (int i = 0x2B83; i <= 0x2C8B; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.GS && Japanese)
|
||||
return accum; // Japanese Gold/Silver
|
||||
|
||||
for (int i = 0x2C8C; i <= 0x2D68; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.GS && !Japanese)
|
||||
return accum; // US Gold/Silver
|
||||
|
||||
return 0;
|
||||
}
|
||||
public override string ChecksumInfo => ChecksumsValid ? "Checksum valid." : "Checksum invalid";
|
||||
|
||||
// Trainer Info
|
||||
|
@ -354,7 +303,7 @@ namespace PKHeX.Core
|
|||
|
||||
public override string OT
|
||||
{
|
||||
get { return PKX.getG1Str(Data.Skip(0x200B).Take(StringLength).ToArray(), Japanese); }
|
||||
get { return PKX.getG1Str(getData(0x200B, StringLength), Japanese); }
|
||||
set
|
||||
{
|
||||
byte[] strdata = PKX.setG1Str(value, Japanese);
|
||||
|
@ -448,22 +397,23 @@ namespace PKHeX.Core
|
|||
}
|
||||
public override uint Money
|
||||
{
|
||||
get { return BigEndian.ToUInt32(Data, MoneyOffset) >> 8; }
|
||||
get { return (uint)BigEndian.BCDToInt32(Data, MoneyOffset, 3); }
|
||||
set
|
||||
{
|
||||
BigEndian.GetBytes(value > 999999 ? 999999 : value).Skip(1).ToArray().CopyTo(Data, MoneyOffset);
|
||||
value = (uint)Math.Min(value, MaxMoney);
|
||||
BigEndian.Int32ToBCD((int)value, 3).CopyTo(Data, MoneyOffset);
|
||||
}
|
||||
}
|
||||
public uint Coin
|
||||
{
|
||||
get
|
||||
{
|
||||
return BigEndian.ToUInt16(Data, MoneyOffset + 7);
|
||||
return (uint)BigEndian.BCDToInt32(Data, MoneyOffset + 7, 2);
|
||||
}
|
||||
set
|
||||
{
|
||||
ushort val = (ushort)Math.Min(value, MaxCoins);
|
||||
BigEndian.GetBytes(val).CopyTo(Data, MoneyOffset + 7);
|
||||
value = (ushort)Math.Min(value, MaxCoins);
|
||||
BigEndian.Int32ToBCD((int)value, 2).CopyTo(Data, MoneyOffset + 7);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,7 +513,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
public override string getBoxName(int box)
|
||||
{
|
||||
return PKX.getG1Str(Data.Skip(BoxNamesOffset + box*9).Take(9).ToArray(), Japanese);
|
||||
return PKX.getG1Str(getData(BoxNamesOffset + box*9, 9), Japanese);
|
||||
}
|
||||
public override void setBoxName(int box, string value)
|
||||
{
|
||||
|
@ -624,10 +574,16 @@ namespace PKHeX.Core
|
|||
int bit = pkm.Species - 1;
|
||||
int ofs = bit >> 3;
|
||||
byte bitval = (byte)(1 << (bit & 7));
|
||||
|
||||
if (!seen)
|
||||
{
|
||||
// Clear the Seen Flag
|
||||
Data[PokedexSeenOffset + ofs] &= (byte)~bitval;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the Seen Flag
|
||||
Data[PokedexSeenOffset + ofs] &= (byte)~bitval;
|
||||
if (seen)
|
||||
Data[PokedexSeenOffset + ofs] |= bitval;
|
||||
Data[PokedexSeenOffset + ofs] |= bitval;
|
||||
}
|
||||
public override void setCaught(PKM pkm, bool caught = true)
|
||||
{
|
||||
|
@ -641,18 +597,22 @@ namespace PKHeX.Core
|
|||
int bit = pkm.Species - 1;
|
||||
int ofs = bit >> 3;
|
||||
byte bitval = (byte)(1 << (bit & 7));
|
||||
// Set the Captured Flag
|
||||
Data[PokedexCaughtOffset + ofs] &= (byte)~bitval;
|
||||
if (caught)
|
||||
|
||||
if (!caught)
|
||||
{
|
||||
Data[PokedexCaughtOffset + ofs] |= bitval;
|
||||
if (pkm.Species == 201) // Unown
|
||||
// Clear the Captured Flag
|
||||
Data[PokedexCaughtOffset + ofs] &= (byte)~bitval;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the Captured Flag
|
||||
Data[PokedexCaughtOffset + ofs] |= bitval;
|
||||
if (pkm.Species == 201) // Unown
|
||||
{
|
||||
// Give all Unown caught to prevent a crash on pokedex view
|
||||
for (int i = 1; i <= 26; i++)
|
||||
{
|
||||
// Give all Unown caught to prevent a crash on pokedex view
|
||||
for (int i = 1; i <= 26; i++)
|
||||
{
|
||||
Data[PokedexSeenOffset + 0x1F + i] = (byte)i;
|
||||
}
|
||||
Data[PokedexSeenOffset + 0x1F + i] = (byte)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -758,12 +758,26 @@ namespace PKHeX.Core
|
|||
|
||||
const int brSize = 0x40;
|
||||
int bit = pkm.Species - 1;
|
||||
byte mask = (byte) (1 << (bit&7));
|
||||
int ofs = PokeDex + bit>>3 + 0x4;
|
||||
|
||||
// Set the Species Owned Flag
|
||||
Data[PokeDex + brSize*0 + bit/8 + 0x4] |= (byte) (1 << (bit%8));
|
||||
Data[ofs + brSize*0] |= mask;
|
||||
|
||||
// Set the Species Seen Flag
|
||||
Data[PokeDex + brSize*1 + bit/8 + 0x4] |= (byte) (1 << (bit%8));
|
||||
// Check if already Seen
|
||||
int gr = pkm.PersonalInfo.Gender;
|
||||
if (gr != 0 && gr < 254) // Not genderless or fixed gender
|
||||
{
|
||||
bool m = (Data[ofs + brSize*1] & mask) != 0;
|
||||
bool f = (Data[ofs + brSize*2] & mask) != 0;
|
||||
if (!(m || f)) // not yet seen
|
||||
{
|
||||
// Set OTHER gender seen bit so it appears second
|
||||
int gender = pkm.Gender & 1;
|
||||
gender ^= 1; // other gender
|
||||
Data[ofs + brSize*(1 + gender)] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
int FormOffset1 = PokeDex + 0x108;
|
||||
int PokeDexLanguageFlags = FormOffset1 + 0x20;
|
||||
|
|
|
@ -524,6 +524,16 @@ namespace PKHeX.Core
|
|||
BitConverter.GetBytes(value).CopyTo(Data, JoinFestaData + 0x50C);
|
||||
}
|
||||
}
|
||||
public string FestivalPlazaName
|
||||
{
|
||||
get { return Util.TrimFromZero(Encoding.Unicode.GetString(Data, JoinFestaData + 0x510, 0x2A)); }
|
||||
set
|
||||
{
|
||||
const int max = 20;
|
||||
if (value.Length > max) value = value.Substring(0, max);
|
||||
Encoding.Unicode.GetBytes(value.PadRight(value.Length + 1, '\0')).CopyTo(Data, JoinFestaData + 0x510);
|
||||
}
|
||||
}
|
||||
|
||||
public override int PlayedHours
|
||||
{
|
||||
|
|
|
@ -1002,5 +1002,74 @@ namespace PKHeX.Core
|
|||
|
||||
return new Tuple<uint, uint>(TID, SID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SaveFile"/> via decryption using a stored xorpad.
|
||||
/// </summary>
|
||||
/// <param name="input">Encrypted byte array of savedata to decrypt.</param>
|
||||
/// <param name="XORpads">Array of possible paths to check for xorpad compatibility.</param>
|
||||
/// <returns>Returns a <see cref="SaveFile"/> if decryption was successful, else null.</returns>
|
||||
public static SaveFile getSAVfromXORpads(byte[] input, string[] XORpads)
|
||||
{
|
||||
byte[] savID = new byte[0x10];
|
||||
Array.Copy(input, 0x10, savID, 0, 0x10);
|
||||
int[] sizes = { SIZE_G6XY, SIZE_G6ORAS, SIZE_G7SM };
|
||||
|
||||
foreach (var file in XORpads)
|
||||
{
|
||||
// Check if xorpad
|
||||
FileInfo fi = new FileInfo(file);
|
||||
|
||||
string filename = fi.Name.ToLower();
|
||||
if (!filename.Contains("xorpad") && !filename.Contains("key"))
|
||||
continue;
|
||||
|
||||
var length = fi.Length;
|
||||
if (length != 0x10009C && length != 0x100000)
|
||||
continue;
|
||||
|
||||
// Fix xorpad alignment
|
||||
byte[] xorpad = File.ReadAllBytes(file);
|
||||
if (xorpad.Length == 0x10009C) // Trim off Powersaves' header
|
||||
{
|
||||
Array.Copy(xorpad, 0x9C, xorpad, 0, 0x100000);
|
||||
Array.Resize(ref xorpad, 0x100000);
|
||||
}
|
||||
|
||||
// Check if encrypted 00's match save
|
||||
if (!xorpad.Skip(0x10).Take(0x10).SequenceEqual(savID))
|
||||
continue;
|
||||
|
||||
// Set up Decrypted File
|
||||
const int mainOffset = 0x5400;
|
||||
int maxSize = sizes.Max();
|
||||
byte[] decryptedPS = new byte[maxSize];
|
||||
Array.Copy(input, mainOffset, decryptedPS, 0, decryptedPS.Length);
|
||||
|
||||
// xor through and decrypt
|
||||
for (int z = 0; z < decryptedPS.Length; z++)
|
||||
decryptedPS[z] ^= xorpad[mainOffset + z];
|
||||
|
||||
// Weakly check the validity of the decrypted content
|
||||
int i; for (i = 0; i < sizes.Length; i++)
|
||||
{
|
||||
if (BitConverter.ToUInt32(decryptedPS, sizes[i] - 0x1F0) != BEEF)
|
||||
continue;
|
||||
Array.Resize(ref decryptedPS, sizes[i]);
|
||||
break;
|
||||
}
|
||||
if (i == sizes.Length)
|
||||
continue;
|
||||
|
||||
// Save file is now decrypted!
|
||||
var SAV = getVariantSAV(decryptedPS);
|
||||
if (SAV == null)
|
||||
continue;
|
||||
|
||||
SAV.FileName = file;
|
||||
return SAV;
|
||||
}
|
||||
return null; // no xorpad compatible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,6 +175,8 @@ namespace PKHeX.Core
|
|||
else
|
||||
{
|
||||
int numStored = Data[Offset];
|
||||
if (numStored > PouchDataSize) // uninitialized yellow (0xFF), sanity check for out-of-bounds values
|
||||
numStored = 0;
|
||||
for (int i = 0; i < numStored; i++)
|
||||
{
|
||||
switch (Type)
|
||||
|
|
|
@ -63,5 +63,40 @@ namespace PKHeX.Core
|
|||
result[--i] = data[o++];
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a 32-bit signed integer converted from bytes in a Binary Coded Decimal format byte array.
|
||||
/// </summary>
|
||||
/// <param name="input">Input byte array to read from.</param>
|
||||
/// <param name="offset">Offset to start reading at.</param>
|
||||
/// <param name="length">Length of array to read.</param>
|
||||
public static int BCDToInt32(byte[] input, int offset, int length)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = offset; i < offset + length; i++)
|
||||
{
|
||||
byte p = input[i];
|
||||
result *= 100;
|
||||
result += 10 * (p >> 4);
|
||||
result += p & 0xf;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the specified 32-bit signed integer value as an array of Binary Coded Decimal format bytes.
|
||||
/// </summary>
|
||||
/// <param name="input">32-bit signed integer to convert.</param>
|
||||
/// <param name="size">Desired size of returned array.</param>
|
||||
public static byte[] Int32ToBCD(int input, int size)
|
||||
{
|
||||
byte[] result = new byte[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
int p = input%100;
|
||||
input /= 100;
|
||||
result[size - i - 1] = (byte)(p/10 << 4 | p%10);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
12
README.md
|
@ -5,9 +5,9 @@ PKHeX
|
|||
Pokémon core series save editor, programmed in [C#](https://en.wikipedia.org/wiki/C_Sharp_%28programming_language%29).
|
||||
|
||||
Supports the following files:
|
||||
* Save files ("main", .sav)
|
||||
* Individual Pokémon entity files (.pk*)
|
||||
* Mystery Gift files (.pgt, .pcd, .pgf, .wc*) including conversion to .pk*
|
||||
* Save files ("main", \*.sav, \*.dsv, \*.dat, \*.gci)
|
||||
* Individual Pokémon entity files (.pk\*)
|
||||
* Mystery Gift files (.pgt, .pcd, .pgf, .wc\*) including conversion to .pk\*
|
||||
* Importing teams from Decrypted 3DS Battle Videos
|
||||
* Transferring from one generation to another, converting formats along the way.
|
||||
|
||||
|
@ -16,7 +16,9 @@ The interface can be translated with resource/external text files so that differ
|
|||
|
||||
Pokémon Showdown sets and QR codes can be imported/exported to assist in sharing.
|
||||
|
||||
Nintendo 3DS savedata containers use an AES MAC that cannot be emulated without the 3DS's keys, thus a resigning service is required (svdt, save_manager, or SaveDataFiler).
|
||||
Nintendo 3DS savedata containers use an AES MAC that cannot be emulated without the 3DS's keys, thus a resigning service is required ([svdt](https://github.com/meladroit/svdt), save_manager, [JKSM](https://github.com/J-D-K/JKSM), or SaveDataFiler).
|
||||
|
||||
**We do not support or condone cheating at the expense of others. Do not use significantly hacked Pokémon in battle or in trades with those who are unaware hacked Pokémon are in use.**
|
||||
|
||||
## Screenshots
|
||||
|
||||
|
@ -42,4 +44,4 @@ PKHeX can be opened with IDEs such as [Visual Studio](https://www.visualstudio.c
|
|||
|
||||
### GNU/Linux
|
||||
|
||||
Install MonoDevelop and [Mono](http://www.mono-project.com/) runtime with `flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref`. GNU/Linux is not the main Operating System of developers of this program so there may be bugs; some may come from non GNU/Linux specific code of Mono (so developers using *BSD, Windows and OS X should be able to reproduce them).
|
||||
Install [MonoDevelop](http://www.monodevelop.com/) and [Mono Runtime](http://www.mono-project.com/) with `flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref`. GNU/Linux is not the main Operating System of developers of this program so there may be bugs; some may come from non GNU/Linux specific code of Mono (so developers using *BSD, Windows and OS X should be able to reproduce them).
|
||||
|
|