From f282711e35ceeb61ae4cfada3b5c5b8197632a14 Mon Sep 17 00:00:00 2001
From: Kurt <kaphotics@gmail.com>
Date: Wed, 25 Jan 2017 22:51:52 -0800
Subject: [PATCH] Cleanup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Use S/M met locations for Pokémon GO origin
Changing to VC1 or GO now autofills met location
Un-alphabetize RGBY games and move to end of games list (+go)
Mark unused region names (Kanto string appears twice in text bank 3,
30013 is used)
Move hypertraining stat toggling to pkm object

shift 1->7 logic to repeat less operations
add more 1->7 logic pertaining to memories
add RefreshAbility method (0 based input, not 1/2/4)
---
 PKHeX.WinForms/MainWindow/Main.cs             | 308 +++++++-----------
 .../Subforms/Save Editors/SAV_BoxViewer.cs    | 134 ++++----
 PKHeX/Game/GameInfo.cs                        |  11 +-
 PKHeX/Legality/Tables.cs                      |   3 +-
 PKHeX/PKM/PK1.cs                              |  46 +--
 PKHeX/PKM/PK7.cs                              |  12 +-
 PKHeX/PKM/PKM.cs                              |  24 +-
 PKHeX/PKM/PKMConverter.cs                     |   6 +-
 8 files changed, 261 insertions(+), 283 deletions(-)

diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs
index 7d157e5ff..ecd080132 100644
--- a/PKHeX.WinForms/MainWindow/Main.cs
+++ b/PKHeX.WinForms/MainWindow/Main.cs
@@ -238,8 +238,9 @@ namespace PKHeX.WinForms
         public static string DatabasePath => Path.Combine(WorkingDirectory, "pkmdb");
         public static string MGDatabasePath => Path.Combine(WorkingDirectory, "mgdb");
         private static string BackupPath => Path.Combine(WorkingDirectory, "bak");
-        private static string ThreadPath => @"https://projectpokemon.org/PKHeX/";
-        private static string VersionPath => @"https://raw.githubusercontent.com/kwsch/PKHeX/master/PKHeX/Resources/text/version.txt";
+        private const string ThreadPath = @"https://projectpokemon.org/PKHeX/";
+        private const string VersionPath = @"https://raw.githubusercontent.com/kwsch/PKHeX/master/PKHeX/Resources/text/version.txt";
+        private const string QR6Path = @"http://loadcode.projectpokemon.org/b1s1.html#"; // Rehosted with permission from LC/MS -- massive thanks!
 
         #endregion
 
@@ -1193,7 +1194,7 @@ namespace PKHeX.WinForms
                 updateOriginGame(null, null);
 
             // Refresh PK* conversion info
-            PKMConverter.updateConfig(SAV.SubRegion, SAV.Country, SAV.ConsoleRegion, SAV.OT, SAV.Gender);
+            PKMConverter.updateConfig(SAV.SubRegion, SAV.Country, SAV.ConsoleRegion, SAV.OT, SAV.Gender, SAV.Language);
 
             if (WindowTranslationRequired) // force update -- re-added controls may be untranslated
                 WinFormsUtil.TranslateInterface(this, curlanguage);
