diff --git a/PKHeX.WinForms/MainWindow/Main.Designer.cs b/PKHeX.WinForms/MainWindow/Main.Designer.cs index 9c8c90021e4..0ccc901dd7b 100644 --- a/PKHeX.WinForms/MainWindow/Main.Designer.cs +++ b/PKHeX.WinForms/MainWindow/Main.Designer.cs @@ -926,6 +926,7 @@ public void InitializeComponent() 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 // diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index 0dab33288d0..f74ce1074e0 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -691,7 +691,9 @@ private void openQuick(string path, bool force = false) 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); } @@ -1940,8 +1942,12 @@ private void clickMetLocation(object sender, EventArgs e) 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; @@ -1950,21 +1956,37 @@ private void clickMetLocation(object sender, EventArgs e) 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 {"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 (suggestion.Count == 1) // no suggestion + return; - if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, suggestion) != DialogResult.Yes) + string suggest = string.Join(Environment.NewLine, suggestion); + if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, suggest) != DialogResult.Yes) return; - TB_MetLevel.Text = level.ToString(); - CB_MetLocation.SelectedValue = location; + if (pkm.Format >= 3) + { + TB_MetLevel.Text = level.ToString(); + CB_MetLocation.SelectedValue = location; + } if (pkm.CurrentLevel < minlvl) TB_Level.Text = minlvl.ToString(); @@ -3825,6 +3847,7 @@ private void loadBoxesFromDB(string path) 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) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.Designer.cs index 34948d403ad..47b20539f05 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.Designer.cs @@ -104,6 +104,9 @@ private void InitializeComponent() 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 @@ private void InitializeComponent() 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 @@ private void InitializeComponent() 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 @@ private void InitializeComponent() 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 @@ private void InitializeComponent() 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 @@ private void InitializeComponent() // // 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 @@ private void InitializeComponent() 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 @@ private void InitializeComponent() this.B_Fashion.UseVisualStyleBackColor = true; this.B_Fashion.Click += new System.EventHandler(this.B_Fashion_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 + // TB_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; + 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"; // - // B_GenTID + // L_PlazaName // - 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 @@ private void InitializeComponent() ((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 @@ private void InitializeComponent() 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; } } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs index 7ab41d9c644..487f713eecb 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs @@ -182,6 +182,7 @@ private void getTextBoxes() 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 @@ private void save() 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) diff --git a/PKHeX/Legality/Analysis.cs b/PKHeX/Legality/Analysis.cs index 4fc59ee639e..394e08a1642 100644 --- a/PKHeX/Legality/Analysis.cs +++ b/PKHeX/Legality/Analysis.cs @@ -70,8 +70,8 @@ public LegalityAnalysis(PKM pk) 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(); } @@ -87,11 +87,12 @@ private void AddLine(CheckResult chk) private void parsePK1(PKM pk) { pkm = pk; - if (!pkm.IsOriginValid()) + if (!pkm.IsOriginValid) { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } updateEncounterChain(); updateMoveLegality(); + updateEncounterInfo(); verifyNickname(); verifyDVs(); verifyG1OT(); @@ -99,23 +100,25 @@ private void parsePK1(PKM pk) 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(); } @@ -141,16 +144,17 @@ private void updateEncounterChain() Parse.Add(Encounter); EvoChain = Legal.getEvolutionChain(pkm, EncounterMatch); } - private void updateChecks() + private void updateEncounterInfo() { EncounterMatch = EncounterMatch ?? pkm.Species; EncounterType = EncounterMatch?.GetType(); if (EncounterType == typeof (MysteryGift)) EncounterType = EncounterType.BaseType; + } + private void updateChecks() + { History = verifyHistory(); - - AddLine(Encounter); AddLine(History); verifyECPID(); @@ -231,7 +235,7 @@ private string getVerboseLegalityReport() 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) @@ -249,7 +253,7 @@ public int[] getSuggestedRelearn() } public int[] getSuggestedMoves(bool tm, bool tutor, bool reminder) { - if (pkm == null || !pkm.IsOriginValid()) + if (pkm == null || !pkm.IsOriginValid) return null; if (!Parsed) return new int[4]; @@ -261,24 +265,30 @@ public EncounterStatic getSuggestedMetInfo() 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) @@ -311,5 +321,18 @@ private static int getSuggestedEggMetLocation(PKM pkm) } 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; + } } } diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index e86af2c1c76..d51396610ce 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -25,6 +25,7 @@ internal enum CheckIdentifier Gender, EVs, Language, + Nickname, Trainer, IVs, None, @@ -50,7 +51,7 @@ public class CheckResult 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; @@ -143,12 +144,12 @@ private void verifyNickname() // 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; } @@ -159,7 +160,7 @@ private void verifyNickname() 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) @@ -193,7 +194,7 @@ private void verifyNickname() 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 un-implemented.", CheckIdentifier.Nickname); return; } @@ -212,11 +213,11 @@ private void verifyNickname() 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; } @@ -224,11 +225,11 @@ private void verifyNickname() 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; } @@ -245,15 +246,15 @@ private void verifyNickname() 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); + AddLine(Severity.Valid, "Nickname does not match another species name.", CheckIdentifier.Nickname); } 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.EVs); + AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.Nickname); } else { @@ -262,9 +263,9 @@ private void verifyNickname() || PKX.SpeciesLang[pkm.Language][pkm.Species] == nickname; if (!match) - AddLine(Severity.Invalid, "Nickname does not match species name.", CheckIdentifier.EVs); + AddLine(Severity.Invalid, "Nickname does not match species name.", CheckIdentifier.Nickname); else - AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.EVs); + AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.Nickname); } } private void verifyEVs() @@ -571,7 +572,7 @@ private CheckResult verifyEncounter() var result = verifyEncounterG1(); if (pkm.Format > 2) // transported to 7+ - Parse.Add(verifyVCEncounter(baseSpecies)); + AddLine(verifyVCEncounter(baseSpecies)); return result; } @@ -621,11 +622,19 @@ private CheckResult verifyVCEncounter(int baseSpecies) species = baseSpecies; // Check existing EncounterMatch - if (EncounterMatch == null) - Parse.Add(new CheckResult(Severity.Invalid, "Unable to match an encounter from origin game.", CheckIdentifier.Encounter)); + string oldEncounter = (EncounterMatch as IEncounterable)?.Name; + if (oldEncounter == null) + return new CheckResult(Severity.Invalid, "Unable to match an encounter from origin game.", CheckIdentifier.Encounter); + + AddLine(new CheckResult(Severity.Valid, "Origin game encounter: " + oldEncounter, CheckIdentifier.Encounter)); var s = EncounterMatch as EncounterStatic; if (s != null && s.Version == GameVersion.SPECIAL) - Parse.Add(new CheckResult(Severity.Invalid, "Special encounter is not available to Virtual Console games.", CheckIdentifier.Encounter)); + { + 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 { @@ -636,6 +645,7 @@ private CheckResult verifyVCEncounter(int baseSpecies) Fateful = species == 151, Location = 30013, EggLocation = 0, + Version = GameVersion.RBY }; var ematch = (EncounterStatic) EncounterMatch; @@ -1555,7 +1565,7 @@ private void verifyHTMemory() 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) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index bb26b8de172..27fd13c3e21 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -400,26 +400,18 @@ private static EvolutionTree getEvolutionTable(PKM pkm) } } - private static int getMaxSpeciesOrigin(int generation) + internal static int getMaxSpeciesOrigin(int generation) { switch (generation) { - case 1: - return MaxSpeciesID_1; - case 2: - return MaxSpeciesID_2; - case 3: - return MaxSpeciesID_3; - case 4: - return MaxSpeciesID_4; - case 5: - return MaxSpeciesID_5; - case 6: - return MaxSpeciesID_6; - case 7: - return MaxSpeciesID_7; - default: - return MaxSpeciesID_7; + case 1: return MaxSpeciesID_1; + case 2: return MaxSpeciesID_2; + case 3: return MaxSpeciesID_3; + case 4: return MaxSpeciesID_4; + case 5: return MaxSpeciesID_5; + case 6: return MaxSpeciesID_6; + case 7: return MaxSpeciesID_7; + default: return -1; } } @@ -637,11 +629,11 @@ where slots.Any() select new EncounterArea { Location = area.Location, Slots = slots, - }).FirstOrDefault(); + }).OrderBy(area => area.Slots.Min(x => x.LevelMin)).FirstOrDefault(); } internal static EncounterStatic getStaticLocation(PKM pkm) { - return getStaticEncounters(pkm).FirstOrDefault(); + return getStaticEncounters(pkm, 100).OrderBy(s => s.Level).FirstOrDefault(); } public static int getLowestLevel(PKM pkm, int refSpecies = -1) @@ -889,7 +881,7 @@ private static IEnumerable getValidEncounterSlots(PKM pkm, Encoun List slotdata = new List(); // Get Valid levels - IEnumerable vs = getValidPreEvolutions(pkm); + IEnumerable vs = getValidPreEvolutions(pkm, ignoreLevel ? 100 : -1, ignoreLevel); // Get slots where pokemon can exist bool ignoreSlotLevel = ignoreLevel; @@ -1028,11 +1020,18 @@ private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form { List r = new List { 0 }; int gen = pkm.GenNumber; - if (pkm.Format < 3) - gen = 1; + if (pkm.GenNumber < 3) + { + int max = pkm.Format < 3 ? 2 : 1; + for (; gen <= max; gen++) + if (pkm.InhabitedGeneration(gen, species)) + r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, gen, MoveReminder)); + gen = 7; + } for (; gen <= pkm.Format; gen++) - r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, gen, MoveReminder)); + if (pkm.InhabitedGeneration(gen)) + r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, gen, MoveReminder)); return r.Distinct(); } private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, int Generation, bool MoveReminder) @@ -1118,6 +1117,9 @@ private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form } private static IEnumerable getEggMoves(PKM pkm, int species, int formnum) { + if (!pkm.InhabitedGeneration(pkm.GenNumber, species)) + return new List(); + switch (pkm.GenNumber) { case 6: // entries per species diff --git a/PKHeX/Legality/Structures/EncounterSlot.cs b/PKHeX/Legality/Structures/EncounterSlot.cs index ae020cf51a8..615b081976d 100644 --- a/PKHeX/Legality/Structures/EncounterSlot.cs +++ b/PKHeX/Legality/Structures/EncounterSlot.cs @@ -25,7 +25,16 @@ public EncounterSlot(EncounterSlot template) 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 { diff --git a/PKHeX/Legality/Structures/EncounterStatic.cs b/PKHeX/Legality/Structures/EncounterStatic.cs index 556a36af1b4..66184458f04 100644 --- a/PKHeX/Legality/Structures/EncounterStatic.cs +++ b/PKHeX/Legality/Structures/EncounterStatic.cs @@ -26,6 +26,15 @@ public class EncounterStatic : IEncounterable 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})"; + } + } } } diff --git a/PKHeX/Legality/Tables1.cs b/PKHeX/Legality/Tables1.cs index 06e410fea54..5079716b6bc 100644 --- a/PKHeX/Legality/Tables1.cs +++ b/PKHeX/Legality/Tables1.cs @@ -45,25 +45,25 @@ public static partial class Legal internal static readonly EncounterStatic[] Encounter_RBY = { - new EncounterStatic { Species = 001, Level = 05 }, // Bulbasaur - new EncounterStatic { Species = 004, Level = 05 }, // Charmander - new EncounterStatic { Species = 007, Level = 05 }, // Squirtle + 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 }, // Nidorina (Red Game Corner) - new EncounterStatic { Species = 033, Level = 17 }, // Nidorino (Blue[EN] / Green[JP] Game Corner) - new EncounterStatic { Species = 035, Level = 08 }, // Clefairy (Red Game Corner) - new EncounterStatic { Species = 036, Level = 24 }, // Clefable (Blue[JP] Game Corner) - new EncounterStatic { Species = 037, Level = 18 }, // Vulpix (Yellow Game Corner) - new EncounterStatic { Species = 040, Level = 22 }, // Wigglytuff (Yellow Game Corner) - new EncounterStatic { Species = 063, Level = 06 }, // Abra (Blue[EN] / Green[JP] Game Corner) - new EncounterStatic { Species = 116, Level = 18 }, // Horsea (Blue[JP] Game Corner) - new EncounterStatic { Species = 123, Level = 25 }, // Scyther (Red Game Corner) - new EncounterStatic { Species = 127, Level = 20 }, // Pinsir (Blue[EN] / Green[JP] Game Corner) - new EncounterStatic { Species = 137, Level = 18 }, // Porygon (Blue[EN] / Green[JP] Game Corner) - new EncounterStatic { Species = 147, Level = 18 }, // Dratini (Red Game Corner) - new EncounterStatic { Species = 148, Level = 30 }, // Dragonair (Blue[JP] 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) @@ -78,24 +78,23 @@ public static partial class Legal // 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 }, // Magikarp - new EncounterStatic { Species = 143, Level = 30 }, // Snorlax - new EncounterStatic { Species = 106, Level = 30 }, // Hitmonlee - new EncounterStatic { Species = 107, Level = 30 }, // Hitmonchan - - new EncounterStatic { Species = 131, Level = 15 }, // Lapras - new EncounterStatic { Species = 138, Level = 30 }, // Omanyte - new EncounterStatic { Species = 140, Level = 30 }, // Kabuto - new EncounterStatic { Species = 142, Level = 30 }, // Aerodactyl + 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 }, // Articuno - new EncounterStatic { Species = 145, Level = 50 }, // Zapdos - new EncounterStatic { Species = 146, Level = 50 }, // Moltres + 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 }, // Mewtwo + new EncounterStatic { Species = 150, Level = 70, Version = GameVersion.RBY }, // Mewtwo - new EncounterStatic { Species = 133, Level = 25 }, // Eevee + 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) @@ -104,6 +103,7 @@ public static partial class Legal // 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 = { diff --git a/PKHeX/MysteryGifts/WC6.cs b/PKHeX/MysteryGifts/WC6.cs index 39feb11ebfb..c19ba173b98 100644 --- a/PKHeX/MysteryGifts/WC6.cs +++ b/PKHeX/MysteryGifts/WC6.cs @@ -278,6 +278,7 @@ public override PKM convertToPKM(SaveFile SAV) 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 @@ public override PKM convertToPKM(SaveFile SAV) 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 @@ public override PKM convertToPKM(SaveFile SAV) 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, diff --git a/PKHeX/MysteryGifts/WC7.cs b/PKHeX/MysteryGifts/WC7.cs index 14600177ab8..091fb5c1d6c 100644 --- a/PKHeX/MysteryGifts/WC7.cs +++ b/PKHeX/MysteryGifts/WC7.cs @@ -297,6 +297,7 @@ public override PKM convertToPKM(SaveFile SAV) 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 +306,11 @@ public override PKM convertToPKM(SaveFile SAV) 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 +354,7 @@ public override PKM convertToPKM(SaveFile SAV) 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, diff --git a/PKHeX/PKM/PKM.cs b/PKHeX/PKM/PKM.cs index 78d57d803ad..3299c6c67f0 100644 --- a/PKHeX/PKM/PKM.cs +++ b/PKHeX/PKM/PKM.cs @@ -403,6 +403,7 @@ public virtual int HPType } // 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; @@ -411,25 +412,8 @@ public virtual int HPType public virtual bool WasIngameTrade => Met_Location == 30001; public virtual bool IsUntraded => Format >= 6 && string.IsNullOrWhiteSpace(HT_Name) && GenNumber == Format; public virtual bool IsNative => GenNumber == Format; - public virtual bool IsOriginValid() - { - switch (Format) - { - case 1: return Species <= Legal.MaxSpeciesID_1; - case 2: return Species <= Legal.MaxSpeciesID_2; - } - 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 { } } @@ -462,26 +446,33 @@ public void HyperTrainInvert(int stat) /// Checks if the could inhabit a set of games. /// /// Set of games. + /// /// True if could inhabit, False if not. - 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 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) + 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: return VC; + case 2: return 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; } diff --git a/PKHeX/PKM/PKX.cs b/PKHeX/PKM/PKX.cs index 5a874810263..c4ac6e50a48 100644 --- a/PKHeX/PKM/PKX.cs +++ b/PKHeX/PKM/PKX.cs @@ -2585,7 +2585,7 @@ public static string getG1ConvertedString(byte[] strdata, bool jp) 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())); } /// diff --git a/PKHeX/Resources/img/Pokemon Sprites/208.png b/PKHeX/Resources/img/Pokemon Sprites/208.png index e787ca9fb59..685697b8117 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/208.png and b/PKHeX/Resources/img/Pokemon Sprites/208.png differ diff --git a/PKHeX/Resources/img/Pokemon Sprites/252.png b/PKHeX/Resources/img/Pokemon Sprites/252.png index 67d905d1f9e..394c59d89d5 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/252.png and b/PKHeX/Resources/img/Pokemon Sprites/252.png differ diff --git a/PKHeX/Resources/img/Pokemon Sprites/256.png b/PKHeX/Resources/img/Pokemon Sprites/256.png index 41794051e5d..3d35be1a15a 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/256.png and b/PKHeX/Resources/img/Pokemon Sprites/256.png differ diff --git a/PKHeX/Resources/img/Pokemon Sprites/257.png b/PKHeX/Resources/img/Pokemon Sprites/257.png index e5e14d485a6..4bbd9bc5f01 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/257.png and b/PKHeX/Resources/img/Pokemon Sprites/257.png differ diff --git a/PKHeX/Resources/img/Pokemon Sprites/272.png b/PKHeX/Resources/img/Pokemon Sprites/272.png index e45cebc2eb3..2b7c686c3db 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/272.png and b/PKHeX/Resources/img/Pokemon Sprites/272.png differ diff --git a/PKHeX/Resources/img/Pokemon Sprites/274.png b/PKHeX/Resources/img/Pokemon Sprites/274.png index 337cb5b7366..b64383665d8 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/274.png and b/PKHeX/Resources/img/Pokemon Sprites/274.png differ diff --git a/PKHeX/Resources/img/Pokemon Sprites/275.png b/PKHeX/Resources/img/Pokemon Sprites/275.png index 953c72188ae..200cc81a127 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/275.png and b/PKHeX/Resources/img/Pokemon Sprites/275.png differ diff --git a/PKHeX/Resources/img/Pokemon Sprites/302.png b/PKHeX/Resources/img/Pokemon Sprites/302.png index ceb5f3725ea..671c0f889f9 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/302.png and b/PKHeX/Resources/img/Pokemon Sprites/302.png differ diff --git a/PKHeX/Resources/img/Pokemon Sprites/376.png b/PKHeX/Resources/img/Pokemon Sprites/376.png index 3d660e58021..e7edf996ef8 100644 Binary files a/PKHeX/Resources/img/Pokemon Sprites/376.png and b/PKHeX/Resources/img/Pokemon Sprites/376.png differ diff --git a/PKHeX/Saves/SAV7.cs b/PKHeX/Saves/SAV7.cs index 1719079370b..bbead9aff87 100644 --- a/PKHeX/Saves/SAV7.cs +++ b/PKHeX/Saves/SAV7.cs @@ -524,6 +524,16 @@ private uint TotalFestaCoins 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 { diff --git a/README.md b/README.md index 6a59cfcd58f..f3f908fe2aa 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ 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). ## Screenshots @@ -42,4 +42,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).