@@ -1593,22 +1594,23 @@ namespace PKHeX.WinForms
         }
         private void setMarkings()
         {
+            Func<bool, double> getOpacity = b => b ? 1 : 0.175;
             PictureBox[] pba = { PB_Mark1, PB_Mark2, PB_Mark3, PB_Mark4, PB_Mark5, PB_Mark6 };
             for (int i = 0; i < pba.Length; i++)
-                pba[i].Image = ImageUtil.ChangeOpacity(pba[i].InitialImage, pkm.Markings[i] != 0 ? 1 : 0.1);
+                pba[i].Image = ImageUtil.ChangeOpacity(pba[i].InitialImage, getOpacity(pkm.Markings[i] != 0));
 
-            PB_MarkShiny.Image = ImageUtil.ChangeOpacity(PB_MarkShiny.InitialImage, !BTN_Shinytize.Enabled ? 1 : 0.1);
-            PB_MarkCured.Image = ImageUtil.ChangeOpacity(PB_MarkCured.InitialImage, CHK_Cured.Checked ? 1 : 0.1);
+            PB_MarkShiny.Image = ImageUtil.ChangeOpacity(PB_MarkShiny.InitialImage, getOpacity(!BTN_Shinytize.Enabled));
+            PB_MarkCured.Image = ImageUtil.ChangeOpacity(PB_MarkCured.InitialImage, getOpacity(CHK_Cured.Checked));
             
-            PB_MarkPentagon.Image = ImageUtil.ChangeOpacity(PB_MarkPentagon.InitialImage, pkm.Gen6 ? 1 : 0.1);
+            PB_MarkPentagon.Image = ImageUtil.ChangeOpacity(PB_MarkPentagon.InitialImage, getOpacity(pkm.Gen6));
 
             // Gen7 Markings
             if (pkm.Format != 7)
                 return;
 
-            PB_MarkAlola.Image = ImageUtil.ChangeOpacity(PB_MarkAlola.InitialImage, pkm.Gen7 ? 1 : 0.1);
-            PB_MarkVC.Image = ImageUtil.ChangeOpacity(PB_MarkVC.InitialImage, pkm.VC ? 1 : 0.1);
-            PB_MarkHorohoro.Image = ImageUtil.ChangeOpacity(PB_MarkHorohoro.InitialImage, pkm.Horohoro ? 1 : 0.1);
+            PB_MarkAlola.Image = ImageUtil.ChangeOpacity(PB_MarkAlola.InitialImage, getOpacity(pkm.Gen7));
+            PB_MarkVC.Image = ImageUtil.ChangeOpacity(PB_MarkVC.InitialImage, getOpacity(pkm.VC));
+            PB_MarkHorohoro.Image = ImageUtil.ChangeOpacity(PB_MarkHorohoro.InitialImage, getOpacity(pkm.Horohoro));
 
             for (int i = 0; i < pba.Length; i++)
             {
@@ -1657,8 +1659,7 @@ namespace PKHeX.WinForms
                 if (!verifiedPKM()) return;
                 PKM pkx = preparePKM();
                 byte[] ekx = pkx.EncryptedBoxData;
-
-                const string server = "http://loadcode.projectpokemon.org/b1s1.html#"; // Rehosted with permission from LC/MS -- massive thanks!
+                
                 Image qr;
                 switch (pkx.Format)
                 {
@@ -1666,7 +1667,7 @@ namespace PKHeX.WinForms
                         qr = QR.GenerateQRCode7((PK7) pkx);
                         break;
                     default:
-                        qr = QR.getQRImage(ekx, pkx.Format == 6 ? server : "null/#");
+                        qr = QR.getQRImage(ekx, pkx.Format == 6 ? QR6Path : "null/#");
                         break;
                 }
 
@@ -1780,27 +1781,7 @@ namespace PKHeX.WinForms
                 else
                 {
                     var index = Array.IndexOf(new[] {TB_HPIV, TB_ATKIV, TB_DEFIV, TB_SPAIV, TB_SPDIV, TB_SPEIV}, sender);
-                    switch (index)
-                    {
-                        case 0:
-                            pkm.HT_HP ^= true;
-                            break;
-                        case 1:
-                            pkm.HT_ATK ^= true;
-                            break;
-                        case 2:
-                            pkm.HT_DEF ^= true;
-                            break;
-                        case 3:
-                            pkm.HT_SPA ^= true;
-                            break;
-                        case 4:
-                            pkm.HT_SPD ^= true;
-                            break;
-                        case 5:
-                            pkm.HT_SPE ^= true;
-                            break;
-                    }
+                    pkm.HyperTrainInvert(index);
                     updateIVs(sender, e);
                 }
             else if (ModifierKeys == Keys.Alt)
@@ -2160,26 +2141,13 @@ namespace PKHeX.WinForms
         private void updateRandomEVs(object sender, EventArgs e)
         {
             changingFields = true;
-            if (ModifierKeys == Keys.Control || ModifierKeys == Keys.Shift)
-            {
-                // Max EVs
-                TB_HPEV.Text = 0.ToString();
-                TB_ATKEV.Text = 0.ToString();
-                TB_DEFEV.Text = 0.ToString();
-                TB_SPAEV.Text = 0.ToString();
-                TB_SPDEV.Text = 0.ToString();
-                TB_SPEEV.Text = 0.ToString();
-            }
-            else
-            {
-                var evs = PKX.getRandomEVs(SAV.Generation);
-                TB_HPEV.Text = evs[0].ToString();
-                TB_ATKEV.Text = evs[1].ToString();
-                TB_DEFEV.Text = evs[2].ToString();
-                TB_SPAEV.Text = evs[3].ToString();
-                TB_SPDEV.Text = evs[4].ToString();
-                TB_SPEEV.Text = evs[5].ToString();
-            }
+
+            var tb = new[] {TB_HPEV, TB_ATKEV, TB_DEFEV, TB_SPAEV, TB_SPDEV, TB_SPEEV};
+            bool zero = ModifierKeys == Keys.Control || ModifierKeys == Keys.Shift;
+            var evs = zero ? new uint[6] : PKX.getRandomEVs(SAV.Generation);
+            for (int i = 0; i < 6; i++)
+                tb[i].Text = evs[i].ToString();
+
             changingFields = false;
             updateEVs(null, null);
         }
@@ -2426,7 +2394,17 @@ namespace PKHeX.WinForms
                 CB_MetLocation.DisplayMember = "Text";
                 CB_MetLocation.ValueMember = "Value";
                 CB_MetLocation.DataSource = new BindingSource(met_list, null);
-                CB_MetLocation.SelectedIndex = 0; // transporter or pal park for past gen pkm
+
+                int metLoc = 0; // transporter or pal park for past gen pkm
+                switch (newTrack)
+                {
+                    case GameVersion.GO: metLoc = 30012; break;
+                    case GameVersion.RBY: metLoc = 30013; break;
+                }
+                if (metLoc != 0)
+                    CB_MetLocation.SelectedValue = metLoc;
+                else
+                    CB_MetLocation.SelectedIndex = metLoc;
 
                 var egg_list = GameInfo.getLocationList(Version, SAV.Generation, egg:true);
                 CB_EggLocation.DisplayMember = "Text";
@@ -3116,13 +3094,10 @@ namespace PKHeX.WinForms
 
         private void Main_FormClosing(object sender, FormClosingEventArgs e)
         {
-            if (SAV.Edited)
-            {
-                if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Any unsaved changes will be lost.", "Are you sure you want to close PKHeX?") != DialogResult.Yes)
-                {
-                    e.Cancel = true;
-                }
-            }
+            if (!SAV.Edited)
+                return;
+            if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Any unsaved changes will be lost.", "Are you sure you want to close PKHeX?"))
+                e.Cancel = true;
         }
         #endregion
 
@@ -3953,10 +3928,17 @@ namespace PKHeX.WinForms
         }
 
         // Subfunction Save Buttons //
-        private void B_OpenWondercards_Click(object sender, EventArgs e)
-        {
-            new SAV_Wondercard(sender as MysteryGift).ShowDialog();
-        }
+        private void B_OpenWondercards_Click(object sender, EventArgs e) => new SAV_Wondercard(sender as MysteryGift).ShowDialog();
+        private void B_OpenPokepuffs_Click(object sender, EventArgs e) => new SAV_Pokepuff().ShowDialog();
+        private void B_OpenPokeBeans_Click(object sender, EventArgs e) => new SAV_Pokebean().ShowDialog();
+        private void B_OpenItemPouch_Click(object sender, EventArgs e) => new SAV_Inventory().ShowDialog();
+        private void B_OpenBerryField_Click(object sender, EventArgs e) => new SAV_BerryFieldXY().ShowDialog();
+        private void B_OpenPokeblocks_Click(object sender, EventArgs e) => new SAV_PokeBlockORAS().ShowDialog();
+        private void B_OpenEventFlags_Click(object sender, EventArgs e) => new SAV_EventFlags().ShowDialog();
+        private void B_OpenSuperTraining_Click(object sender, EventArgs e) => new SAV_SuperTrain().ShowDialog();
+        private void B_OpenSecretBase_Click(object sender, EventArgs e) => new SAV_SecretBase().ShowDialog();
+        private void B_OpenZygardeCells_Click(object sender, EventArgs e) => new SAV_ZygardeCell().ShowDialog();
+        private void B_LinkInfo_Click(object sender, EventArgs e) => new SAV_Link6().ShowDialog();
         private void B_OpenBoxLayout_Click(object sender, EventArgs e)
         {
             new SAV_BoxLayout(CB_BoxSelect.SelectedIndex).ShowDialog();
@@ -3973,35 +3955,7 @@ namespace PKHeX.WinForms
             else if (SAV.Generation == 7)
                 new SAV_Trainer7().ShowDialog();
             // Refresh conversion info
-            PKMConverter.updateConfig(SAV.SubRegion, SAV.Country, SAV.ConsoleRegion, SAV.OT, SAV.Gender);
-        }
-        private void B_OpenPokepuffs_Click(object sender, EventArgs e)
-        {
-            new SAV_Pokepuff().ShowDialog();
-        }
-        private void B_OpenPokeBeans_Click(object sender, EventArgs e)
-        {
-            new SAV_Pokebean().ShowDialog();
-        }
-        private void B_OpenItemPouch_Click(object sender, EventArgs e)
-        {
-            new SAV_Inventory().ShowDialog();
-        }
-        private void B_OpenBerryField_Click(object sender, EventArgs e)
-        {
-            new SAV_BerryFieldXY().ShowDialog();
-        }
-        private void B_OpenPokeblocks_Click(object sender, EventArgs e)
-        {
-            new SAV_PokeBlockORAS().ShowDialog();
-        }
-        private void B_OpenEventFlags_Click(object sender, EventArgs e)
-        {
-            new SAV_EventFlags().ShowDialog();
-        }
-        private void B_OpenSuperTraining_Click(object sender, EventArgs e)
-        {
-            new SAV_SuperTrain().ShowDialog();
+            PKMConverter.updateConfig(SAV.SubRegion, SAV.Country, SAV.ConsoleRegion, SAV.OT, SAV.Gender, SAV.Language);
         }
         private void B_OpenOPowers_Click(object sender, EventArgs e)
         {
@@ -4098,18 +4052,6 @@ namespace PKHeX.WinForms
             else if (SAV.SM)
                 new SAV_HallOfFame7().ShowDialog();
         }
-        private void B_OpenSecretBase_Click(object sender, EventArgs e)
-        {
-            new SAV_SecretBase().ShowDialog();
-        }
-        private void B_OpenZygardeCells_Click(object sender, EventArgs e)
-        {
-            new SAV_ZygardeCell().ShowDialog();
-        }
-        private void B_LinkInfo_Click(object sender, EventArgs e)
-        {
-            new SAV_Link6().ShowDialog();
-        }
         private void B_CGearSkin_Click(object sender, EventArgs e)
         {
             if (SAV.Generation != 5)
@@ -4144,10 +4086,8 @@ namespace PKHeX.WinForms
         // Drag and drop related functions
         private void pbBoxSlot_MouseClick(object sender, MouseEventArgs e)
         {
-            if (DragInfo.slotDragDropInProgress)
-                return;
-            
-            clickSlot(sender, e);
+            if (!DragInfo.slotDragDropInProgress)
+                clickSlot(sender, e);
         }
         private void pbBoxSlot_MouseUp(object sender, MouseEventArgs e)
         {
@@ -4168,83 +4108,83 @@ namespace PKHeX.WinForms
             if (DragInfo.slotDragDropInProgress)
                 return;
 
-            if (DragInfo.slotLeftMouseIsDown)
+            if (!DragInfo.slotLeftMouseIsDown)
+                return;
+
+            // The goal is to create a temporary PKX file for the underlying Pokemon
+            // and use that file to perform a drag drop operation.
+
+            // Abort if there is no Pokemon in the given slot.
+            PictureBox pb = (PictureBox)sender;
+            if (pb.Image == null)
+                return;
+
+            int slot = getSlot(pb);
+            int box = slot >= 30 ? -1 : CB_BoxSelect.SelectedIndex;
+            if (SAV.getIsSlotLocked(box, slot))
+                return;
+
+            // Set flag to prevent re-entering.
+            DragInfo.slotDragDropInProgress = true;
+
+            DragInfo.slotSource = this;
+            DragInfo.slotSourceSlotNumber = slot;
+            DragInfo.slotSourceBoxNumber = box;
+            DragInfo.slotSourceOffset = getPKXOffset(DragInfo.slotSourceSlotNumber);
+
+            // Prepare Data
+            DragInfo.slotPkmSource = SAV.getData(DragInfo.slotSourceOffset, SAV.SIZE_STORED);
+
+            // Make a new file name based off the PID
+            bool encrypt = ModifierKeys == Keys.Control;
+            byte[] dragdata = SAV.decryptPKM(DragInfo.slotPkmSource);
+            Array.Resize(ref dragdata, SAV.SIZE_STORED);
+            PKM pkx = SAV.getPKM(dragdata);
+            string fn = pkx.FileName; fn = fn.Substring(0, fn.LastIndexOf('.'));
+            string filename = $"{fn}{(encrypt ? ".ek" + pkx.Format : "." + pkx.Extension)}";
+
+            // Make File
+            string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
+            try
             {
-                // The goal is to create a temporary PKX file for the underlying Pokemon
-                // and use that file to perform a drag drop operation.
-
-                // Abort if there is no Pokemon in the given slot.
-                PictureBox pb = (PictureBox)sender;
-                if (pb.Image == null)
-                    return;
-
-                int slot = getSlot(pb);
-                int box = slot >= 30 ? -1 : CB_BoxSelect.SelectedIndex;
-                if (SAV.getIsSlotLocked(box, slot))
-                    return;
-
-                // Set flag to prevent re-entering.
-                DragInfo.slotDragDropInProgress = true;
-
-                DragInfo.slotSource = this;
-                DragInfo.slotSourceSlotNumber = slot;
-                DragInfo.slotSourceBoxNumber = box;
-                DragInfo.slotSourceOffset = getPKXOffset(DragInfo.slotSourceSlotNumber);
-
-                // Prepare Data
-                DragInfo.slotPkmSource = SAV.getData(DragInfo.slotSourceOffset, SAV.SIZE_STORED);
-
-                // Make a new file name based off the PID
-                bool encrypt = ModifierKeys == Keys.Control;
-                byte[] dragdata = SAV.decryptPKM(DragInfo.slotPkmSource);
-                Array.Resize(ref dragdata, SAV.SIZE_STORED);
-                PKM pkx = SAV.getPKM(dragdata);
-                string fn = pkx.FileName; fn = fn.Substring(0, fn.LastIndexOf('.'));
-                string filename = $"{fn}{(encrypt ? ".ek" + pkx.Format : "." + pkx.Extension)}";
-
-                // Make File
-                string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
-                try
-                {
-                    File.WriteAllBytes(newfile, encrypt ? pkx.EncryptedBoxData : pkx.DecryptedBoxData);
-                    var img = (Bitmap)pb.Image;
-                    DragInfo.Cursor = Cursor.Current = new Cursor(img.GetHicon());
-                    pb.Image = null;
-                    pb.BackgroundImage = Resources.slotDrag;
-                    // Thread Blocks on DoDragDrop
-                    DragInfo.CurrentPath = newfile;
-                    DragDropEffects result = pb.DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Move);
-                    if (!DragInfo.SourceValid || result != DragDropEffects.Link) // not dropped to another box slot, restore img
-                        pb.Image = img;
-                    else // refresh image
-                        getQuickFiller(pb, SAV.getStoredSlot(DragInfo.slotSourceOffset));
-                    pb.BackgroundImage = null;
+                File.WriteAllBytes(newfile, encrypt ? pkx.EncryptedBoxData : pkx.DecryptedBoxData);
+                var img = (Bitmap)pb.Image;
+                DragInfo.Cursor = Cursor.Current = new Cursor(img.GetHicon());
+                pb.Image = null;
+                pb.BackgroundImage = Resources.slotDrag;
+                // Thread Blocks on DoDragDrop
+                DragInfo.CurrentPath = newfile;
+                DragDropEffects result = pb.DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Move);
+                if (!DragInfo.SourceValid || result != DragDropEffects.Link) // not dropped to another box slot, restore img
+                    pb.Image = img;
+                else // refresh image
+                    getQuickFiller(pb, SAV.getStoredSlot(DragInfo.slotSourceOffset));
+                pb.BackgroundImage = null;
                     
-                    if (DragInfo.SameBox && DragInfo.DestinationValid)
-                        SlotPictureBoxes[DragInfo.slotDestinationSlotNumber].Image = img;
+                if (DragInfo.SameBox && DragInfo.DestinationValid)
+                    SlotPictureBoxes[DragInfo.slotDestinationSlotNumber].Image = img;
 
-                    if (result == DragDropEffects.Copy) // viewed in tabs, apply 'view' highlight
-                        getSlotColor(DragInfo.slotSourceSlotNumber, Resources.slotView);
-                }
-                catch (Exception x)
-                {
-                    WinFormsUtil.Error("Drag & Drop Error", x);
-                }
-                notifyBoxViewerRefresh();
-                DragInfo.Reset();
-                Cursor = DefaultCursor;
-
-                // Browser apps need time to load data since the file isn't moved to a location on the user's local storage.
-                // Tested 10ms -> too quick, 100ms was fine. 500ms should be safe?
-                new Thread(() =>
-                {
-                    Thread.Sleep(500);
-                    if (File.Exists(newfile) && DragInfo.CurrentPath == null)
-                        File.Delete(newfile);
-                }).Start();
-                if (DragInfo.SourceParty || DragInfo.DestinationParty)
-                    setParty();
+                if (result == DragDropEffects.Copy) // viewed in tabs, apply 'view' highlight
+                    getSlotColor(DragInfo.slotSourceSlotNumber, Resources.slotView);
             }
+            catch (Exception x)
+            {
+                WinFormsUtil.Error("Drag & Drop Error", x);
+            }
+            notifyBoxViewerRefresh();
+            DragInfo.Reset();
+            Cursor = DefaultCursor;
+
+            // Browser apps need time to load data since the file isn't moved to a location on the user's local storage.
+            // Tested 10ms -> too quick, 100ms was fine. 500ms should be safe?
+            new Thread(() =>
+            {
+                Thread.Sleep(500);
+                if (File.Exists(newfile) && DragInfo.CurrentPath == null)
+                    File.Delete(newfile);
+            }).Start();
+            if (DragInfo.SourceParty || DragInfo.DestinationParty)
+                setParty();
         }
         private void pbBoxSlot_DragDrop(object sender, DragEventArgs e)
         {
diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs
index de3dc80fc..b95fff541 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs	
+++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs	
@@ -164,76 +164,76 @@ namespace PKHeX.WinForms
             if (DragInfo.slotDragDropInProgress)
                 return;
 
-            if (DragInfo.slotLeftMouseIsDown)
+            if (!DragInfo.slotLeftMouseIsDown)
+                return;
+
+            // The goal is to create a temporary PKX file for the underlying Pokemon
+            // and use that file to perform a drag drop operation.
+
+            // Abort if there is no Pokemon in the given slot.
+            PictureBox pb = (PictureBox)sender;
+            if (pb.Image == null)
+                return;
+
+            int slot = getSlot(pb);
+            int box = slot >= 30 ? -1 : CB_BoxSelect.SelectedIndex;
+            if (SAV.getIsSlotLocked(box, slot))
+                return;
+
+            // Set flag to prevent re-entering.
+            DragInfo.slotDragDropInProgress = true;
+
+            DragInfo.slotSource = this;
+            DragInfo.slotSourceSlotNumber = slot;
+            DragInfo.slotSourceBoxNumber = box;
+            DragInfo.slotSourceOffset = getPKXOffset(DragInfo.slotSourceSlotNumber);
+
+            // Prepare Data
+            DragInfo.slotPkmSource = SAV.getData(DragInfo.slotSourceOffset, SAV.SIZE_STORED);
+
+            // Make a new file name based off the PID
+            byte[] dragdata = SAV.decryptPKM(DragInfo.slotPkmSource);
+            Array.Resize(ref dragdata, SAV.SIZE_STORED);
+            PKM pkx = SAV.getPKM(dragdata);
+            string filename = pkx.FileName;
+
+            // Make File
+            string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
+            try
             {
-                // The goal is to create a temporary PKX file for the underlying Pokemon
-                // and use that file to perform a drag drop operation.
+                File.WriteAllBytes(newfile, dragdata);
+                var img = (Bitmap)pb.Image;
+                DragInfo.Cursor = Cursor.Current = new Cursor(img.GetHicon());
+                pb.Image = null;
+                pb.BackgroundImage = Core.Properties.Resources.slotDrag;
+                // Thread Blocks on DoDragDrop
+                DragInfo.CurrentPath = newfile;
+                DragDropEffects result = pb.DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Move);
+                if (!DragInfo.SourceValid || result != DragDropEffects.Link) // not dropped to another box slot, restore img
+                    pb.Image = img;
+                else // refresh image
+                    getQuickFiller(pb, SAV.getStoredSlot(DragInfo.slotSourceOffset));
+                pb.BackgroundImage = null;
 
-                // Abort if there is no Pokemon in the given slot.
-                PictureBox pb = (PictureBox)sender;
-                if (pb.Image == null)
-                    return;
-
-                int slot = getSlot(pb);
-                int box = slot >= 30 ? -1 : CB_BoxSelect.SelectedIndex;
-                if (SAV.getIsSlotLocked(box, slot))
-                    return;
-
-                // Set flag to prevent re-entering.
-                DragInfo.slotDragDropInProgress = true;
-
-                DragInfo.slotSource = this;
-                DragInfo.slotSourceSlotNumber = slot;
-                DragInfo.slotSourceBoxNumber = box;
-                DragInfo.slotSourceOffset = getPKXOffset(DragInfo.slotSourceSlotNumber);
-
-                // Prepare Data
-                DragInfo.slotPkmSource = SAV.getData(DragInfo.slotSourceOffset, SAV.SIZE_STORED);
-
-                // Make a new file name based off the PID
-                byte[] dragdata = SAV.decryptPKM(DragInfo.slotPkmSource);
-                Array.Resize(ref dragdata, SAV.SIZE_STORED);
-                PKM pkx = SAV.getPKM(dragdata);
-                string filename = pkx.FileName;
-
-                // Make File
-                string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
-                try
-                {
-                    File.WriteAllBytes(newfile, dragdata);
-                    var img = (Bitmap)pb.Image;
-                    DragInfo.Cursor = Cursor.Current = new Cursor(img.GetHicon());
-                    pb.Image = null;
-                    pb.BackgroundImage = Core.Properties.Resources.slotDrag;
-                    // Thread Blocks on DoDragDrop
-                    DragInfo.CurrentPath = newfile;
-                    DragDropEffects result = pb.DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Move);
-                    if (!DragInfo.SourceValid || result != DragDropEffects.Link) // not dropped to another box slot, restore img
-                        pb.Image = img;
-                    else // refresh image
-                        getQuickFiller(pb, SAV.getStoredSlot(DragInfo.slotSourceOffset));
-                    pb.BackgroundImage = null;
-
-                    if (DragInfo.SameBox && DragInfo.DestinationValid)
-                        SlotPictureBoxes[DragInfo.slotDestinationSlotNumber].Image = img;
-                }
-                catch (Exception x)
-                {
-                    WinFormsUtil.Error("Drag & Drop Error", x);
-                }
-                parent.notifyBoxViewerRefresh();
-                DragInfo.Reset();
-                Cursor = DefaultCursor;
-
-                // Browser apps need time to load data since the file isn't moved to a location on the user's local storage.
-                // Tested 10ms -> too quick, 100ms was fine. 500ms should be safe?
-                new Thread(() =>
-                {
-                    Thread.Sleep(500);
-                    if (File.Exists(newfile) && DragInfo.CurrentPath == null)
-                        File.Delete(newfile);
-                }).Start();
+                if (DragInfo.SameBox && DragInfo.DestinationValid)
+                    SlotPictureBoxes[DragInfo.slotDestinationSlotNumber].Image = img;
             }
+            catch (Exception x)
+            {
+                WinFormsUtil.Error("Drag & Drop Error", x);
+            }
+            parent.notifyBoxViewerRefresh();
+            DragInfo.Reset();
+            Cursor = DefaultCursor;
+
+            // Browser apps need time to load data since the file isn't moved to a location on the user's local storage.
+            // Tested 10ms -> too quick, 100ms was fine. 500ms should be safe?
+            new Thread(() =>
+            {
+                Thread.Sleep(500);
+                if (File.Exists(newfile) && DragInfo.CurrentPath == null)
+                    File.Delete(newfile);
+            }).Start();
         }
         private void pbBoxSlot_DragDrop(object sender, DragEventArgs e)
         {
diff --git a/PKHeX/Game/GameInfo.cs b/PKHeX/Game/GameInfo.cs
index e3045f274..6f2f8fa1d 100644
--- a/PKHeX/Game/GameInfo.cs
+++ b/PKHeX/Game/GameInfo.cs
@@ -218,6 +218,9 @@ namespace PKHeX.Core
                 }
                 metSM_00000_good.CopyTo(metSM_00000, 0);
 
+                for (int i = 2; i <= 5; i++) // distinguish first set of regions (unused) from second (used)
+                    metSM_30000[i] += " (-)";
+
                 // Set the first entry of a met location to "" (nothing)
                 // Fix (None) tags
                 abilitylist[0] = itemlist[0] = movelist[0] = metXY_00000[0] = metBW2_00000[0] = metHGSS_00000[0] = "(" + itemlist[0] + ")";
@@ -276,7 +279,9 @@ namespace PKHeX.Core
             SpeciesDataSource = Util.getCBList(s.specieslist, null);
             NatureDataSource = Util.getCBList(s.natures, null);
             AbilityDataSource = Util.getCBList(s.abilitylist, null);
-            VersionDataSource = Util.getCBList(s.gamelist, Legal.Games_7vc, Legal.Games_7go, Legal.Games_7sm, Legal.Games_6oras, Legal.Games_6xy, Legal.Games_5, Legal.Games_4, Legal.Games_4e, Legal.Games_4r, Legal.Games_3, Legal.Games_3e, Legal.Games_3r, Legal.Games_3s);
+            VersionDataSource = Util.getCBList(s.gamelist, Legal.Games_7sm, Legal.Games_6oras, Legal.Games_6xy, Legal.Games_5, Legal.Games_4, Legal.Games_4e, Legal.Games_4r, Legal.Games_3, Legal.Games_3e, Legal.Games_3r, Legal.Games_3s);
+            VersionDataSource.AddRange(Util.getCBList(s.gamelist, Legal.Games_7vc1).OrderBy(g => g.Value)); // stuff to end unsorted
+            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();
@@ -416,10 +421,12 @@ namespace PKHeX.Core
 
                 case GameVersion.SN:
                 case GameVersion.MN:
+
+                case GameVersion.GO:
                 case GameVersion.RD:
                 case GameVersion.BU:
-                case GameVersion.YW:
                 case GameVersion.GN:
+                case GameVersion.YW:
                     return metGen7.Take(3).Concat(metGen7.Skip(3).OrderByDescending(loc => loc.Value < 200)).ToList(); // Secret Base
             }
 
diff --git a/PKHeX/Legality/Tables.cs b/PKHeX/Legality/Tables.cs
index 4ffd0820b..d23c976b3 100644
--- a/PKHeX/Legality/Tables.cs
+++ b/PKHeX/Legality/Tables.cs
@@ -215,7 +215,8 @@
 
         #region Games
 
-        public static readonly int[] Games_7vc = { 35, 36, 37, 38 };
+        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_7go = { 34 };
         public static readonly int[] Games_7sm = { 30, 31 };
         public static readonly int[] Games_6xy = { 24, 25 };
diff --git a/PKHeX/PKM/PK1.cs b/PKHeX/PKM/PK1.cs
index 9a7c9fe08..700870fae 100644
--- a/PKHeX/PKM/PK1.cs
+++ b/PKHeX/PKM/PK1.cs
@@ -317,12 +317,11 @@ namespace PKHeX.Core
                 EncryptionConstant = Util.rnd32(),
                 Species = Species,
                 TID = TID,
-                EXP = EXP,
                 CurrentLevel = CurrentLevel,
+                EXP = EXP,
                 Met_Level = CurrentLevel,
                 Nature = (int) (EXP%25),
                 PID = Util.rnd32(),
-                AbilityNumber = 4,
                 Ball = 4,
                 MetDate = DateTime.Now,
                 Version = (int)GameVersion.RD, // Default to red, for now?
@@ -338,19 +337,29 @@ namespace PKHeX.Core
                 Move2_PP = Move2_PP,
                 Move3_PP = Move3_PP,
                 Move4_PP = Move4_PP,
-                CurrentFriendship = PersonalTable.SM[Species].BaseFriendship,
                 Met_Location = 30013, // "Kanto region", hardcoded.
                 Gender = PersonalTable.SM[Species].RandomGender,
                 OT_Name = PKX.getG1ConvertedString(otname, Japanese),
                 Nickname = Util.getSpeciesList(Japanese ? "jp" : "en")[Species],
-                IsNicknamed = false
-            };
+                IsNicknamed = false,
 
 
+
+                Country = PKMConverter.Country,
+                Region = PKMConverter.Region,
+                ConsoleRegion = PKMConverter.ConsoleRegion,
+                CurrentHandler = 1,
+                HT_Name = PKMConverter.OT_Name,
+                HT_Gender = PKMConverter.OT_Gender,
+                Language = PKMConverter,
+            };
+            pk7.OT_Friendship = pk7.HT_Friendship = PersonalTable.SM[Species].BaseFriendship;
+
             // IVs
             var new_ivs = new int[6];
+            int flawless = Species == 151 ? 5 : 3;
             for (var i = 0; i < new_ivs.Length; i++) new_ivs[i] = (int)(Util.rnd32() & 31);
-            for (var i = 0; i < (Species == 151 ? 5 : 3); i++) new_ivs[i] = 31;
+            for (var i = 0; i < flawless; i++) new_ivs[i] = 31;
             Util.Shuffle(new_ivs);
             pk7.IVs = new_ivs;
 
@@ -358,26 +367,21 @@ namespace PKHeX.Core
             if (IsShiny)
                 pk7.setShinyPID();
 
-            if (new[] {92, 93, 94, 151, 109, 110}.Contains(Species))
-                pk7.AbilityNumber = 1;
+            int abil = 2; // Hidden
+            if (new[] {92, 93, 94, 109, 110, 151}.Contains(Species))
+                abil = 0; // Reset
+            pk7.RefreshAbility(abil); // 0/1/2 (not 1/2/4)
 
-            if (IsNicknamedBank)
+            if (Species == 151) // Mew gets special treatment.
+                pk7.FatefulEncounter = true;
+            else if (IsNicknamedBank)
             {
                 pk7.IsNicknamed = true;
                 pk7.Nickname = PKX.getG1ConvertedString(nick, Japanese);
             }
-
-            // TODO: Language, 3DS Country/Region Info, Memories (Link Trade/Somewhere, remembers feeling {rnd})
-
-            if (Species == 151) // Mew gets special treatment.
-            {
-                pk7.FatefulEncounter = true;
-                pk7.AbilityNumber = 1;
-                pk7.Egg_Location = 0;
-                pk7.Nickname = Util.getSpeciesList(Japanese ? "jp" : "en")[Species];
-                pk7.IsNicknamed = false;
-            }
-
+            
+            pk7.TradeMemory(Bank:true); // oh no, memories on gen7 pkm
+            
             pk7.RefreshChecksum();
             return pk7;
         }
diff --git a/PKHeX/PKM/PK7.cs b/PKHeX/PKM/PK7.cs
index 1e37889a8..d33a09e23 100644
--- a/PKHeX/PKM/PK7.cs
+++ b/PKHeX/PKM/PK7.cs
@@ -586,11 +586,13 @@ namespace PKHeX.Core
         }
         public void TradeMemory(bool Bank)
         {
-            return; // appears no memories are set, ever?
-            // HT_Memory = 4; // Link trade to [VAR: General Location]
-            // HT_TextVar = Bank ? 0 : 9; // Somewhere (Bank) : Pokécenter (Trade)
-            // HT_Intensity = 1;
-            // HT_Feeling = Util.rand.Next(0, Bank ? 9 : 19); // 0-9 Bank, 0-19 Trade
+            if (!Bank)
+                return;
+
+            HT_Memory = 4; // Link trade to [VAR: General Location]
+            HT_TextVar = 0; // Somewhere (Bank)
+            HT_Intensity = 1;
+            HT_Feeling = Util.rand.Next(0, 9); // 0-9 Bank
         }
 
         // Legality Properties
diff --git a/PKHeX/PKM/PKM.cs b/PKHeX/PKM/PKM.cs
index 6d9bf3c33..c6d95c9d6 100644
--- a/PKHeX/PKM/PKM.cs
+++ b/PKHeX/PKM/PKM.cs
@@ -261,13 +261,15 @@ namespace PKHeX.Core
         public virtual bool IsShiny => TSV == PSV;
         public virtual bool Locked { get { return false; } set { } }
         public int TrainerID7 => (int)((uint)(TID | (SID << 16)) % 1000000);
-        public bool VC => Version >= 35 && Version <= 41;
+        public bool VC2 => Version >= 39 && Version <= 41;
+        public bool VC1 => Version >= 35 && Version <= 38;
         public bool Horohoro => Version == 34;
         public bool XY => Version == (int)GameVersion.X || Version == (int)GameVersion.Y;
         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 VC => VC1 || VC2;
         public bool Gen7 => Version >= 30 && Version <= 33;
         public bool Gen6 => Version >= 24 && Version <= 29;
         public bool Gen5 => Version >= 20 && Version <= 23;
@@ -428,6 +430,18 @@ namespace PKHeX.Core
         public virtual bool HT_SPA { get { return false; } set { } }
         public virtual bool HT_SPD { get { return false; } set { } }
         public virtual bool HT_SPE { get { return false; } set { } }
+        public void HyperTrainInvert(int stat)
+        {
+            switch (stat)
+            {
+                case 0: HT_HP ^= true; break;
+                case 1: HT_ATK ^= true; break;
+                case 2: HT_DEF ^= true; break;
+                case 3: HT_SPA ^= true; break;
+                case 4: HT_SPD ^= true; break;
+                case 5: HT_SPE ^= true; break;
+            }
+        }
 
         public bool InhabitedGeneration(int Generation)
         {
@@ -489,6 +503,14 @@ namespace PKHeX.Core
                 ReorderMoves();
             }
         }
+        public void RefreshAbility(int n)
+        {
+            AbilityNumber = 1 << n;
+            int[] abilities = PersonalInfo.Abilities;
+            if (n < abilities.Length)
+                Ability = abilities[n];
+        }
+
 
         public int PotentialRating
         {
diff --git a/PKHeX/PKM/PKMConverter.cs b/PKHeX/PKM/PKMConverter.cs
index a09c5623a..f16d423bf 100644
--- a/PKHeX/PKM/PKMConverter.cs
+++ b/PKHeX/PKM/PKMConverter.cs
@@ -9,15 +9,17 @@ namespace PKHeX.Core
         public static int Region = 7;
         public static int ConsoleRegion = 1;
         public static string OT_Name = "PKHeX";
-        public static int OT_Gender;
+        public static int OT_Gender; // Male
+        public static int Language = 1; // en
 
-        public static void updateConfig(int SUBREGION, int COUNTRY, int _3DSREGION, string TRAINERNAME, int TRAINERGENDER)
+        public static void updateConfig(int SUBREGION, int COUNTRY, int _3DSREGION, string TRAINERNAME, int TRAINERGENDER, int LANGUAGE)
         {
             Region = SUBREGION;
             Country = COUNTRY;
             ConsoleRegion = _3DSREGION;
             OT_Name = TRAINERNAME;
             OT_Gender = TRAINERGENDER;
+            Language = LANGUAGE;
         }
 
         /// <summary>