mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-15 00:37:11 +00:00
ff64a875fc
Easier clearing of values; instead of saying "stuff is wrong", it's obvious the user deleted the text so just set it to the 0th item.
3440 lines
151 KiB
C#
3440 lines
151 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Media;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
|
|
namespace PKHeX
|
|
{
|
|
public partial class Main : Form
|
|
{
|
|
public Main()
|
|
{
|
|
#region Initialize Form
|
|
new Thread(() => new SplashScreen().ShowDialog()).Start();
|
|
InitializeComponent();
|
|
// Initialize SAV-Set Parameters in case compilation settings were changed.
|
|
SAV6.SetUpdateDex = Menu_ModifyDex.Checked;
|
|
SAV6.SetUpdatePK6 = Menu_ModifyPK6.Checked;
|
|
SlotPictureBoxes = new[] {
|
|
bpkx1, bpkx2, bpkx3, bpkx4, bpkx5, bpkx6,
|
|
bpkx7, bpkx8, bpkx9, bpkx10,bpkx11,bpkx12,
|
|
bpkx13,bpkx14,bpkx15,bpkx16,bpkx17,bpkx18,
|
|
bpkx19,bpkx20,bpkx21,bpkx22,bpkx23,bpkx24,
|
|
bpkx25,bpkx26,bpkx27,bpkx28,bpkx29,bpkx30,
|
|
|
|
ppkx1, ppkx2, ppkx3, ppkx4, ppkx5, ppkx6,
|
|
bbpkx1,bbpkx2,bbpkx3,bbpkx4,bbpkx5,bbpkx6,
|
|
|
|
dcpkx1, dcpkx2, gtspkx, fusedpkx,subepkx1,subepkx2,subepkx3,
|
|
};
|
|
defaultControlWhite = CB_Species.BackColor;
|
|
defaultControlText = Label_Species.ForeColor;
|
|
CB_ExtraBytes.SelectedIndex = 0;
|
|
|
|
// Initialize Boxes
|
|
for (int i = 0; i < 30*31; i++)
|
|
SAV.setData(blankEK6, SAV.Box + i*PK6.SIZE_STORED);
|
|
|
|
// Set up Language Selection
|
|
foreach (var cbItem in main_langlist)
|
|
CB_MainLanguage.Items.Add(cbItem);
|
|
|
|
// ToolTips for Drag&Drop
|
|
new ToolTip().SetToolTip(dragout, "PK6 QuickSave");
|
|
|
|
// Box Drag & Drop
|
|
foreach (PictureBox pb in PAN_Box.Controls)
|
|
{
|
|
pb.AllowDrop = true;
|
|
// The PictureBoxes have their own drag&drop event handlers.
|
|
}
|
|
foreach (TabPage tab in tabMain.TabPages)
|
|
{
|
|
tab.AllowDrop = true;
|
|
tab.DragDrop += tabMain_DragDrop;
|
|
tab.DragEnter += tabMain_DragEnter;
|
|
}
|
|
foreach (TabPage tab in tabBoxMulti.TabPages)
|
|
{
|
|
tab.AllowDrop = true;
|
|
tab.DragDrop += tabMain_DragDrop;
|
|
tab.DragEnter += tabMain_DragEnter;
|
|
}
|
|
// Box to Tabs D&D
|
|
dragout.AllowDrop = true;
|
|
|
|
string[] args = Environment.GetCommandLineArgs();
|
|
string filename = args.Length > 0 ? Path.GetFileNameWithoutExtension(args[0]) : "";
|
|
HaX = filename.IndexOf("HaX", StringComparison.Ordinal) >= 0;
|
|
// Show Hacked Stuff if HaX
|
|
CHK_HackedStats.Enabled = CHK_HackedStats.Visible = DEV_Ability.Enabled = DEV_Ability.Visible =
|
|
MT_Level.Enabled = MT_Level.Visible = TB_AbilityNumber.Visible = MT_Form.Enabled = MT_Form.Visible = HaX;
|
|
// Hide Regular Stuff if !HaX
|
|
TB_Level.Visible = CB_Ability.Visible = !HaX;
|
|
// Load WC6 folder to legality
|
|
refreshWC6DB();
|
|
#endregion
|
|
#region Localize & Populate Fields
|
|
// Try and detect the language
|
|
int[] main_langnum = {1, 2, 3, 4, 5, 7, 8, 9};
|
|
main_langnum = main_langnum.Concat(Enumerable.Range(10, lang_val.Length).Select(i => i)).ToArray();
|
|
string lastTwoChars = filename.Length > 2 ? filename.Substring(filename.Length - 2) : "";
|
|
int lang = filename.Length > 2 ? Array.IndexOf(lang_val, lastTwoChars) : - 1;
|
|
CB_MainLanguage.SelectedIndex = lang >= 0 ? main_langnum[lang] - 1 : (lastTwoChars == "jp" ? 1 : 0);
|
|
|
|
InitializeFields();
|
|
CB_Language.SelectedIndex = lang >= 0 && lang < 7 ? main_langnum[lang] : 1;
|
|
#endregion
|
|
#region Load Initial File(s)
|
|
// Load the arguments
|
|
pathSDF = Util.GetSDFLocation();
|
|
path3DS = Util.get3DSLocation();
|
|
if (args.Length > 1)
|
|
{
|
|
foreach (string arg in args.Skip(1).Where(a => a.Length > 4))
|
|
openQuick(arg);
|
|
}
|
|
else if (path3DS != null && File.Exists(Path.Combine(Path.GetPathRoot(path3DS), "ramsav.bin")))
|
|
openQuick(Path.Combine(Path.GetPathRoot(path3DS), "ramsav.bin"));
|
|
else if (path3DS != null && File.Exists(Path.Combine(Path.GetPathRoot(path3DS), "SaveDataBackup", "main")))
|
|
openQuick(Path.Combine(Path.GetPathRoot(path3DS), "SaveDataBackup", "main"));
|
|
else if (pathSDF != null)
|
|
openQuick(Path.Combine(pathSDF, "main"));
|
|
else if (File.Exists(Util.NormalizePath(Path.Combine(Util.GetTempFolder(), "root", "main"))))
|
|
openQuick(Util.NormalizePath(Path.Combine(Util.GetTempFolder(), "root", "main")));
|
|
|
|
GB_OT.Click += clickGT;
|
|
GB_nOT.Click += clickGT;
|
|
GB_Daycare.Click += switchDaycare;
|
|
GB_RelearnMoves.Click += clickMoves;
|
|
|
|
TB_Nickname.Font = PKX.getPKXFont(11);
|
|
TB_OT.Font = (Font)TB_Nickname.Font.Clone();
|
|
TB_OTt2.Font = (Font)TB_Nickname.Font.Clone();
|
|
formInitialized = true;
|
|
|
|
// Splash Screen closes on its own.
|
|
BringToFront();
|
|
WindowState = FormWindowState.Minimized;
|
|
Show();
|
|
WindowState = FormWindowState.Normal;
|
|
if (HaX) Util.Alert("Illegal mode activated.", "Please behave.");
|
|
#endregion
|
|
}
|
|
|
|
#region Important Variables
|
|
public static readonly byte[] blankEK6 = PKX.encryptArray(new byte[PK6.SIZE_PARTY]);
|
|
public static PK6 pk6 = new PK6(); // Tab Pokemon Data Storage
|
|
public static SAV6 SAV = new SAV6(); // Save File
|
|
public static Color defaultControlWhite;
|
|
public static Color defaultControlText;
|
|
public static string eggname = "";
|
|
public const string DatabasePath = "db";
|
|
public const string WC6DatabasePath = "wc6";
|
|
public static string[] gendersymbols = { "♂", "♀", "-" };
|
|
public static string[] specieslist, movelist, itemlist, abilitylist, types, natures, forms,
|
|
memories, genloc, trainingbags, trainingstage, characteristics,
|
|
encountertypelist, gamelanguages, balllist, gamelist, pokeblocks = { };
|
|
public static string[] metHGSS_00000, metHGSS_02000, metHGSS_03000 = { };
|
|
public static string[] metBW2_00000, metBW2_30000, metBW2_40000, metBW2_60000 = { };
|
|
public static string[] metXY_00000, metXY_30000, metXY_40000, metXY_60000 = { };
|
|
public static string[] wallpapernames, puffs, itempouch = { };
|
|
public static string curlanguage = "en";
|
|
public static bool unicode;
|
|
public static List<Util.cbItem> MoveDataSource, ItemDataSource, SpeciesDataSource, BallDataSource, NatureDataSource, AbilityDataSource, VersionDataSource;
|
|
|
|
public static volatile bool formInitialized, fieldsInitialized, fieldsLoaded;
|
|
private static int colorizedbox = 32;
|
|
private static Image colorizedcolor;
|
|
private static int colorizedslot;
|
|
private static string pathSDF;
|
|
private static string path3DS;
|
|
private static bool HaX;
|
|
private LegalityAnalysis Legality = new LegalityAnalysis(new PK6());
|
|
private static readonly Image mixedHighlight = Util.ChangeOpacity(Properties.Resources.slotSet, 0.5);
|
|
private static readonly string BackupPath = "bak";
|
|
private static readonly string[] lang_val = { "en", "ja", "fr", "it", "de", "es", "ko", "zh", "pt" };
|
|
private static readonly string[] main_langlist =
|
|
{
|
|
"English", // ENG
|
|
"日本語", // JPN
|
|
"Français", // FRE
|
|
"Italiano", // ITA
|
|
"Deutsch", // GER
|
|
"Español", // SPA
|
|
"한국어", // KOR
|
|
"中文", // CHN
|
|
"Português", // Portuguese
|
|
};
|
|
private static string origintrack;
|
|
private readonly PictureBox[] SlotPictureBoxes;
|
|
private readonly ToolTip Tip1 = new ToolTip(), Tip2 = new ToolTip(), Tip3 = new ToolTip(), NatureTip = new ToolTip();
|
|
#endregion
|
|
|
|
#region //// MAIN MENU FUNCTIONS ////
|
|
// Main Menu Strip UI Functions
|
|
private void mainMenuOpen(object sender, EventArgs e)
|
|
{
|
|
OpenFileDialog ofd = new OpenFileDialog
|
|
{
|
|
Filter = "PKX File|*.pk6;*.pkx" +
|
|
"|EKX File|*.ek6;*.ekx" +
|
|
"|BIN File|*.bin" +
|
|
"|All Files|*.*",
|
|
RestoreDirectory = true,
|
|
FilterIndex = 4,
|
|
FileName = "main",
|
|
};
|
|
|
|
// Detect main
|
|
string cyberpath = Util.GetTempFolder();
|
|
pathSDF = Util.GetSDFLocation();
|
|
path3DS = Util.get3DSLocation();
|
|
if (path3DS != null && File.Exists(Path.Combine(Path.GetPathRoot(path3DS), "SaveDataBackup", "main")))
|
|
ofd.InitialDirectory = Path.Combine(Path.GetPathRoot(path3DS), "SaveDataBackup");
|
|
else if (pathSDF != null)
|
|
ofd.InitialDirectory = pathSDF;
|
|
else if (path3DS != null)
|
|
ofd.InitialDirectory = Path.GetPathRoot(path3DS);
|
|
else if (Directory.Exists(Path.Combine(cyberpath, "root")))
|
|
ofd.InitialDirectory = Path.Combine(cyberpath, "root");
|
|
else if (Directory.Exists(cyberpath))
|
|
ofd.InitialDirectory = cyberpath;
|
|
else if (File.Exists(Path.Combine(ofd.InitialDirectory, "main"))) { }
|
|
else { ofd.RestoreDirectory = false; ofd.FilterIndex = 1; ofd.FileName = ""; }
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
openQuick(ofd.FileName);
|
|
}
|
|
private void mainMenuSave(object sender, EventArgs e)
|
|
{
|
|
if (!verifiedPKX()) return;
|
|
SaveFileDialog sfd = new SaveFileDialog
|
|
{
|
|
Filter = "PKX File|*.pk6;*.pkx" +
|
|
"|EKX File|*.ek6;*.ekx" +
|
|
"|BIN File|*.bin" +
|
|
"|All Files|*.*",
|
|
DefaultExt = "pk6",
|
|
FileName = TB_Nickname.Text + " - " + TB_PID.Text
|
|
};
|
|
if (sfd.ShowDialog() != DialogResult.OK) return;
|
|
string path = sfd.FileName;
|
|
// Injection Dummy Override
|
|
if (path.Contains("pokemon.ekx")) path = Path.Combine(Path.GetDirectoryName(path), "pokemon.ekx");
|
|
string ext = Path.GetExtension(path);
|
|
|
|
if (File.Exists(path) && !path.Contains("pokemon.ekx"))
|
|
{
|
|
// File already exists, save a .bak
|
|
byte[] backupfile = File.ReadAllBytes(path);
|
|
File.WriteAllBytes(path + ".bak", backupfile);
|
|
}
|
|
|
|
PK6 pk = preparepkx();
|
|
if (new[] {".ekx", ".ek6", ".bin"}.Contains(ext))
|
|
File.WriteAllBytes(path, pk.EncryptedPartyData);
|
|
else if (new[] { ".pkx", ".pk6" }.Contains(ext))
|
|
File.WriteAllBytes(path, pk.Data);
|
|
else
|
|
{
|
|
Util.Error($"Foreign File Extension: {ext}", "Exporting as encrypted.");
|
|
File.WriteAllBytes(path, pk6.EncryptedPartyData);
|
|
}
|
|
}
|
|
private void mainMenuExit(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys == (Keys.Control | Keys.E)) // Hotkey Triggered
|
|
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo, "Quit PKHeX?")) return;
|
|
Close();
|
|
}
|
|
private void mainMenuAbout(object sender, EventArgs e)
|
|
{
|
|
// Open a new form with the About details.
|
|
new About().ShowDialog();
|
|
}
|
|
// Sub Menu Options
|
|
private void mainMenuCodeGen(object sender, EventArgs e)
|
|
{
|
|
// Open Code Generator
|
|
PK6 formdata = null;
|
|
if (verifiedPKX()) formdata = preparepkx();
|
|
CodeGenerator CodeGen = new CodeGenerator(formdata.Data);
|
|
CodeGen.ShowDialog();
|
|
|
|
byte[] data = CodeGen.returnArray;
|
|
if (data == null) return;
|
|
byte[] decdata = PKX.decryptArray(data);
|
|
Array.Copy(decdata, pk6.Data, PK6.SIZE_STORED);
|
|
try { populateFields(pk6); }
|
|
catch
|
|
{
|
|
Array.Copy(new byte[PK6.SIZE_STORED], pk6.Data, PK6.SIZE_STORED);
|
|
populateFields(pk6);
|
|
Util.Error("Imported code did not decrypt properly", "Please verify that what you imported was correct.");
|
|
}
|
|
}
|
|
private void mainMenuBoxReport(object sender, EventArgs e)
|
|
{
|
|
if (Application.OpenForms.Cast<Form>().Any(form => form.Name == typeof(frmReport).Name))
|
|
{ Util.Alert("Window is already open."); return; }
|
|
|
|
frmReport ReportForm = new frmReport();
|
|
ReportForm.Show();
|
|
ReportForm.PopulateData(SAV.Data, SAV.Box);
|
|
}
|
|
private void mainMenuDatabase(object sender, EventArgs e)
|
|
{
|
|
if (Application.OpenForms.Cast<Form>().Any(form => form.Name == typeof(SAV_Database).Name))
|
|
{ Util.Alert("Window is already open."); return; }
|
|
|
|
if (Directory.Exists("db"))
|
|
new SAV_Database(this).Show();
|
|
else
|
|
Util.Alert("PKHeX's database was not found",
|
|
"Please dump all boxes from a save file, then ensure the 'db' folder exists.");
|
|
}
|
|
private void mainMenuUnicode(object sender, EventArgs e)
|
|
{
|
|
unicode = Menu_Unicode.Checked;
|
|
updateUnicode();
|
|
}
|
|
private void mainMenuModifyDex(object sender, EventArgs e)
|
|
{
|
|
SAV6.SetUpdateDex = Menu_ModifyDex.Checked;
|
|
}
|
|
private void mainMenuModifyPK6(object sender, EventArgs e)
|
|
{
|
|
SAV6.SetUpdatePK6 = Menu_ModifyPK6.Checked;
|
|
}
|
|
private void mainMenuBoxLoad(object sender, EventArgs e)
|
|
{
|
|
string path = "";
|
|
if (Directory.Exists(DatabasePath))
|
|
{
|
|
DialogResult ld = Util.Prompt(MessageBoxButtons.YesNo, "Load from PKHeX's database?");
|
|
if (ld == DialogResult.Yes)
|
|
path = DatabasePath;
|
|
else if (ld == DialogResult.No)
|
|
{
|
|
// open folder dialog
|
|
FolderBrowserDialog fbd = new FolderBrowserDialog();
|
|
if (fbd.ShowDialog() == DialogResult.OK)
|
|
path = fbd.SelectedPath;
|
|
}
|
|
else return;
|
|
}
|
|
else
|
|
{
|
|
// open folder dialog
|
|
FolderBrowserDialog fbd = new FolderBrowserDialog();
|
|
if (fbd.ShowDialog() == DialogResult.OK)
|
|
path = fbd.SelectedPath;
|
|
}
|
|
loadBoxesFromDB(path);
|
|
}
|
|
private void mainMenuBoxDump(object sender, EventArgs e)
|
|
{
|
|
string path;
|
|
bool dumptoboxes = false;
|
|
// Dump all of box content to files.
|
|
DialogResult ld = Util.Prompt(MessageBoxButtons.YesNo, "Save to PKHeX's database?");
|
|
if (ld == DialogResult.Yes)
|
|
{
|
|
path = DatabasePath;
|
|
if (!Directory.Exists(path))
|
|
Directory.CreateDirectory(path);
|
|
}
|
|
else if (ld == DialogResult.No)
|
|
{
|
|
dumptoboxes = DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Save each box separately?");
|
|
|
|
// open folder dialog
|
|
FolderBrowserDialog fbd = new FolderBrowserDialog();
|
|
if (fbd.ShowDialog() != DialogResult.OK)
|
|
return;
|
|
|
|
path = fbd.SelectedPath;
|
|
}
|
|
else return;
|
|
|
|
dumpBoxesToDB(path, dumptoboxes);
|
|
}
|
|
// Misc Options
|
|
private void clickShowdownImportPK6(object sender, EventArgs e)
|
|
{
|
|
if (!Clipboard.ContainsText())
|
|
{ Util.Alert("Clipboard does not contain text."); return; }
|
|
|
|
// Get Simulator Data
|
|
PKX.ShowdownSet Set = new PKX.ShowdownSet(Clipboard.GetText());
|
|
|
|
if (Set.Species < 0)
|
|
{ Util.Alert("Set data not found in clipboard."); return; }
|
|
|
|
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo, "Import this set?", Clipboard.GetText()))
|
|
{ return; }
|
|
|
|
// Set Species & Nickname
|
|
CB_Species.SelectedValue = Set.Species;
|
|
CHK_Nicknamed.Checked = Set.Nickname != null;
|
|
if (Set.Nickname != null)
|
|
TB_Nickname.Text = Set.Nickname;
|
|
if (Set.Gender != null && PKX.getGender(Set.Gender) != 2 && PKX.getGender(Set.Gender) != 2)
|
|
{
|
|
int Gender = PKX.getGender(Set.Gender);
|
|
Label_Gender.Text = gendersymbols[Gender];
|
|
Label_Gender.ForeColor = Gender == 2 ? Label_Species.ForeColor : (Gender == 1 ? Color.Red : Color.Blue);
|
|
}
|
|
|
|
// Set Form
|
|
string[] formStrings = PKX.getFormList(Set.Species,
|
|
Util.getStringList("Types", "en"),
|
|
Util.getStringList("Forms", "en"), gendersymbols);
|
|
int form = 0;
|
|
for (int i = 0; i < formStrings.Length; i++)
|
|
if (formStrings[i].Contains(Set.Form ?? ""))
|
|
{ form = i; break; }
|
|
CB_Form.SelectedIndex = form;
|
|
|
|
// Set Ability
|
|
byte[] abilities = PKX.getAbilities(Set.Species, form);
|
|
int ability = Array.IndexOf(abilities, (byte)Set.Ability);
|
|
if (ability < 0) ability = 0;
|
|
CB_Ability.SelectedIndex = ability;
|
|
ComboBox[] m = { CB_Move1, CB_Move2, CB_Move3, CB_Move4, };
|
|
for (int i = 0; i < 4; i++) m[i].SelectedValue = Set.Moves[i];
|
|
|
|
// Set Item and Nature
|
|
CB_HeldItem.SelectedValue = Set.Item < 0 ? 0 : Set.Item;
|
|
CB_Nature.SelectedValue = Set.Nature < 0 ? 0 : Set.Nature;
|
|
|
|
// Set IVs
|
|
TB_HPIV.Text = Set.IVs[0].ToString();
|
|
TB_ATKIV.Text = Set.IVs[1].ToString();
|
|
TB_DEFIV.Text = Set.IVs[2].ToString();
|
|
TB_SPAIV.Text = Set.IVs[3].ToString();
|
|
TB_SPDIV.Text = Set.IVs[4].ToString();
|
|
TB_SPEIV.Text = Set.IVs[5].ToString();
|
|
|
|
// Set EVs
|
|
TB_HPEV.Text = Set.EVs[0].ToString();
|
|
TB_ATKEV.Text = Set.EVs[1].ToString();
|
|
TB_DEFEV.Text = Set.EVs[2].ToString();
|
|
TB_SPAEV.Text = Set.EVs[3].ToString();
|
|
TB_SPDEV.Text = Set.EVs[4].ToString();
|
|
TB_SPEEV.Text = Set.EVs[5].ToString();
|
|
|
|
// Set Level and Friendship
|
|
TB_Level.Text = Set.Level.ToString();
|
|
TB_Friendship.Text = Set.Friendship.ToString();
|
|
|
|
// Reset IV/EVs
|
|
BTN_RerollPID.PerformClick();
|
|
BTN_RerollEC.PerformClick();
|
|
if (Set.Shiny) BTN_Shinytize.PerformClick();
|
|
}
|
|
private void clickShowdownExportPK6(object sender, EventArgs e)
|
|
{
|
|
if (!verifiedPKX())
|
|
{ Util.Alert("Fix data before exporting."); return; }
|
|
|
|
Clipboard.SetText(preparepkx().ShowdownText);
|
|
Util.Alert("Exported Showdown Set to Clipboard:", Clipboard.GetText());
|
|
}
|
|
private void clickShowdownExportParty(object sender, EventArgs e)
|
|
{
|
|
if (SAV.PartyData.Length <= 0) return;
|
|
try
|
|
{
|
|
Clipboard.SetText(
|
|
SAV.PartyData.Aggregate("", (current, pk) => current + pk.ShowdownText
|
|
+ Environment.NewLine + Environment.NewLine).Trim());
|
|
Util.Alert("Showdown Team (Party) set to Clipboard.");
|
|
}
|
|
catch { }
|
|
}
|
|
private void clickShowdownExportBattleBox(object sender, EventArgs e)
|
|
{
|
|
if (SAV.BattleBoxData.Length <= 0) return;
|
|
try
|
|
{
|
|
Clipboard.SetText(
|
|
SAV.BattleBoxData.Aggregate("", (current, pk) => current + pk.ShowdownText
|
|
+ Environment.NewLine + Environment.NewLine).Trim());
|
|
Util.Alert("Showdown Team (Battle Box) set to Clipboard.");
|
|
}
|
|
catch { }
|
|
}
|
|
private void clickOpenTempFolder(object sender, EventArgs e)
|
|
{
|
|
string path = Util.GetTempFolder();
|
|
if (Directory.Exists(Path.Combine(path, "root")))
|
|
Process.Start("explorer.exe", @Path.Combine(path, "root"));
|
|
else if (Directory.Exists(path))
|
|
Process.Start("explorer.exe", @path);
|
|
else
|
|
Util.Alert("Can't find the temporary file.", "Make sure the Cyber Gadget software is paused.");
|
|
}
|
|
private void clickOpenCacheFolder(object sender, EventArgs e)
|
|
{
|
|
string path = Util.GetCacheFolder();
|
|
if (Directory.Exists(path))
|
|
Process.Start("explorer.exe", @path);
|
|
else
|
|
Util.Alert("Can't find the cache folder.");
|
|
}
|
|
private void clickOpenSDFFolder(object sender, EventArgs e)
|
|
{
|
|
string path;
|
|
if (path3DS != null && Directory.Exists(path = Util.GetSDFLocation()))
|
|
Process.Start("explorer.exe", @path);
|
|
else
|
|
Util.Alert("Can't find the SaveDataFiler folder.");
|
|
}
|
|
private void clickOpenSDBFolder(object sender, EventArgs e)
|
|
{
|
|
string path;
|
|
if (path3DS != null && Directory.Exists(path = Path.Combine(Path.GetPathRoot(path3DS), "SaveDataBackup")))
|
|
Process.Start("explorer.exe", @path);
|
|
else
|
|
Util.Alert("Can't find the SaveDataBackup folder.");
|
|
}
|
|
|
|
// Main Menu Subfunctions
|
|
private void openQuick(string path)
|
|
{
|
|
// detect if it is a folder (load into boxes or not)
|
|
if (Directory.Exists(path))
|
|
{ loadBoxesFromDB(path); return; }
|
|
|
|
string ext = Path.GetExtension(path);
|
|
FileInfo fi = new FileInfo(path);
|
|
if (fi.Length > 0x10009C)
|
|
Util.Error("Input file is too large.", path);
|
|
else
|
|
{
|
|
byte[] input; try { input = File.ReadAllBytes(path); }
|
|
catch { Util.Error("File is in use by another program!", path); return; }
|
|
|
|
try { openFile(input, path, ext); }
|
|
catch
|
|
{
|
|
try
|
|
{
|
|
byte[] blank = (byte[])blankEK6.Clone();
|
|
|
|
for (int i = 0; i < PK6.SIZE_STORED; i++)
|
|
blank[i] ^= input[i];
|
|
|
|
openFile(blank, path, ext);
|
|
}
|
|
catch { openFile(input, path, ext); }
|
|
}
|
|
}
|
|
}
|
|
private void openFile(byte[] input, string path, string ext)
|
|
{
|
|
#region Powersaves Read-Only Conversion
|
|
if (input.Length == 0x10009C) // Resize to 1MB
|
|
{
|
|
Array.Copy(input, 0x9C, input, 0, 0x100000);
|
|
Array.Resize(ref input, 0x100000);
|
|
}
|
|
#endregion
|
|
#region Saves
|
|
if ((input.Length == SAV6.SIZE_ORAS) && BitConverter.ToUInt32(input, SAV6.SIZE_ORAS - 0x1F0) == SAV6.BEEF) // ORAS
|
|
openMAIN(input, path);
|
|
else if ((input.Length == SAV6.SIZE_XY) && BitConverter.ToUInt32(input, SAV6.SIZE_XY - 0x1F0) == SAV6.BEEF) // XY
|
|
openMAIN(input, path);
|
|
else if ((input.Length == SAV6.SIZE_ORASDEMO) && BitConverter.ToUInt32(input, SAV6.SIZE_ORASDEMO - 0x1F0) == SAV6.BEEF) // ORAS Demo
|
|
openMAIN(input, path);
|
|
// Verify the Data Input Size is Proper
|
|
else if (input.Length == 0x100000)
|
|
{
|
|
if (openXOR(input, path)) // Check if we can load the save via xorpad
|
|
return; // only if a save is loaded we abort
|
|
if (BitConverter.ToUInt64(input, 0x10) != 0) // encrypted save
|
|
{ Util.Error("PKHeX only edits decrypted save files." + Environment.NewLine + "This save file is not decrypted.", path); return; }
|
|
|
|
DialogResult sdr = Util.Prompt(MessageBoxButtons.YesNoCancel, "Press Yes to load the sav at 0x3000", "Press No for the one at 0x82000");
|
|
if (sdr == DialogResult.Cancel)
|
|
return;
|
|
int savshift = sdr == DialogResult.Yes ? 0 : 0x7F000;
|
|
byte[] psdata = input.Skip(0x5400 + savshift).Take(SAV6.SIZE_ORAS).ToArray();
|
|
if (BitConverter.ToUInt32(psdata, psdata.Length - 0x1F0) != SAV6.BEEF)
|
|
Array.Resize(ref psdata, SAV6.SIZE_XY);
|
|
if (BitConverter.ToUInt32(psdata, psdata.Length - 0x1F0) != SAV6.BEEF)
|
|
{ Util.Error("The data file is not a valid save file", path); return; }
|
|
|
|
openMAIN(psdata, path);
|
|
}
|
|
#endregion
|
|
#region PK6/EK6
|
|
else if ((input.Length == PK6.SIZE_PARTY || input.Length == PK6.SIZE_STORED) && ext != ".pgt")
|
|
{
|
|
// Check if Input is PKX
|
|
if (new[] {".pk6", ".ek6", ".pkx", ".ekx", ""}.Contains(ext))
|
|
{
|
|
// Check if Encrypted before Loading
|
|
populateFields(new PK6(BitConverter.ToUInt16(input, 0xC8) == 0 && BitConverter.ToUInt16(input, 0x58) == 0 ? input : PKX.decryptArray(input)));
|
|
}
|
|
else
|
|
Util.Error("Unable to recognize file." + Environment.NewLine + "Only valid .pk* .ek* .bin supported.",
|
|
$"File Loaded:{Environment.NewLine}{path}");
|
|
}
|
|
#endregion
|
|
#region PK3/PK4/PK5 Conversion
|
|
else if (new[] { PK3.SIZE_PARTY, PK3.SIZE_STORED, PK4.SIZE_PARTY, PK4.SIZE_STORED, PK5.SIZE_PARTY }.Contains(input.Length))
|
|
{
|
|
if (!PKX.verifychk(input)) Util.Error("Invalid File (Checksum Error)");
|
|
try // to convert g5pkm
|
|
{
|
|
populateFields(Converter.ConvertPKMtoPK6(input));
|
|
}
|
|
catch
|
|
{
|
|
populateFields(new PK6());
|
|
Util.Error("Attempted to load previous generation PKM.", "Conversion failed.");
|
|
}
|
|
}
|
|
#endregion
|
|
#region Box Data
|
|
else if ((input.Length == PK6.SIZE_STORED * 30 || input.Length == PK6.SIZE_STORED * 30 * 31) && BitConverter.ToUInt16(input, 4) == 0 && BitConverter.ToUInt32(input, 8) > 0)
|
|
{
|
|
int baseOffset = SAV.Box + PK6.SIZE_STORED * 30 * (input.Length == PK6.SIZE_STORED * 30 ? CB_BoxSelect.SelectedIndex : 0);
|
|
for (int i = 0; i < input.Length / PK6.SIZE_STORED; i++)
|
|
{
|
|
byte[] data = input.Skip(PK6.SIZE_STORED * i).Take(PK6.SIZE_STORED).ToArray();
|
|
SAV.setEK6Stored(data, baseOffset + i * PK6.SIZE_STORED);
|
|
}
|
|
setPKXBoxes();
|
|
Util.Alert("Box Binary loaded.");
|
|
}
|
|
#endregion
|
|
#region Battle Video
|
|
else if (input.Length == 0x2E60 && BitConverter.ToUInt64(input, 0xE18) != 0 && BitConverter.ToUInt16(input, 0xE12) == 0)
|
|
{
|
|
if (Util.Prompt(MessageBoxButtons.YesNo, "Load Batte Video Pokémon data to " + CB_BoxSelect.Text + "?", "The first 24 slots will be overwritten.") != DialogResult.Yes) return;
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
byte[] data = input.Skip(0xE18 + PK6.SIZE_PARTY * i + i / 6 * 8).Take(PK6.SIZE_STORED).ToArray();
|
|
SAV.setEK6Stored(data, SAV.Box + i*PK6.SIZE_STORED + CB_BoxSelect.SelectedIndex*30*PK6.SIZE_STORED);
|
|
}
|
|
setPKXBoxes();
|
|
}
|
|
#endregion
|
|
#region Wondercard
|
|
else if (input.Length == WC6.Size && ext == ".wc6")
|
|
if (ModifierKeys == Keys.Control)
|
|
new SAV_Wondercard(input).Show();
|
|
else
|
|
{
|
|
PK6 pk = new WC6(input).convertToPK6(SAV);
|
|
if (pk == null || pk.Species == 0 || pk.Species > 721)
|
|
{
|
|
Util.Error("Failed to convert Wondercard.",
|
|
pk == null ? "Not a Pokémon Wondercard." : "Invalid species.");
|
|
return;
|
|
}
|
|
populateFields(pk);
|
|
}
|
|
else if (input.Length == PGF.Size && ext == ".pgf")
|
|
{
|
|
PK5 pk = new PGF(input).convertToPK5(SAV);
|
|
if (pk == null || pk.Species == 0 || pk.Species > 721)
|
|
{
|
|
Util.Error("Failed to convert PGF.",
|
|
pk == null ? "Not a Pokémon PGF." : "Invalid species.");
|
|
return;
|
|
}
|
|
populateFields(Converter.ConvertPKMtoPK6(pk.Data));
|
|
}
|
|
else if (input.Length == PGT.Size && ext == ".pgt")
|
|
{
|
|
PGT pgt = new PGT(input);
|
|
PK4 pk = pgt.convertToPK4(SAV);
|
|
if (pk == null || pk.Species == 0 || pk.Species > 721)
|
|
{
|
|
Util.Error("Failed to convert PGT.",
|
|
pk == null ? "Not a Pokémon PGT." : "Invalid species.");
|
|
return;
|
|
}
|
|
populateFields(Converter.ConvertPKMtoPK6(pk.Data));
|
|
}
|
|
else if (input.Length == PCD.Size && ext == ".pcd")
|
|
{
|
|
PCD pcd = new PCD(input);
|
|
PGT pgt = pcd.Gift;
|
|
PK4 pk = pgt.convertToPK4(SAV);
|
|
if (pk == null || pk.Species == 0 || pk.Species > 721)
|
|
{
|
|
Util.Error("Failed to convert PCD.",
|
|
pk == null ? "Not a Pokémon PCD." : "Invalid species.");
|
|
return;
|
|
}
|
|
populateFields(Converter.ConvertPKMtoPK6(pk.Data));
|
|
}
|
|
#endregion
|
|
else
|
|
Util.Error("Attempted to load an unsupported file type/size.",
|
|
$"File Loaded:{Environment.NewLine}{path}",
|
|
$"File Size:{Environment.NewLine}{input.Length} bytes (0x{input.Length.ToString("X4")})");
|
|
}
|
|
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);
|
|
|
|
int loop = 0;
|
|
check:
|
|
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(SAV6.SIZE_ORAS).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, SAV6.SIZE_ORAS - 0x1F0) != SAV6.BEEF) // Not OR/AS
|
|
if (BitConverter.ToUInt32(decryptedPS, SAV6.SIZE_XY - 0x1F0) != SAV6.BEEF) // Not X/Y
|
|
continue;
|
|
else
|
|
Array.Resize(ref decryptedPS, SAV6.SIZE_XY); // set to X/Y size
|
|
else Array.Resize(ref decryptedPS, SAV6.SIZE_ORAS); // set to ORAS size just in case
|
|
|
|
// Save file is now decrypted!
|
|
|
|
// Trigger Loading of the decrypted save file.
|
|
openMAIN(decryptedPS, path);
|
|
|
|
// Abort the opening of a non-cyber file.
|
|
return true;
|
|
}
|
|
// End file check loop, check the input path for xorpads too if it isn't the same as the EXE (quite common).
|
|
if (xorpath != exepath || loop++ > 0) return false; // no xorpad compatible
|
|
xorpath = Path.GetDirectoryName(path); goto check;
|
|
}
|
|
private void openMAIN(byte[] input, string path)
|
|
{
|
|
SAV = new SAV6(input)
|
|
{
|
|
FilePath = Path.GetDirectoryName(path),
|
|
FileName = Path.GetExtension(path) == ".bak"
|
|
? Path.GetFileName(path).Split(new[] { " [" }, StringSplitOptions.None)[0]
|
|
: Path.GetFileName(path)
|
|
};
|
|
L_Save.Text = "SAV: " + Path.GetFileNameWithoutExtension(Util.CleanFileName(SAV.BAKName)); // more descriptive
|
|
|
|
// Enable Secondary Tools
|
|
GB_SAVtools.Enabled = B_JPEG.Enabled = true;
|
|
Menu_ExportSAV.Enabled = B_VerifyCHK.Enabled = SAV.Exportable;
|
|
|
|
DaycareSlot = 0;
|
|
|
|
setBoxNames(); // Display the Box Names
|
|
setPKXBoxes(); // Reload all of the PKX Windows
|
|
|
|
// Version Exclusive Editors
|
|
GB_SUBE.Visible = !SAV.ORAS;
|
|
B_OpenSecretBase.Visible = SAV.ORAS;
|
|
|
|
if (SAV.Box > -1)
|
|
{
|
|
int startBox = SAV.CurrentBox; // FF if BattleBox
|
|
if (startBox > 30) { tabBoxMulti.SelectedIndex = 1; CB_BoxSelect.SelectedIndex = 0; }
|
|
else { tabBoxMulti.SelectedIndex = 0; CB_BoxSelect.SelectedIndex = startBox; }
|
|
}
|
|
|
|
TB_GameSync.Enabled = SAV.GameSyncID != 0;
|
|
TB_GameSync.Text = SAV.GameSyncID.ToString("X16");
|
|
TB_Secure1.Text = SAV.Secure1.ToString("X16");
|
|
TB_Secure2.Text = SAV.Secure2.ToString("X16");
|
|
PB_Locked.Visible = SAV.BattleBoxLocked;
|
|
|
|
// Hide content if not present in game.
|
|
PAN_Box.Visible = CB_BoxSelect.Visible = B_BoxLeft.Visible = B_BoxRight.Visible = SAV.Box > -1;
|
|
Menu_LoadBoxes.Enabled = Menu_Report.Enabled = Menu_Modify.Enabled = B_SaveBoxBin.Enabled = SAV.Box > -1;
|
|
PAN_BattleBox.Visible = L_BattleBox.Visible = L_ReadOnlyPBB.Visible = SAV.BattleBox > -1;
|
|
GB_Daycare.Visible = SAV.Daycare > -1;
|
|
GB_Fused.Visible = SAV.Fused > -1;
|
|
GB_GTS.Visible = SAV.GTS > -1;
|
|
B_OpenSecretBase.Enabled = SAV.SecretBase > -1;
|
|
B_OpenPokepuffs.Enabled = SAV.Puff > -1;
|
|
B_OUTPasserby.Enabled = SAV.PSS > -1;
|
|
B_OpenBoxLayout.Enabled = SAV.BoxWallpapers > -1;
|
|
B_OpenWondercards.Enabled = SAV.WondercardFlags > -1;
|
|
B_OpenSuperTraining.Enabled = SAV.SuperTrain > -1;
|
|
B_OpenHallofFame.Enabled = SAV.HoF > -1;
|
|
B_OpenOPowers.Enabled = SAV.OPower > -1;
|
|
B_OpenPokedex.Enabled = SAV.PokeDex > -1;
|
|
B_OpenBerryField.Enabled = SAV.BerryField > -1;
|
|
B_JPEG.Enabled = SAV.JPEG > -1;
|
|
|
|
// Refresh PK#->PK6 conversion info
|
|
Converter.updateConfig(SAV.SubRegion, SAV.Country, SAV.ConsoleRegion, SAV.OT, SAV.Gender);
|
|
|
|
// Indicate audibly the save is loaded
|
|
SystemSounds.Beep.Play();
|
|
|
|
// If backup folder exists, save a backup.
|
|
string backupName = Path.Combine(BackupPath, Util.CleanFileName(SAV.BAKName));
|
|
if (SAV.Exportable && Directory.Exists(BackupPath) && !File.Exists(backupName))
|
|
File.WriteAllBytes(backupName, SAV.BAK);
|
|
}
|
|
private void refreshWC6DB()
|
|
{
|
|
List<WC6> wc6db = new List<WC6>();
|
|
byte[] wc6bin = Properties.Resources.wc6;
|
|
for (int i = 0; i < wc6bin.Length; i += WC6.Size)
|
|
wc6db.Add(new WC6(wc6bin.Skip(i).Take(WC6.Size).ToArray()));
|
|
|
|
if (Directory.Exists(WC6DatabasePath))
|
|
wc6db.AddRange(from file in Directory.GetFiles(WC6DatabasePath, "*", SearchOption.AllDirectories)
|
|
let fi = new FileInfo(file)
|
|
where fi.Extension == ".wc6" && fi.Length == WC6.Size
|
|
select new WC6(File.ReadAllBytes(file)));
|
|
|
|
Legal.WC6DB = wc6db.Distinct().ToArray();
|
|
}
|
|
|
|
// Language Translation
|
|
private void changeMainLanguage(object sender, EventArgs e)
|
|
{
|
|
PK6 pk = fieldsInitialized ? preparepkx() : pk6;
|
|
bool alreadyInit = fieldsInitialized;
|
|
fieldsInitialized = false;
|
|
Menu_Options.DropDown.Close();
|
|
InitializeStrings();
|
|
InitializeLanguage();
|
|
Util.TranslateInterface(this, lang_val[CB_MainLanguage.SelectedIndex]); // Translate the UI to language.
|
|
populateFields(pk); // put data back in form
|
|
fieldsInitialized |= alreadyInit;
|
|
}
|
|
private void InitializeStrings()
|
|
{
|
|
if (CB_MainLanguage.SelectedIndex < 8)
|
|
curlanguage = lang_val[CB_MainLanguage.SelectedIndex];
|
|
|
|
string l = curlanguage;
|
|
natures = Util.getStringList("Natures", l);
|
|
types = Util.getStringList("Types", l);
|
|
abilitylist = Util.getStringList("Abilities", l);
|
|
movelist = Util.getStringList("Moves", l);
|
|
itemlist = Util.getStringList("Items", l);
|
|
characteristics = Util.getStringList("Character", l);
|
|
specieslist = Util.getStringList("Species", l);
|
|
wallpapernames = Util.getStringList("Wallpaper", l);
|
|
itempouch = Util.getStringList("ItemPouch", l);
|
|
encountertypelist = Util.getStringList("EncounterType", l);
|
|
gamelist = Util.getStringList("Games", l);
|
|
gamelanguages = Util.getNulledStringArray(Util.getStringList("languages"));
|
|
|
|
balllist = new string[Legal.Items_Ball.Length];
|
|
for (int i = 0; i < balllist.Length; i++)
|
|
balllist[i] = itemlist[Legal.Items_Ball[i]];
|
|
|
|
if ((l != "zh") || (l == "zh" && !fieldsInitialized)) // load initial binaries
|
|
{
|
|
pokeblocks = Util.getStringList("Pokeblock", l);
|
|
forms = Util.getStringList("Forms", l);
|
|
memories = Util.getStringList("Memories", l);
|
|
genloc = Util.getStringList("GenLoc", l);
|
|
trainingbags = Util.getStringList("TrainingBag", l);
|
|
trainingstage = Util.getStringList("SuperTraining", l);
|
|
puffs = Util.getStringList("Puff", l);
|
|
}
|
|
|
|
// Fix Item Names (Duplicate entries)
|
|
itemlist[456] += " (OLD)"; // S.S. Ticket
|
|
itemlist[463] += " (OLD)"; // Storage Key
|
|
itemlist[478] += " (OLD)"; // Basement Key
|
|
itemlist[626] += " (2)"; // Xtransceiver
|
|
itemlist[629] += " (2)"; // DNA Splicers
|
|
itemlist[637] += " (2)"; // Dropped Item
|
|
itemlist[707] += " (2)"; // Travel Trunk
|
|
itemlist[713] += " (2)"; // Alt Bike
|
|
itemlist[714] += " (2)"; // Holo Caster
|
|
itemlist[729] += " (1)"; // Meteorite
|
|
itemlist[740] += " (2)"; // Contest Costume
|
|
itemlist[751] += " (2)"; // Meteorite
|
|
itemlist[771] += " (3)"; // Meteorite
|
|
itemlist[772] += " (4)"; // Meteorite
|
|
|
|
// Get the Egg Name and then replace it with --- for the comboboxes.
|
|
eggname = specieslist[0];
|
|
specieslist[0] = "---";
|
|
|
|
// Get the met locations... for all of the games...
|
|
metHGSS_00000 = Util.getStringList("hgss_00000", l);
|
|
metHGSS_02000 = Util.getStringList("hgss_02000", l);
|
|
metHGSS_03000 = Util.getStringList("hgss_03000", l);
|
|
|
|
metBW2_00000 = Util.getStringList("bw2_00000", l);
|
|
metBW2_30000 = Util.getStringList("bw2_30000", l);
|
|
metBW2_40000 = Util.getStringList("bw2_40000", l);
|
|
metBW2_60000 = Util.getStringList("bw2_60000", l);
|
|
|
|
metXY_00000 = Util.getStringList("xy_00000", l);
|
|
metXY_30000 = Util.getStringList("xy_30000", l);
|
|
metXY_40000 = Util.getStringList("xy_40000", l);
|
|
metXY_60000 = Util.getStringList("xy_60000", l);
|
|
|
|
// Fix up some of the Location strings to make them more descriptive:
|
|
metHGSS_02000[1] += " (NPC)"; // Anything from an NPC
|
|
metHGSS_02000[2] += " (" + eggname + ")"; // Egg From Link Trade
|
|
metBW2_00000[36] = metBW2_00000[84] + "/" + metBW2_00000[36]; // Cold Storage in BW = PWT in BW2
|
|
|
|
// BW2 Entries from 76 to 105 are for Entralink in BW
|
|
for (int i = 76; i < 106; i++)
|
|
metBW2_00000[i] = metBW2_00000[i] + "●";
|
|
|
|
// Localize the Poketransfer to the language (30001)
|
|
string[] ptransp = { "Poké Transfer", "ポケシフター", "Poké Fret", "Pokétrasporto", "Poképorter", "Pokétransfer", "포케시프터", "ポケシフター" };
|
|
metBW2_30000[1 - 1] = ptransp[Array.IndexOf(lang_val, curlanguage)];
|
|
metBW2_30000[2 - 1] += " (NPC)"; // Anything from an NPC
|
|
metBW2_30000[3 - 1] += " (" + eggname + ")"; // Egg From Link Trade
|
|
|
|
// Zorua/Zoroark events
|
|
metBW2_30000[10 - 1] = specieslist[251] + " (" + specieslist[570] + " 1)"; // Celebi's Zorua Event
|
|
metBW2_30000[11 - 1] = specieslist[251] + " (" + specieslist[570] + " 2)"; // Celebi's Zorua Event
|
|
metBW2_30000[12 - 1] = specieslist[571] + " (" + "1)"; // Zoroark
|
|
metBW2_30000[13 - 1] = specieslist[571] + " (" + "2)"; // Zoroark
|
|
|
|
metBW2_60000[3 - 1] += " (" + eggname + ")"; // Egg Treasure Hunter/Breeder, whatever...
|
|
|
|
metXY_00000[104] += " (X/Y)"; // Victory Road
|
|
metXY_00000[298] += " (OR/AS)"; // Victory Road
|
|
metXY_30000[0] += " (NPC)"; // Anything from an NPC
|
|
metXY_30000[1] += " (" + eggname + ")"; // Egg From Link Trade
|
|
|
|
// 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] + ")";
|
|
|
|
// Force an update to the met locations
|
|
origintrack = "";
|
|
|
|
if (fieldsInitialized)
|
|
updateIVs(null, null); // Prompt an update for the characteristics
|
|
}
|
|
#endregion
|
|
|
|
#region //// PKX WINDOW FUNCTIONS ////
|
|
private void InitializeFields()
|
|
{
|
|
// Now that the ComboBoxes are ready, load the data.
|
|
fieldsInitialized = true;
|
|
pk6.Species = 493;
|
|
pk6.Move1 = 1;
|
|
pk6.RefreshChecksum();
|
|
|
|
// Load Data
|
|
populateFields(pk6);
|
|
{
|
|
TB_OT.Text = "PKHeX";
|
|
TB_TID.Text = 12345.ToString();
|
|
TB_SID.Text = 54321.ToString();
|
|
CB_GameOrigin.SelectedIndex = 0;
|
|
CB_Language.SelectedIndex = 0;
|
|
CB_BoxSelect.SelectedIndex = 0;
|
|
CB_GameOrigin.SelectedIndex = 0;
|
|
CB_PPu1.SelectedIndex = CB_PPu2.SelectedIndex = CB_PPu3.SelectedIndex = CB_PPu4.SelectedIndex = 0;
|
|
CB_Ball.SelectedIndex = 0;
|
|
CB_Country.SelectedIndex = 0;
|
|
setAbilityList(TB_AbilityNumber, Util.getIndex(CB_Species), CB_Ability, CB_Form);
|
|
}
|
|
}
|
|
private void InitializeLanguage()
|
|
{
|
|
// Set the Display
|
|
CB_Country.DisplayMember =
|
|
CB_SubRegion.DisplayMember =
|
|
CB_3DSReg.DisplayMember =
|
|
CB_Language.DisplayMember =
|
|
CB_Ball.DisplayMember =
|
|
CB_HeldItem.DisplayMember =
|
|
CB_Species.DisplayMember =
|
|
DEV_Ability.DisplayMember =
|
|
CB_Nature.DisplayMember =
|
|
CB_EncounterType.DisplayMember =
|
|
CB_GameOrigin.DisplayMember =
|
|
CB_HPType.DisplayMember = "Text";
|
|
|
|
// Set the Value
|
|
CB_Country.ValueMember =
|
|
CB_SubRegion.ValueMember =
|
|
CB_3DSReg.ValueMember =
|
|
CB_Language.ValueMember =
|
|
CB_Ball.ValueMember =
|
|
CB_HeldItem.ValueMember =
|
|
CB_Species.ValueMember =
|
|
DEV_Ability.ValueMember =
|
|
CB_Nature.ValueMember =
|
|
CB_EncounterType.ValueMember =
|
|
CB_GameOrigin.ValueMember =
|
|
CB_HPType.ValueMember = "Value";
|
|
|
|
// Set the various ComboBox DataSources up with their allowed entries
|
|
setCountrySubRegion(CB_Country, "countries");
|
|
CB_3DSReg.DataSource = Util.getUnsortedCBList("regions3ds");
|
|
CB_Language.DataSource = Util.getUnsortedCBList("languages");
|
|
int[] ball_nums = { 7, 576, 13, 492, 497, 14, 495, 493, 496, 494, 11, 498, 8, 6, 12, 15, 9, 5, 499, 10, 1, 16 };
|
|
int[] ball_vals = { 7, 25, 13, 17, 22, 14, 20, 18, 21, 19, 11, 23, 8, 6, 12, 15, 9, 5, 24, 10, 1, 16 };
|
|
BallDataSource = Util.getVariedCBList(itemlist, ball_nums, ball_vals);
|
|
ItemDataSource = Util.getCBList(itemlist, DEV_Ability.Enabled ? null : Legal.Items_Held);
|
|
SpeciesDataSource = Util.getCBList(specieslist, null);
|
|
NatureDataSource = Util.getCBList(natures, null);
|
|
AbilityDataSource = Util.getCBList(abilitylist, null);
|
|
VersionDataSource = Util.getCBList(gamelist, 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);
|
|
|
|
CB_Ball.DataSource = new BindingSource(BallDataSource, null);
|
|
CB_Species.DataSource = new BindingSource(SpeciesDataSource, null);
|
|
CB_HeldItem.DataSource = new BindingSource(ItemDataSource, null);
|
|
CB_Nature.DataSource = new BindingSource(NatureDataSource, null);
|
|
|
|
DEV_Ability.DataSource = new BindingSource(AbilityDataSource, null);
|
|
CB_EncounterType.DataSource = Util.getCBList(encountertypelist, new[] { 0 }, Legal.Gen4EncounterTypes);
|
|
CB_GameOrigin.DataSource = new BindingSource(VersionDataSource, null);
|
|
CB_HPType.DataSource = Util.getCBList(types.Skip(1).Take(16).ToArray(), null);
|
|
|
|
// Set the Move ComboBoxes too..
|
|
{
|
|
MoveDataSource = Util.getCBList(movelist, null);
|
|
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(MoveDataSource, null);
|
|
}
|
|
}
|
|
}
|
|
public void populateFields(PK6 pk, bool focus = true)
|
|
{
|
|
pk6 = pk ?? new PK6();
|
|
if (fieldsInitialized & !PKX.verifychk(pk6.Data))
|
|
Util.Alert("PKX File has an invalid checksum.");
|
|
|
|
// Reset a little.
|
|
bool oldInit = fieldsInitialized;
|
|
fieldsInitialized = fieldsLoaded = false;
|
|
CAL_EggDate.Value = new DateTime(2000, 01, 01);
|
|
if (focus)
|
|
Tab_Main.Focus();
|
|
|
|
// Do first
|
|
pk6.Stat_Level = PKX.getLevel(pk6.Species, pk6.EXP);
|
|
if (pk6.Stat_Level == 100)
|
|
pk6.EXP = PKX.getEXP(pk6.Stat_Level, pk6.Species);
|
|
|
|
CB_Species.SelectedValue = pk6.Species;
|
|
TB_Level.Text = pk6.Stat_Level.ToString();
|
|
TB_EXP.Text = pk6.EXP.ToString();
|
|
|
|
// Load rest
|
|
TB_EC.Text = pk6.EncryptionConstant.ToString("X8");
|
|
CHK_Fateful.Checked = pk6.FatefulEncounter;
|
|
CHK_IsEgg.Checked = pk6.IsEgg;
|
|
CHK_Nicknamed.Checked = pk6.IsNicknamed;
|
|
Label_OTGender.Text = gendersymbols[pk6.OT_Gender];
|
|
Label_OTGender.ForeColor = pk6.OT_Gender == 1 ? Color.Red : Color.Blue;
|
|
CHK_Circle.Checked = pk6.Circle;
|
|
CHK_Triangle.Checked = pk6.Triangle;
|
|
CHK_Square.Checked = pk6.Square;
|
|
CHK_Heart.Checked = pk6.Heart;
|
|
CHK_Star.Checked = pk6.Star;
|
|
CHK_Diamond.Checked = pk6.Diamond;
|
|
TB_PID.Text = pk6.PID.ToString("X8");
|
|
CB_HeldItem.SelectedValue = pk6.HeldItem;
|
|
setAbilityList(TB_AbilityNumber, pk6.Species, CB_Ability, CB_Form);
|
|
TB_AbilityNumber.Text = pk6.AbilityNumber.ToString();
|
|
CB_Ability.SelectedIndex = pk6.AbilityNumber < 6 ? pk6.AbilityNumber >> 1 : 0; // with some simple error handling
|
|
CB_Nature.SelectedValue = pk6.Nature;
|
|
TB_TID.Text = pk6.TID.ToString("00000");
|
|
TB_SID.Text = pk6.SID.ToString("00000");
|
|
TB_Nickname.Text = pk6.Nickname;
|
|
TB_OT.Text = pk6.OT_Name;
|
|
TB_OTt2.Text = pk6.HT_Name;
|
|
TB_Friendship.Text = pk6.CurrentFriendship.ToString();
|
|
if (pk6.CurrentHandler == 1) // HT
|
|
{
|
|
GB_nOT.BackgroundImage = mixedHighlight;
|
|
GB_OT.BackgroundImage = null;
|
|
}
|
|
else // = 0
|
|
{
|
|
GB_OT.BackgroundImage = mixedHighlight;
|
|
GB_nOT.BackgroundImage = null;
|
|
}
|
|
CB_Language.SelectedValue = pk6.Language;
|
|
CB_Country.SelectedValue = pk6.Country;
|
|
CB_SubRegion.SelectedValue = pk6.Region;
|
|
CB_3DSReg.SelectedValue = pk6.ConsoleRegion;
|
|
CB_GameOrigin.SelectedValue = pk6.Version;
|
|
CB_EncounterType.SelectedValue = pk6.Gen4 ? pk6.EncounterType : 0;
|
|
CB_Ball.SelectedValue = pk6.Ball;
|
|
|
|
if (pk6.Met_Month == 0) { pk6.Met_Month = 1; }
|
|
if (pk6.Met_Day == 0) { pk6.Met_Day = 1; }
|
|
try { CAL_MetDate.Value = new DateTime(pk6.Met_Year + 2000, pk6.Met_Month, pk6.Met_Day); }
|
|
catch { CAL_MetDate.Value = new DateTime(2000, 1, 1); }
|
|
|
|
if (pk6.Egg_Location != 0)
|
|
{
|
|
// Was obtained initially as an egg.
|
|
CHK_AsEgg.Checked = true;
|
|
GB_EggConditions.Enabled = true;
|
|
|
|
CB_EggLocation.SelectedValue = pk6.Egg_Location;
|
|
try { CAL_EggDate.Value = new DateTime(pk6.Egg_Year + 2000, pk6.Egg_Month, pk6.Egg_Day); }
|
|
catch { CAL_MetDate.Value = new DateTime(2000, 1, 1); }
|
|
}
|
|
else { CHK_AsEgg.Checked = GB_EggConditions.Enabled = false; CB_EggLocation.SelectedValue = 0; }
|
|
|
|
CB_MetLocation.SelectedValue = pk6.Met_Location;
|
|
|
|
// Set CT Gender to None if no CT, else set to gender symbol.
|
|
Label_CTGender.Text = pk6.HT_Name == "" ? "" : gendersymbols[pk6.HT_Gender];
|
|
Label_CTGender.ForeColor = pk6.HT_Gender == 1 ? Color.Red : Color.Blue;
|
|
|
|
TB_MetLevel.Text = pk6.Met_Level.ToString();
|
|
|
|
// Reset Label and ComboBox visibility, as well as non-data checked status.
|
|
Label_PKRS.Visible = CB_PKRSStrain.Visible = CHK_Infected.Checked = pk6.PKRS_Strain != 0;
|
|
Label_PKRSdays.Visible = CB_PKRSDays.Visible = pk6.PKRS_Days != 0;
|
|
|
|
// Set SelectedIndexes for PKRS
|
|
CB_PKRSStrain.SelectedIndex = pk6.PKRS_Strain;
|
|
CHK_Cured.Checked = pk6.PKRS_Strain > 0 && pk6.PKRS_Days == 0;
|
|
CB_PKRSDays.SelectedIndex = Math.Min(CB_PKRSDays.Items.Count - 1, pk6.PKRS_Days); // to strip out bad hacked 'rus
|
|
|
|
TB_Cool.Text = pk6.CNT_Cool.ToString();
|
|
TB_Beauty.Text = pk6.CNT_Beauty.ToString();
|
|
TB_Cute.Text = pk6.CNT_Cute.ToString();
|
|
TB_Smart.Text = pk6.CNT_Smart.ToString();
|
|
TB_Tough.Text = pk6.CNT_Tough.ToString();
|
|
TB_Sheen.Text = pk6.CNT_Sheen.ToString();
|
|
|
|
TB_HPIV.Text = pk6.IV_HP.ToString();
|
|
TB_ATKIV.Text = pk6.IV_ATK.ToString();
|
|
TB_DEFIV.Text = pk6.IV_DEF.ToString();
|
|
TB_SPEIV.Text = pk6.IV_SPE.ToString();
|
|
TB_SPAIV.Text = pk6.IV_SPA.ToString();
|
|
TB_SPDIV.Text = pk6.IV_SPD.ToString();
|
|
CB_HPType.SelectedValue = pk6.HPType;
|
|
|
|
TB_HPEV.Text = pk6.EV_HP.ToString();
|
|
TB_ATKEV.Text = pk6.EV_ATK.ToString();
|
|
TB_DEFEV.Text = pk6.EV_DEF.ToString();
|
|
TB_SPEEV.Text = pk6.EV_SPE.ToString();
|
|
TB_SPAEV.Text = pk6.EV_SPA.ToString();
|
|
TB_SPDEV.Text = pk6.EV_SPD.ToString();
|
|
|
|
CB_Move1.SelectedValue = pk6.Move1;
|
|
CB_Move2.SelectedValue = pk6.Move2;
|
|
CB_Move3.SelectedValue = pk6.Move3;
|
|
CB_Move4.SelectedValue = pk6.Move4;
|
|
CB_RelearnMove1.SelectedValue = pk6.RelearnMove1;
|
|
CB_RelearnMove2.SelectedValue = pk6.RelearnMove2;
|
|
CB_RelearnMove3.SelectedValue = pk6.RelearnMove3;
|
|
CB_RelearnMove4.SelectedValue = pk6.RelearnMove4;
|
|
CB_PPu1.SelectedIndex = pk6.Move1_PPUps;
|
|
CB_PPu2.SelectedIndex = pk6.Move2_PPUps;
|
|
CB_PPu3.SelectedIndex = pk6.Move3_PPUps;
|
|
CB_PPu4.SelectedIndex = pk6.Move4_PPUps;
|
|
TB_PP1.Text = pk6.Move1_PP.ToString();
|
|
TB_PP2.Text = pk6.Move2_PP.ToString();
|
|
TB_PP3.Text = pk6.Move3_PP.ToString();
|
|
TB_PP4.Text = pk6.Move4_PP.ToString();
|
|
|
|
// Set Form if count is enough, else if count is more than 1 set equal to max else zero.
|
|
CB_Form.SelectedIndex = CB_Form.Items.Count > pk6.AltForm ? pk6.AltForm : (CB_Form.Items.Count > 1 ? CB_Form.Items.Count - 1 : 0);
|
|
|
|
// Load Extrabyte Value
|
|
TB_ExtraByte.Text = pk6.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString();
|
|
|
|
updateStats();
|
|
setIsShiny();
|
|
|
|
CB_EncounterType.Visible = Label_EncounterType.Visible = pk6.Gen4;
|
|
|
|
fieldsInitialized = oldInit;
|
|
updateIVs(null, null);
|
|
updatePKRSInfected(null, null);
|
|
updatePKRSCured(null, null);
|
|
|
|
TB_EXP.Text = pk6.EXP.ToString();
|
|
Label_Gender.Text = gendersymbols[pk6.Gender];
|
|
Label_Gender.ForeColor = pk6.Gender == 2 ? Label_Species.ForeColor : (pk6.Gender == 1 ? Color.Red : Color.Blue);
|
|
|
|
if (HaX) // DEV Illegality
|
|
{
|
|
DEV_Ability.SelectedValue = pk6.Ability;
|
|
MT_Level.Text = pk6.Stat_Level.ToString();
|
|
MT_Form.Text = pk6.AltForm.ToString();
|
|
}
|
|
|
|
// Set the Preview Box
|
|
dragout.Image = pk6.Sprite;
|
|
|
|
// Highlight the Current Handler
|
|
clickGT(pk6.CurrentHandler == 1 ? GB_nOT : GB_OT, null);
|
|
|
|
fieldsLoaded = true;
|
|
updateLegality();
|
|
}
|
|
// General Use Functions shared by other Forms //
|
|
internal static void setCountrySubRegion(ComboBox CB, string type)
|
|
{
|
|
int index = CB.SelectedIndex;
|
|
// fix for Korean / Chinese being swapped
|
|
string cl = curlanguage + "";
|
|
cl = cl == "zh" ? "ko" : cl == "ko" ? "zh" : cl;
|
|
|
|
CB.DataSource = Util.getCBList(type, cl);
|
|
|
|
if (index > 0 && index < CB.Items.Count && fieldsInitialized)
|
|
CB.SelectedIndex = index;
|
|
}
|
|
internal static void setForms(int species, ComboBox cb, Label l = null)
|
|
{
|
|
// Form Tables
|
|
cb.DisplayMember = "Text";
|
|
cb.ValueMember = "Value";
|
|
bool hasForms = PKX.Personal[species].HasFormes || new[] { 664, 665, 414, }.Contains(species);
|
|
cb.Enabled = cb.Visible = hasForms;
|
|
if (l != null) l.Visible = hasForms;
|
|
|
|
cb.DataSource = PKX.getFormList(species, types, forms, gendersymbols).ToList();
|
|
}
|
|
internal static void setAbilityList(MaskedTextBox tb_abil, int species, ComboBox cb_abil, ComboBox cb_forme)
|
|
{
|
|
if (!fieldsInitialized && string.IsNullOrWhiteSpace(tb_abil.Text))
|
|
return;
|
|
int newabil = Convert.ToInt16(tb_abil.Text) >> 1;
|
|
|
|
int form = cb_forme.SelectedIndex;
|
|
byte[] abils = PKX.getAbilities(species, form);
|
|
|
|
// Build Ability List
|
|
List<string> ability_list = new List<string>
|
|
{
|
|
abilitylist[abils[0]] + " (1)",
|
|
abilitylist[abils[1]] + " (2)",
|
|
abilitylist[abils[2]] + " (H)"
|
|
};
|
|
cb_abil.DataSource = ability_list;
|
|
|
|
cb_abil.SelectedIndex = newabil < 3 ? newabil : 0;
|
|
}
|
|
// PKX Data Calculation Functions //
|
|
private void setIsShiny()
|
|
{
|
|
bool isShiny = PKX.getIsShiny(Util.getHEXval(TB_PID.Text), Util.ToUInt32(TB_TID.Text), Util.ToUInt32(TB_SID.Text));
|
|
|
|
// Set the Controls
|
|
BTN_Shinytize.Visible = BTN_Shinytize.Enabled = !isShiny;
|
|
Label_IsShiny.Visible = isShiny;
|
|
|
|
// Refresh Markings (for Shiny Star if applicable)
|
|
setMarkings();
|
|
}
|
|
private void setMarkings()
|
|
{
|
|
PictureBox[] pba = { PB_Mark1, PB_Mark2, PB_Mark3, PB_Mark4, PB_Mark5, PB_Mark6 };
|
|
CheckBox[] cba = { CHK_Circle, CHK_Triangle, CHK_Square, CHK_Heart, CHK_Star, CHK_Diamond };
|
|
for (int i = 0; i < 6; i++)
|
|
pba[i].Image = Util.ChangeOpacity(pba[i].InitialImage, (cba[i].Checked ? 1 : 0) * 0.9 + 0.1);
|
|
|
|
PB_MarkShiny.Image = Util.ChangeOpacity(PB_MarkShiny.InitialImage, (!BTN_Shinytize.Enabled ? 1 : 0) * 0.9 + 0.1);
|
|
PB_MarkCured.Image = Util.ChangeOpacity(PB_MarkCured.InitialImage, (CHK_Cured.Checked ? 1 : 0) * 0.9 + 0.1);
|
|
|
|
int Version = Util.getIndex(CB_GameOrigin); // 24,25 = XY, 26,27 = ORAS, 28,29 = ???
|
|
PB_MarkPentagon.Image = Util.ChangeOpacity(PB_MarkPentagon.InitialImage, (Version >= 24 && Version <= 29 ? 1 : 0) * 0.9 + 0.1);
|
|
}
|
|
// Clicked Label Shortcuts //
|
|
private void clickQR(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys == Keys.Alt)
|
|
{
|
|
// Fetch data from QR code...
|
|
byte[] ekx = Util.getQRData();
|
|
|
|
if (ekx == null) return;
|
|
|
|
if (ekx.Length != PK6.SIZE_STORED) { Util.Alert($"Decoded data not {PK6.SIZE_STORED} bytes.", $"QR Data Size: {ekx.Length}"); }
|
|
else try
|
|
{
|
|
PK6 pk = new PK6(PKX.decryptArray(ekx));
|
|
if (pk.ChecksumValid) { populateFields(pk); }
|
|
else Util.Alert("Invalid checksum in QR data.");
|
|
}
|
|
catch { Util.Alert("Error loading decrypted data."); }
|
|
}
|
|
else
|
|
{
|
|
if (!verifiedPKX()) return;
|
|
PK6 pkx = preparepkx();
|
|
byte[] ekx = pkx.EncryptedBoxData;
|
|
const string server = "http://loadcode.projectpokemon.org/b1s1.html#"; // Rehosted with permission from LC/MS -- massive thanks!
|
|
Image qr = Util.getQRImage(ekx, server);
|
|
|
|
if (qr == null) return;
|
|
|
|
string[] r = pkx.QRText;
|
|
new QR(qr, dragout.Image, r[0], r[1], r[2], "PKHeX @ ProjectPokemon.org").ShowDialog();
|
|
}
|
|
}
|
|
private void clickFriendship(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys == Keys.Control) // prompt to reset
|
|
TB_Friendship.Text = pk6.CurrentHandler == 0 ? pk6.OT_Friendship.ToString() : pk6.HT_Friendship.ToString();
|
|
else
|
|
TB_Friendship.Text = TB_Friendship.Text == "255" ? PKX.getBaseFriendship(pk6.Species).ToString() : "255";
|
|
}
|
|
private void clickGender(object sender, EventArgs e)
|
|
{
|
|
// Get Gender Threshold
|
|
int gt = PKX.Personal[Util.getIndex(CB_Species)].Gender;
|
|
|
|
if (gt == 255 || gt == 0 || gt == 254) // Single gender/genderless
|
|
return;
|
|
|
|
if (gt >= 255) return;
|
|
// If not a single gender(less) species: (should be <254 but whatever, 255 never happens)
|
|
|
|
pk6.Gender = PKX.getGender(Label_Gender.Text) ^ 1;
|
|
Label_Gender.Text = gendersymbols[pk6.Gender];
|
|
Label_Gender.ForeColor = pk6.Gender == 2 ? Label_Species.ForeColor : (pk6.Gender == 1 ? Color.Red : Color.Blue);
|
|
|
|
if (PKX.getGender(CB_Form.Text) < 2) // Gendered Forms
|
|
CB_Form.SelectedIndex = PKX.getGender(Label_Gender.Text);
|
|
|
|
getQuickFiller(dragout);
|
|
}
|
|
private void clickPPUps(object sender, EventArgs e)
|
|
{
|
|
CB_PPu1.SelectedIndex = ModifierKeys != Keys.Control && Util.getIndex(CB_Move1) > 0 ? 3 : 0;
|
|
CB_PPu2.SelectedIndex = ModifierKeys != Keys.Control && Util.getIndex(CB_Move2) > 0 ? 3 : 0;
|
|
CB_PPu3.SelectedIndex = ModifierKeys != Keys.Control && Util.getIndex(CB_Move3) > 0 ? 3 : 0;
|
|
CB_PPu4.SelectedIndex = ModifierKeys != Keys.Control && Util.getIndex(CB_Move4) > 0 ? 3 : 0;
|
|
}
|
|
private void clickMarking(object sender, EventArgs e)
|
|
{
|
|
PictureBox[] pba = { PB_Mark1, PB_Mark2, PB_Mark3, PB_Mark4, PB_Mark5, PB_Mark6 };
|
|
CheckBox[] cba = { CHK_Circle, CHK_Triangle, CHK_Square, CHK_Heart, CHK_Star, CHK_Diamond };
|
|
|
|
cba[Array.IndexOf(pba, sender)].Checked ^= true;
|
|
setMarkings();
|
|
}
|
|
private void clickStatLabel(object sender, MouseEventArgs e)
|
|
{
|
|
if (!(ModifierKeys == Keys.Control || ModifierKeys == Keys.Alt))
|
|
return;
|
|
|
|
int index = Array.IndexOf(new[] { Label_HP, Label_ATK, Label_DEF, Label_SPA, Label_SPD, Label_SPE }, sender);
|
|
|
|
if (ModifierKeys == Keys.Alt) // EV
|
|
{
|
|
var arrayEV = new[] {TB_HPEV, TB_ATKEV, TB_DEFEV, TB_SPAEV, TB_SPDEV, TB_SPEEV};
|
|
arrayEV[index].Text = (e.Button == MouseButtons.Left
|
|
? Math.Min(Math.Max(510 - Util.ToInt32(TB_EVTotal.Text) + Util.ToInt32(arrayEV[index].Text), 0), 252)
|
|
: 0).ToString();
|
|
}
|
|
else
|
|
new[] {TB_HPIV, TB_ATKIV, TB_DEFIV, TB_SPAIV, TB_SPDIV, TB_SPEIV}[index].Text =
|
|
(e.Button == MouseButtons.Left ? 31 : 0).ToString();
|
|
}
|
|
private void clickIV(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys == Keys.Control)
|
|
(sender as MaskedTextBox).Text = 31.ToString();
|
|
else if (ModifierKeys == Keys.Alt)
|
|
(sender as MaskedTextBox).Text = 0.ToString();
|
|
}
|
|
private void clickEV(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys == Keys.Control) // EV
|
|
(sender as MaskedTextBox).Text = Math.Min(Math.Max(510 - Util.ToInt32(TB_EVTotal.Text) + Util.ToInt32((sender as MaskedTextBox).Text), 0), 252).ToString();
|
|
else if (ModifierKeys == Keys.Alt)
|
|
(sender as MaskedTextBox).Text = 0.ToString();
|
|
}
|
|
private void clickOT(object sender, EventArgs e)
|
|
{
|
|
if (!SAV.Exportable)
|
|
return;
|
|
|
|
// Get Save Information
|
|
TB_OT.Text = SAV.OT;
|
|
Label_OTGender.Text = gendersymbols[SAV.Gender % 2];
|
|
TB_TID.Text = SAV.TID.ToString();
|
|
TB_SID.Text = SAV.SID.ToString();
|
|
CB_GameOrigin.SelectedValue = SAV.Game;
|
|
CB_SubRegion.SelectedValue = SAV.SubRegion;
|
|
CB_Country.SelectedValue = SAV.Country;
|
|
CB_3DSReg.SelectedValue = SAV.ConsoleRegion;
|
|
CB_Language.SelectedValue = SAV.Language;
|
|
updateNickname(null, null);
|
|
}
|
|
private void clickCT(object sender, EventArgs e)
|
|
{
|
|
if (TB_OTt2.Text.Length > 0)
|
|
Label_CTGender.Text = gendersymbols[SAV.Gender % 2];
|
|
}
|
|
private void clickGT(object sender, EventArgs e)
|
|
{
|
|
if (sender == GB_OT)
|
|
{
|
|
pk6.CurrentHandler = 0;
|
|
TB_Friendship.Text = pk6.OT_Friendship.ToString();
|
|
GB_OT.BackgroundImage = mixedHighlight;
|
|
GB_nOT.BackgroundImage = null;
|
|
}
|
|
else if (TB_OTt2.Text.Length > 0)
|
|
{
|
|
pk6.CurrentHandler = 1;
|
|
TB_Friendship.Text = pk6.HT_Friendship.ToString();
|
|
GB_OT.BackgroundImage = null;
|
|
GB_nOT.BackgroundImage = mixedHighlight;
|
|
}
|
|
}
|
|
private void clickTRGender(object sender, EventArgs e)
|
|
{
|
|
Label lbl = sender as Label;
|
|
if (!string.IsNullOrWhiteSpace(lbl?.Text)) // set gender label (toggle M/F)
|
|
{
|
|
int gender = PKX.getGender(lbl.Text) ^ 1;
|
|
lbl.Text = gendersymbols[gender];
|
|
lbl.ForeColor = gender == 1 ? Color.Red : Color.Blue;
|
|
}
|
|
}
|
|
private void clickMoves(object sender, EventArgs e)
|
|
{
|
|
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo, "Copy current moves to Relearn Moves?"))
|
|
return;
|
|
|
|
CB_RelearnMove1.SelectedIndex = CB_Move1.SelectedIndex > -1 ? CB_Move1.SelectedIndex : 0;
|
|
CB_RelearnMove2.SelectedIndex = CB_Move2.SelectedIndex > -1 ? CB_Move2.SelectedIndex : 0;
|
|
CB_RelearnMove3.SelectedIndex = CB_Move3.SelectedIndex > -1 ? CB_Move3.SelectedIndex : 0;
|
|
CB_RelearnMove4.SelectedIndex = CB_Move4.SelectedIndex > -1 ? CB_Move4.SelectedIndex : 0;
|
|
}
|
|
// Prompted Updates of PKX Functions //
|
|
private bool changingFields;
|
|
private void updateEXPLevel(object sender, EventArgs e)
|
|
{
|
|
if (changingFields) return;
|
|
|
|
changingFields = true;
|
|
if (sender == TB_EXP)
|
|
{
|
|
// Change the Level
|
|
uint EXP = Util.ToUInt32(TB_EXP.Text);
|
|
int Species = Util.getIndex(CB_Species);
|
|
int Level = PKX.getLevel(Species, EXP);
|
|
if (Level == 100)
|
|
EXP = PKX.getEXP(100, Species);
|
|
|
|
TB_Level.Text = Level.ToString();
|
|
if (!MT_Level.Visible)
|
|
TB_EXP.Text = EXP.ToString();
|
|
else
|
|
MT_Level.Text = Level.ToString();
|
|
}
|
|
else
|
|
{
|
|
// Change the XP
|
|
int Level = Util.ToInt32((MT_Level.Focused ? MT_Level : TB_Level).Text);
|
|
if (Level > 100) TB_Level.Text = "100";
|
|
if (Level > byte.MaxValue) MT_Level.Text = "255";
|
|
|
|
TB_EXP.Text = PKX.getEXP(Level, Util.getIndex(CB_Species)).ToString();
|
|
}
|
|
changingFields = false;
|
|
updateStats();
|
|
updateLegality();
|
|
}
|
|
private void updateHPType(object sender, EventArgs e)
|
|
{
|
|
if (changingFields || !fieldsInitialized) return;
|
|
changingFields = true;
|
|
int[] ivs =
|
|
{
|
|
Util.ToInt32(TB_HPIV.Text), Util.ToInt32(TB_ATKIV.Text), Util.ToInt32(TB_DEFIV.Text),
|
|
Util.ToInt32(TB_SPAIV.Text), Util.ToInt32(TB_SPDIV.Text), Util.ToInt32(TB_SPEIV.Text)
|
|
};
|
|
|
|
// Change IVs to match the new Hidden Power
|
|
int[] newIVs = PKX.setHPIVs(Util.getIndex(CB_HPType), ivs);
|
|
TB_HPIV.Text = newIVs[0].ToString();
|
|
TB_ATKIV.Text = newIVs[1].ToString();
|
|
TB_DEFIV.Text = newIVs[2].ToString();
|
|
|
|
TB_SPAIV.Text = newIVs[3].ToString();
|
|
TB_SPDIV.Text = newIVs[4].ToString();
|
|
TB_SPEIV.Text = newIVs[5].ToString();
|
|
|
|
// Refresh View
|
|
changingFields = false;
|
|
updateIVs(null, null);
|
|
}
|
|
private void updateIVs(object sender, EventArgs e)
|
|
{
|
|
if (changingFields || !fieldsInitialized) return;
|
|
if (sender != null && Util.ToInt32((sender as MaskedTextBox).Text) > 31)
|
|
(sender as MaskedTextBox).Text = "31";
|
|
|
|
changingFields = true;
|
|
|
|
// Update IVs
|
|
pk6.IV_HP = Util.ToInt32(TB_HPIV.Text);
|
|
pk6.IV_ATK = Util.ToInt32(TB_ATKIV.Text);
|
|
pk6.IV_DEF = Util.ToInt32(TB_DEFIV.Text);
|
|
pk6.IV_SPE = Util.ToInt32(TB_SPEIV.Text);
|
|
pk6.IV_SPA = Util.ToInt32(TB_SPAIV.Text);
|
|
pk6.IV_SPD = Util.ToInt32(TB_SPDIV.Text);
|
|
|
|
CB_HPType.SelectedValue = pk6.HPType;
|
|
changingFields = false;
|
|
|
|
// Potential Reading
|
|
L_Potential.Text = (!unicode
|
|
? new[] {"★☆☆☆", "★★☆☆", "★★★☆", "★★★★"}
|
|
: new[] {"+", "++", "+++", "++++"}
|
|
)[pk6.PotentialRating];
|
|
|
|
TB_IVTotal.Text = pk6.IVs.Sum().ToString();
|
|
|
|
L_Characteristic.Text = characteristics[pk6.Characteristic];
|
|
updateStats();
|
|
}
|
|
private void updateEVs(object sender, EventArgs e)
|
|
{
|
|
if (sender != null)
|
|
if (Util.ToInt32((sender as MaskedTextBox).Text) > 252)
|
|
(sender as MaskedTextBox).Text = "252";
|
|
|
|
changingFields = true;
|
|
int EV_HP = Util.ToInt32(TB_HPEV.Text);
|
|
int EV_ATK = Util.ToInt32(TB_ATKEV.Text);
|
|
int EV_DEF = Util.ToInt32(TB_DEFEV.Text);
|
|
int EV_SPA = Util.ToInt32(TB_SPAEV.Text);
|
|
int EV_SPD = Util.ToInt32(TB_SPDEV.Text);
|
|
int EV_SPE = Util.ToInt32(TB_SPEEV.Text);
|
|
|
|
int evtotal = EV_HP + EV_ATK + EV_DEF + EV_SPA + EV_SPD + EV_SPE;
|
|
|
|
if (evtotal > 510) // Background turns Red
|
|
TB_EVTotal.BackColor = Color.Red;
|
|
else if (evtotal == 510) // Maximum EVs
|
|
TB_EVTotal.BackColor = Color.Honeydew;
|
|
else if (evtotal == 508) // Fishy EVs
|
|
TB_EVTotal.BackColor = Color.LightYellow;
|
|
else TB_EVTotal.BackColor = Color.WhiteSmoke;
|
|
|
|
TB_EVTotal.Text = evtotal.ToString();
|
|
changingFields = false;
|
|
updateStats();
|
|
}
|
|
private void updateRandomIVs(object sender, EventArgs e)
|
|
{
|
|
changingFields = true;
|
|
if (ModifierKeys == Keys.Control || ModifierKeys == Keys.Shift)
|
|
{
|
|
// Max IVs
|
|
TB_HPIV.Text = 31.ToString();
|
|
TB_ATKIV.Text = 31.ToString();
|
|
TB_DEFIV.Text = 31.ToString();
|
|
TB_SPAIV.Text = 31.ToString();
|
|
TB_SPDIV.Text = 31.ToString();
|
|
TB_SPEIV.Text = 31.ToString();
|
|
}
|
|
else
|
|
{
|
|
TB_HPIV.Text = (Util.rnd32() & 0x1F).ToString();
|
|
TB_ATKIV.Text = (Util.rnd32() & 0x1F).ToString();
|
|
TB_DEFIV.Text = (Util.rnd32() & 0x1F).ToString();
|
|
TB_SPAIV.Text = (Util.rnd32() & 0x1F).ToString();
|
|
TB_SPDIV.Text = (Util.rnd32() & 0x1F).ToString();
|
|
TB_SPEIV.Text = (Util.rnd32() & 0x1F).ToString();
|
|
}
|
|
changingFields = false;
|
|
updateIVs(null, null);
|
|
}
|
|
private void updateRandomEVs(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys == Keys.Control || ModifierKeys == Keys.Shift)
|
|
{
|
|
// Max IVs
|
|
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
|
|
{
|
|
byte[] evs = PKX.getRandomEVs();
|
|
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();
|
|
}
|
|
}
|
|
private void updateRandomPID(object sender, EventArgs e)
|
|
{
|
|
TB_PID.Text = PKX.getRandomPID(Util.getIndex(CB_Species), PKX.getGender(Label_Gender.Text)).ToString("X8");
|
|
getQuickFiller(dragout);
|
|
}
|
|
private void updateRandomEC(object sender, EventArgs e)
|
|
{
|
|
TB_EC.Text = Util.rnd32().ToString("X8");
|
|
}
|
|
private void updateHackedStats(object sender, EventArgs e)
|
|
{
|
|
Stat_HP.Enabled =
|
|
Stat_ATK.Enabled =
|
|
Stat_DEF.Enabled =
|
|
Stat_SPA.Enabled =
|
|
Stat_SPD.Enabled =
|
|
Stat_SPE.Enabled = CHK_HackedStats.Checked;
|
|
}
|
|
private void updateHackedStatText(object sender, EventArgs e)
|
|
{
|
|
if (!CHK_HackedStats.Checked || !(sender is TextBox))
|
|
return;
|
|
|
|
string text = ((TextBox)sender).Text;
|
|
if (string.IsNullOrWhiteSpace(text))
|
|
((TextBox)sender).Text = "0";
|
|
|
|
if (Convert.ToUInt32(text) > ushort.MaxValue)
|
|
((TextBox)sender).Text = "65535";
|
|
}
|
|
private void update255_MTB(object sender, EventArgs e)
|
|
{
|
|
if (Util.ToInt32((sender as MaskedTextBox).Text) > byte.MaxValue)
|
|
(sender as MaskedTextBox).Text = "255";
|
|
}
|
|
private void updateForm(object sender, EventArgs e)
|
|
{
|
|
updateStats();
|
|
// Repopulate Abilities if Species Form has different abilities
|
|
setAbilityList(TB_AbilityNumber, Util.getIndex(CB_Species), CB_Ability, CB_Form);
|
|
|
|
// Gender Forms
|
|
if (PKX.getGender(CB_Form.Text) < 2 && Util.getIndex(CB_Species) != 201) // don't do this for Unown
|
|
Label_Gender.Text = CB_Form.Text;
|
|
|
|
if (changingFields)
|
|
return;
|
|
changingFields = true;
|
|
MT_Form.Text = CB_Form.SelectedIndex.ToString();
|
|
changingFields = false;
|
|
}
|
|
private void updateHaXForm(object sender, EventArgs e)
|
|
{
|
|
if (changingFields)
|
|
return;
|
|
changingFields = true;
|
|
int form = Util.ToInt32(MT_Form.Text);
|
|
CB_Form.SelectedIndex = CB_Form.Items.Count > form ? form : -1;
|
|
changingFields = false;
|
|
}
|
|
private void updatePP(object sender, EventArgs e)
|
|
{
|
|
TB_PP1.Text = PKX.getMovePP(Util.getIndex(CB_Move1), CB_PPu1.SelectedIndex).ToString();
|
|
TB_PP2.Text = PKX.getMovePP(Util.getIndex(CB_Move2), CB_PPu2.SelectedIndex).ToString();
|
|
TB_PP3.Text = PKX.getMovePP(Util.getIndex(CB_Move3), CB_PPu3.SelectedIndex).ToString();
|
|
TB_PP4.Text = PKX.getMovePP(Util.getIndex(CB_Move4), CB_PPu4.SelectedIndex).ToString();
|
|
}
|
|
private void updatePKRSstrain(object sender, EventArgs e)
|
|
{
|
|
// Change the PKRS Days to the legal bounds.
|
|
int currentDuration = CB_PKRSDays.SelectedIndex;
|
|
CB_PKRSDays.Items.Clear();
|
|
foreach (int day in Enumerable.Range(0, CB_PKRSStrain.SelectedIndex % 4 + 2)) CB_PKRSDays.Items.Add(day);
|
|
|
|
// Set the days back if they're legal, else set it to 1. (0 always passes).
|
|
CB_PKRSDays.SelectedIndex = currentDuration < CB_PKRSDays.Items.Count ? currentDuration : 1;
|
|
|
|
if (CB_PKRSStrain.SelectedIndex != 0) return;
|
|
|
|
// Never Infected
|
|
CB_PKRSDays.SelectedIndex = 0;
|
|
CHK_Cured.Checked = false;
|
|
CHK_Infected.Checked = false;
|
|
}
|
|
private void updatePKRSdays(object sender, EventArgs e)
|
|
{
|
|
if (CB_PKRSDays.SelectedIndex != 0) return;
|
|
|
|
// If no days are selected
|
|
if (CB_PKRSStrain.SelectedIndex == 0)
|
|
{
|
|
// Never Infected
|
|
CHK_Cured.Checked = false;
|
|
CHK_Infected.Checked = false;
|
|
}
|
|
else CHK_Cured.Checked = true;
|
|
}
|
|
private void updatePKRSCured(object sender, EventArgs e)
|
|
{
|
|
if (!fieldsInitialized) return;
|
|
// Cured PokeRus is toggled
|
|
if (CHK_Cured.Checked)
|
|
{
|
|
// Has Had PokeRus
|
|
Label_PKRSdays.Visible = CB_PKRSDays.Visible = false;
|
|
CB_PKRSDays.SelectedIndex = 0;
|
|
|
|
Label_PKRS.Visible = CB_PKRSStrain.Visible = true;
|
|
CHK_Infected.Checked = true;
|
|
|
|
// If we're cured we have to have a strain infection.
|
|
if (CB_PKRSStrain.SelectedIndex == 0)
|
|
CB_PKRSStrain.SelectedIndex = 1;
|
|
}
|
|
else if (!CHK_Infected.Checked)
|
|
{
|
|
// Not Infected, Disable the other
|
|
Label_PKRS.Visible = CB_PKRSStrain.Visible = false;
|
|
CB_PKRSStrain.SelectedIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
// Still Infected for a duration
|
|
Label_PKRSdays.Visible = CB_PKRSDays.Visible = true;
|
|
CB_PKRSDays.SelectedValue = 1;
|
|
}
|
|
// if not cured yet, days > 0
|
|
if (!CHK_Cured.Checked && CHK_Infected.Checked && CB_PKRSDays.SelectedIndex == 0)
|
|
CB_PKRSDays.SelectedIndex++;
|
|
|
|
setMarkings();
|
|
}
|
|
private void updatePKRSInfected(object sender, EventArgs e)
|
|
{
|
|
if (!fieldsInitialized) return;
|
|
if (CHK_Cured.Checked && !CHK_Infected.Checked) { CHK_Cured.Checked = false; return; }
|
|
if (CHK_Cured.Checked) return;
|
|
Label_PKRS.Visible = CB_PKRSStrain.Visible = CHK_Infected.Checked;
|
|
if (!CHK_Infected.Checked) { CB_PKRSStrain.SelectedIndex = 0; CB_PKRSDays.SelectedIndex = 0; Label_PKRSdays.Visible = CB_PKRSDays.Visible = false; }
|
|
else if (CB_PKRSStrain.SelectedIndex == 0) { CB_PKRSStrain.SelectedIndex = 1; Label_PKRSdays.Visible = CB_PKRSDays.Visible = true; updatePKRSCured(sender, e);}
|
|
|
|
// if not cured yet, days > 0
|
|
if (CHK_Infected.Checked && CB_PKRSDays.SelectedIndex == 0) CB_PKRSDays.SelectedIndex++;
|
|
}
|
|
private void updateCountry(object sender, EventArgs e)
|
|
{
|
|
if (Util.getIndex(sender as ComboBox) > 0)
|
|
setCountrySubRegion(CB_SubRegion, "sr_" + Util.getIndex(sender as ComboBox).ToString("000"));
|
|
}
|
|
private void updateSpecies(object sender, EventArgs e)
|
|
{
|
|
// Change Species Prompted
|
|
int Species = Util.getIndex(CB_Species);
|
|
int Level = Util.ToInt32(TB_Level.Text);
|
|
if (MT_Level.Visible) Level = Util.ToInt32(MT_Level.Text);
|
|
|
|
// Get Forms for Given Species
|
|
setForms(Species, CB_Form, Label_Form);
|
|
|
|
// Recalculate EXP for Given Level
|
|
uint EXP = PKX.getEXP(Level, Species);
|
|
TB_EXP.Text = EXP.ToString();
|
|
|
|
// Check for Gender Changes
|
|
// Get Gender Threshold
|
|
int gt = PKX.Personal[Species].Gender;
|
|
int genderflag;
|
|
|
|
if (gt == 255) // Genderless
|
|
genderflag = 2;
|
|
else if (gt == 254) // Female Only
|
|
genderflag = 1;
|
|
else if (gt == 0) // Male Only
|
|
genderflag = 0;
|
|
else // get gender from old PID correlation
|
|
genderflag = (Util.getHEXval(TB_PID.Text) & 0xFF) <= gt ? 1 : 0;
|
|
|
|
int Gender = genderflag;
|
|
Label_Gender.Text = gendersymbols[Gender];
|
|
Label_Gender.ForeColor = Gender == 2 ? Label_Species.ForeColor : (Gender == 1 ? Color.Red : Color.Blue);
|
|
setAbilityList(TB_AbilityNumber, Species, CB_Ability, CB_Form);
|
|
updateForm(null, null);
|
|
|
|
// If species changes and no nickname, set the new name == speciesName.
|
|
if (!CHK_Nicknamed.Checked)
|
|
updateNickname(sender, e);
|
|
|
|
updateLegality();
|
|
}
|
|
private void updateOriginGame(object sender, EventArgs e)
|
|
{
|
|
int Version = Util.getIndex(CB_GameOrigin);
|
|
|
|
if (Version < 24 && origintrack != "Past")
|
|
{
|
|
// Load Past Gen Locations
|
|
#region B2W2 Met Locations
|
|
{
|
|
// Build up our met list
|
|
var met_list = Util.getCBList(metBW2_00000, new[] { 0 });
|
|
met_list = Util.getOffsetCBList(met_list, metBW2_60000, 60001, new[] { 60002 });
|
|
met_list = Util.getOffsetCBList(met_list, metBW2_30000, 30001, new[] { 30003 });
|
|
met_list = Util.getOffsetCBList(met_list, metBW2_00000, 00000, Legal.Met_BW2_0);
|
|
met_list = Util.getOffsetCBList(met_list, metBW2_30000, 30001, Legal.Met_BW2_3);
|
|
met_list = Util.getOffsetCBList(met_list, metBW2_40000, 40001, Legal.Met_BW2_4);
|
|
met_list = Util.getOffsetCBList(met_list, metBW2_60000, 60001, Legal.Met_BW2_6);
|
|
CB_MetLocation.DisplayMember = "Text";
|
|
CB_MetLocation.ValueMember = "Value";
|
|
CB_MetLocation.DataSource = met_list;
|
|
CB_EggLocation.DisplayMember = "Text";
|
|
CB_EggLocation.ValueMember = "Value";
|
|
CB_EggLocation.DataSource = new BindingSource(met_list, null);
|
|
CB_EggLocation.SelectedValue = 0;
|
|
CB_MetLocation.SelectedValue = Version < 20 ? 30001 : 60001;
|
|
origintrack = "Past";
|
|
}
|
|
#endregion
|
|
}
|
|
else if (Version > 23 && (origintrack != "XY"))
|
|
{
|
|
// Load X/Y/OR/AS locations
|
|
#region ORAS Met Locations
|
|
{
|
|
// Build up our met list
|
|
var met_list = Util.getCBList(metXY_00000, new[] { 0 });
|
|
met_list = Util.getOffsetCBList(met_list, metXY_60000, 60001, new[] { 60002 });
|
|
met_list = Util.getOffsetCBList(met_list, metXY_30000, 30001, new[] { 30002 });
|
|
met_list = Util.getOffsetCBList(met_list, metXY_00000, 00000, Legal.Met_XY_0);
|
|
met_list = Util.getOffsetCBList(met_list, metXY_30000, 30001, Legal.Met_XY_3);
|
|
met_list = Util.getOffsetCBList(met_list, metXY_40000, 40001, Legal.Met_XY_4);
|
|
met_list = Util.getOffsetCBList(met_list, metXY_60000, 60001, Legal.Met_XY_6);
|
|
CB_MetLocation.DisplayMember = "Text";
|
|
CB_MetLocation.ValueMember = "Value";
|
|
CB_MetLocation.DataSource = met_list;
|
|
CB_EggLocation.DisplayMember = "Text";
|
|
CB_EggLocation.ValueMember = "Value";
|
|
CB_EggLocation.DataSource = new BindingSource(met_list, null);
|
|
CB_EggLocation.SelectedValue = 0;
|
|
CB_MetLocation.SelectedValue = 0;
|
|
origintrack = "XY";
|
|
}
|
|
#endregion
|
|
}
|
|
if (Version < 0x10 && origintrack != "Gen4")
|
|
{
|
|
// Load Gen 4 egg locations if Gen 4 Origin.
|
|
#region HGSS Met Locations
|
|
var met_list = Util.getCBList(metHGSS_00000, new[] { 0 });
|
|
met_list = Util.getOffsetCBList(met_list, metHGSS_02000, 2000, new[] { 2000 });
|
|
met_list = Util.getOffsetCBList(met_list, metHGSS_02000, 2000, new[] { 2002 });
|
|
met_list = Util.getOffsetCBList(met_list, metHGSS_03000, 3000, new[] { 3001 });
|
|
met_list = Util.getOffsetCBList(met_list, metHGSS_00000, 0000, Legal.Met_HGSS_0);
|
|
met_list = Util.getOffsetCBList(met_list, metHGSS_02000, 2000, Legal.Met_HGSS_2);
|
|
met_list = Util.getOffsetCBList(met_list, metHGSS_03000, 3000, Legal.Met_HGSS_3);
|
|
|
|
CB_EggLocation.DisplayMember = "Text";
|
|
CB_EggLocation.ValueMember = "Value";
|
|
CB_EggLocation.DataSource = met_list;
|
|
CB_EggLocation.SelectedValue = 0;
|
|
origintrack = "Gen4";
|
|
#endregion
|
|
}
|
|
|
|
// Visibility logic for Gen 4 encounter type; only show for Gen 4 Pokemon.
|
|
CB_EncounterType.Visible = Label_EncounterType.Visible = !(Version > 12 || Version < 7);
|
|
// If not Gen 4, set Encounter Type to 0 after it set !visible.
|
|
if (Version > 12 || Version < 7)
|
|
CB_EncounterType.SelectedValue = 0;
|
|
|
|
setMarkings(); // Set/Remove KB marking
|
|
if (!fieldsLoaded)
|
|
return;
|
|
pk6.Version = Version;
|
|
updateLegality();
|
|
}
|
|
private void updateExtraByteValue(object sender, EventArgs e)
|
|
{
|
|
// Changed Extra Byte's Value
|
|
if (Util.ToInt32((sender as MaskedTextBox).Text) > byte.MaxValue)
|
|
(sender as MaskedTextBox).Text = "255";
|
|
|
|
int value = Util.ToInt32(TB_ExtraByte.Text);
|
|
int offset = Convert.ToInt32(CB_ExtraBytes.Text, 16);
|
|
pk6.Data[offset] = (byte)value;
|
|
}
|
|
private void updateExtraByteIndex(object sender, EventArgs e)
|
|
{
|
|
// Byte changed, need to refresh the Text box for the byte's value.
|
|
TB_ExtraByte.Text = pk6.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString();
|
|
}
|
|
private void updateNatureModification(object sender, EventArgs e)
|
|
{
|
|
if (sender != CB_Nature) return;
|
|
int nature = Util.getIndex(CB_Nature);
|
|
int incr = nature / 5;
|
|
int decr = nature % 5;
|
|
|
|
Label[] labarray = { Label_ATK, Label_DEF, Label_SPE, Label_SPA, Label_SPD };
|
|
// Reset Label Colors
|
|
foreach (Label label in labarray)
|
|
label.ForeColor = defaultControlText;
|
|
|
|
// Set Colored StatLabels only if Nature isn't Neutral
|
|
NatureTip.SetToolTip(CB_Nature,
|
|
incr != decr
|
|
? $"+{labarray[incr].Text} / -{labarray[decr].Text}".Replace(":", "")
|
|
: "-/-");
|
|
}
|
|
private void updateNickname(object sender, EventArgs e)
|
|
{
|
|
if (fieldsInitialized && ModifierKeys == Keys.Control && sender != null) // Import Showdown
|
|
{
|
|
clickShowdownImportPK6(sender, e);
|
|
return;
|
|
}
|
|
if (fieldsInitialized && ModifierKeys == Keys.Alt && sender != null) // Export Showdown
|
|
{
|
|
clickShowdownExportPK6(sender, e);
|
|
return;
|
|
}
|
|
if (!fieldsInitialized || CHK_Nicknamed.Checked) return;
|
|
|
|
// Fetch Current Species and set it as Nickname Text
|
|
int species = Util.getIndex(CB_Species);
|
|
if (species == 0 || species > 721)
|
|
TB_Nickname.Text = "";
|
|
else
|
|
{
|
|
// get language
|
|
int lang = Util.getIndex(CB_Language);
|
|
if (CHK_IsEgg.Checked) species = 0; // Set species to 0 to get the egg name.
|
|
TB_Nickname.Text = PKX.getSpeciesName(CHK_IsEgg.Checked ? 0 : species, lang);
|
|
}
|
|
}
|
|
private void updateNicknameClick(object sender, MouseEventArgs e)
|
|
{
|
|
TextBox tb = !(sender is TextBox) ? TB_Nickname : sender as TextBox;
|
|
// Special Character Form
|
|
if (ModifierKeys != Keys.Control)
|
|
return;
|
|
|
|
if (Application.OpenForms.Cast<Form>().Any(form => form.Name == typeof(f2_Text).Name))
|
|
{ Util.Alert("Window is already open."); return; }
|
|
new f2_Text(tb).Show();
|
|
}
|
|
private void updateNotOT(object sender, EventArgs e)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(TB_OTt2.Text))
|
|
{
|
|
clickGT(GB_OT, null); // Switch CT over to OT.
|
|
Label_CTGender.Text = "";
|
|
TB_Friendship.Text = pk6.OT_Friendship.ToString();
|
|
}
|
|
else if (string.IsNullOrWhiteSpace(Label_CTGender.Text))
|
|
Label_CTGender.Text = gendersymbols[0];
|
|
}
|
|
private void updateIsEgg(object sender, EventArgs e)
|
|
{
|
|
if (CHK_IsEgg.Checked)
|
|
{
|
|
CHK_Nicknamed.Checked = false;
|
|
TB_Friendship.Text = "1";
|
|
|
|
// If we are an egg, it won't have a met location.
|
|
CHK_AsEgg.Checked = true;
|
|
GB_EggConditions.Enabled = true;
|
|
|
|
CAL_MetDate.Value = new DateTime(2000, 01, 01);
|
|
CB_MetLocation.SelectedIndex = 2;
|
|
}
|
|
else // Not Egg
|
|
{
|
|
if (!CHK_Nicknamed.Checked)
|
|
updateNickname(null, null);
|
|
|
|
TB_Friendship.Text = PKX.getBaseFriendship(Util.getIndex(CB_Species)).ToString();
|
|
|
|
if (CB_EggLocation.SelectedIndex == 0)
|
|
{
|
|
CAL_EggDate.Value = new DateTime(2000, 01, 01);
|
|
CHK_AsEgg.Checked = false;
|
|
GB_EggConditions.Enabled = false;
|
|
}
|
|
}
|
|
// Display hatch counter if it is an egg, Display Friendship if it is not.
|
|
Label_HatchCounter.Visible = CHK_IsEgg.Checked;
|
|
Label_Friendship.Visible = !CHK_IsEgg.Checked;
|
|
|
|
// Update image to (not) show egg.
|
|
if (!fieldsInitialized) return;
|
|
updateNickname(null, null);
|
|
getQuickFiller(dragout);
|
|
}
|
|
private void updateMetAsEgg(object sender, EventArgs e)
|
|
{
|
|
GB_EggConditions.Enabled = CHK_AsEgg.Checked;
|
|
if (CHK_AsEgg.Checked) return;
|
|
// Remove egg met data
|
|
CHK_IsEgg.Checked = false;
|
|
CAL_EggDate.Value = new DateTime(2000, 01, 01);
|
|
CB_EggLocation.SelectedValue = 0;
|
|
|
|
updateLegality();
|
|
}
|
|
private void updateShinyPID(object sender, EventArgs e)
|
|
{
|
|
uint PID = Util.getHEXval(TB_PID.Text);
|
|
uint UID = PID >> 16;
|
|
uint LID = PID & 0xFFFF;
|
|
uint PSV = UID ^ LID;
|
|
uint TID = Util.ToUInt32(TB_TID.Text);
|
|
uint SID = Util.ToUInt32(TB_SID.Text);
|
|
uint TSV = TID ^ SID;
|
|
uint XOR = TSV ^ PSV;
|
|
|
|
// Preserve Gen5 Origin Ability bit just in case
|
|
XOR &= 0xFFFE; XOR |= UID & 1;
|
|
|
|
// New XOR should be 0 or 1.
|
|
if (XOR > 16)
|
|
TB_PID.Text = (((UID ^ XOR) << 16) + LID).ToString("X8");
|
|
|
|
setIsShiny();
|
|
getQuickFiller(dragout);
|
|
}
|
|
private void updateTSV(object sender, EventArgs e)
|
|
{
|
|
ushort TID = (ushort)Util.ToUInt32(TB_TID.Text);
|
|
ushort SID = (ushort)Util.ToUInt32(TB_SID.Text);
|
|
uint TSV = PKX.getTSV(TID, SID);
|
|
Tip1.SetToolTip(TB_TID, "TSV: " + TSV.ToString("0000"));
|
|
Tip2.SetToolTip(TB_SID, "TSV: " + TSV.ToString("0000"));
|
|
|
|
uint PSV = PKX.getPSV(Util.getHEXval(TB_PID.Text));
|
|
Tip3.SetToolTip(TB_PID, "PSV: " + PSV.ToString("0000"));
|
|
}
|
|
private void update_ID(object sender, EventArgs e)
|
|
{
|
|
// Trim out nonhex characters
|
|
TB_PID.Text = Util.getHEXval(TB_PID.Text).ToString("X8");
|
|
TB_EC.Text = Util.getHEXval(TB_EC.Text).ToString("X8");
|
|
|
|
// Max TID/SID is 65535
|
|
if (Util.ToUInt32(TB_TID.Text) > ushort.MaxValue) TB_TID.Text = "65535";
|
|
if (Util.ToUInt32(TB_SID.Text) > ushort.MaxValue) TB_SID.Text = "65535";
|
|
|
|
setIsShiny();
|
|
getQuickFiller(dragout);
|
|
updateIVs(null, null); // If the PID is changed, PID%6 (Characteristic) might be changed.
|
|
TB_PID.Select(60, 0); // position cursor at end of field
|
|
}
|
|
|
|
private void validateComboBox(object sender)
|
|
{
|
|
if (!(sender is ComboBox))
|
|
return;
|
|
|
|
ComboBox cb = (ComboBox)sender;
|
|
cb.SelectionLength = 0;
|
|
if (cb.Text == "")
|
|
{ cb.SelectedIndex = 0; return; }
|
|
cb.BackColor = cb.SelectedValue == null ? Color.DarkSalmon : defaultControlWhite;
|
|
}
|
|
private void validateComboBox(object sender, EventArgs e)
|
|
{
|
|
if (!(sender is ComboBox))
|
|
return;
|
|
|
|
validateComboBox(sender);
|
|
|
|
if (fieldsLoaded)
|
|
getQuickFiller(dragout);
|
|
}
|
|
private void validateComboBox2(object sender, EventArgs e)
|
|
{
|
|
validateComboBox(sender, e);
|
|
if (sender == CB_Ability)
|
|
TB_AbilityNumber.Text = (1 << CB_Ability.SelectedIndex).ToString();
|
|
updateNatureModification(sender, null);
|
|
updateIVs(null, null); // updating Nature will trigger stats to update as well
|
|
}
|
|
private void validateMove(object sender, EventArgs e)
|
|
{
|
|
if (!fieldsLoaded)
|
|
return;
|
|
|
|
validateComboBox(sender);
|
|
|
|
int[] relearnMoves =
|
|
{
|
|
Util.getIndex(CB_RelearnMove1), Util.getIndex(CB_RelearnMove2),
|
|
Util.getIndex(CB_RelearnMove3), Util.getIndex(CB_RelearnMove4)
|
|
};
|
|
if (new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4 }.Contains(sender)) // Move
|
|
{
|
|
updatePP(sender, e);
|
|
int[] moves =
|
|
{
|
|
Util.getIndex(CB_Move1), Util.getIndex(CB_Move2),
|
|
Util.getIndex(CB_Move3), Util.getIndex(CB_Move4)
|
|
};
|
|
PictureBox[] moveCB = {PB_WarnMove1, PB_WarnMove2, PB_WarnMove3, PB_WarnMove4};
|
|
bool[] legal = Legality.getMoveValidity(moves, relearnMoves);
|
|
for (int i = 0; i < 4; i++)
|
|
moveCB[i].Visible = !legal[i];
|
|
}
|
|
else
|
|
{
|
|
PictureBox[] moveCB = { PB_WarnRelearn1, PB_WarnRelearn2, PB_WarnRelearn3, PB_WarnRelearn4 };
|
|
bool[] legal = Legality.getRelearnValidity(relearnMoves);
|
|
for (int i = 0; i < 4; i++)
|
|
moveCB[i].Visible = !legal[i];
|
|
|
|
// Refresh move states
|
|
foreach (ComboBox c in new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4 })
|
|
validateMove(c, e);
|
|
}
|
|
}
|
|
private void validateLocation(object sender, EventArgs e)
|
|
{
|
|
validateComboBox(sender);
|
|
if (!fieldsLoaded)
|
|
return;
|
|
|
|
pk6.Met_Location = Util.getIndex(CB_MetLocation);
|
|
pk6.Egg_Location = Util.getIndex(CB_EggLocation);
|
|
updateLegality();
|
|
}
|
|
private void removedropCB(object sender, KeyEventArgs e)
|
|
{
|
|
((ComboBox)sender).DroppedDown = false;
|
|
}
|
|
private void updateLegality()
|
|
{
|
|
if (!fieldsLoaded)
|
|
return;
|
|
|
|
Legality = new LegalityAnalysis(pk6);
|
|
|
|
// refresh
|
|
foreach (ComboBox cb in new[] {CB_RelearnMove1, CB_RelearnMove2, CB_RelearnMove3, CB_RelearnMove4})
|
|
validateMove(cb, null);
|
|
}
|
|
private void updateStats()
|
|
{
|
|
// Gather the needed information.
|
|
int species = Util.getIndex(CB_Species);
|
|
int level = Util.ToInt32(MT_Level.Enabled ? MT_Level.Text : TB_Level.Text);
|
|
if (level == 0) level = 1;
|
|
int form = CB_Form.SelectedIndex;
|
|
int HP_IV = Util.ToInt32(TB_HPIV.Text);
|
|
int ATK_IV = Util.ToInt32(TB_ATKIV.Text);
|
|
int DEF_IV = Util.ToInt32(TB_DEFIV.Text);
|
|
int SPA_IV = Util.ToInt32(TB_SPAIV.Text);
|
|
int SPD_IV = Util.ToInt32(TB_SPDIV.Text);
|
|
int SPE_IV = Util.ToInt32(TB_SPEIV.Text);
|
|
|
|
int HP_EV = Util.ToInt32(TB_HPEV.Text);
|
|
int ATK_EV = Util.ToInt32(TB_ATKEV.Text);
|
|
int DEF_EV = Util.ToInt32(TB_DEFEV.Text);
|
|
int SPA_EV = Util.ToInt32(TB_SPAEV.Text);
|
|
int SPD_EV = Util.ToInt32(TB_SPDEV.Text);
|
|
int SPE_EV = Util.ToInt32(TB_SPEEV.Text);
|
|
|
|
int nature = Util.getIndex(CB_Nature);
|
|
|
|
// Generate the stats.
|
|
ushort[] stats = PKX.getStats(species, level, nature, form,
|
|
HP_EV, ATK_EV, DEF_EV, SPA_EV, SPD_EV, SPE_EV,
|
|
HP_IV, ATK_IV, DEF_IV, SPA_IV, SPD_IV, SPE_IV);
|
|
|
|
Stat_HP.Text = stats[0].ToString();
|
|
Stat_ATK.Text = stats[1].ToString();
|
|
Stat_DEF.Text = stats[2].ToString();
|
|
Stat_SPA.Text = stats[4].ToString();
|
|
Stat_SPD.Text = stats[5].ToString();
|
|
Stat_SPE.Text = stats[3].ToString();
|
|
|
|
// Recolor the Stat Labels based on boosted stats.
|
|
{
|
|
int incr = nature / 5;
|
|
int decr = nature % 5;
|
|
|
|
Label[] labarray = { Label_ATK, Label_DEF, Label_SPE, Label_SPA, Label_SPD };
|
|
// Reset Label Colors
|
|
foreach (Label label in labarray)
|
|
label.ForeColor = defaultControlText;
|
|
|
|
// Set Colored StatLabels only if Nature isn't Neutral
|
|
if (incr == decr) return;
|
|
labarray[incr].ForeColor = Color.Red;
|
|
labarray[decr].ForeColor = Color.Blue;
|
|
}
|
|
}
|
|
private void updateUnicode()
|
|
{
|
|
if (!unicode)
|
|
{
|
|
gendersymbols = new[] { "M", "F", "-" };
|
|
BTN_Shinytize.Text = "*";
|
|
TB_Nickname.Font = TB_OT.Font = TB_OTt2.Font = Label_TID.Font;
|
|
}
|
|
else
|
|
{
|
|
gendersymbols = new[] { "♂", "♀", "-" };
|
|
BTN_Shinytize.Text = "☆";
|
|
TB_Nickname.Font = TB_OT.Font = TB_OTt2.Font = PKX.getPKXFont(11);
|
|
}
|
|
// Switch active gender labels to new if they are active.
|
|
if (PKX.getGender(Label_Gender.Text) < 2)
|
|
Label_Gender.Text = gendersymbols[PKX.getGender(Label_Gender.Text)];
|
|
if (PKX.getGender(Label_OTGender.Text) < 2)
|
|
Label_OTGender.Text = gendersymbols[PKX.getGender(Label_OTGender.Text)];
|
|
if (PKX.getGender(Label_CTGender.Text) < 2)
|
|
Label_CTGender.Text = gendersymbols[PKX.getGender(Label_CTGender.Text)];
|
|
}
|
|
// Secondary Windows for Ribbons/Amie/Memories
|
|
private void openRibbons(object sender, EventArgs e)
|
|
{
|
|
new RibbMedal().ShowDialog();
|
|
}
|
|
private void openHistory(object sender, EventArgs e)
|
|
{
|
|
// Write back current values
|
|
pk6.Version = Util.getIndex(CB_GameOrigin);
|
|
pk6.HT_Name = TB_OTt2.Text;
|
|
pk6.OT_Name = TB_OT.Text;
|
|
pk6.IsEgg = CHK_IsEgg.Checked;
|
|
if (pk6.CurrentHandler == 0)
|
|
pk6.OT_Friendship = Util.ToInt32(TB_Friendship.Text);
|
|
else // 1
|
|
pk6.HT_Friendship = Util.ToInt32(TB_Friendship.Text);
|
|
new MemoryAmie().ShowDialog();
|
|
TB_Friendship.Text = (pk6.CurrentHandler == 0 ? pk6.OT_Friendship : pk6.HT_Friendship).ToString();
|
|
}
|
|
// Open/Save Array Manipulation //
|
|
public bool verifiedPKX()
|
|
{
|
|
if (ModifierKeys == (Keys.Control | Keys.Shift | Keys.Alt))
|
|
return true; // Override
|
|
// Make sure the PKX Fields are filled out properly (color check)
|
|
#region ComboBoxes to verify they are set.
|
|
ComboBox[] cba = {
|
|
CB_Species, CB_Nature, CB_HeldItem, CB_Ability, // Main Tab
|
|
CB_MetLocation, CB_EggLocation, CB_Ball, // Met Tab
|
|
CB_Move1, CB_Move2, CB_Move3, CB_Move4, // Moves
|
|
CB_RelearnMove1, CB_RelearnMove2, CB_RelearnMove3, CB_RelearnMove4 // Moves
|
|
};
|
|
for (int i = 0; i < cba.Length; i++)
|
|
{
|
|
int back = cba[i].BackColor.ToArgb();
|
|
if (back == SystemColors.Control.ToArgb() || back == 0 ||
|
|
!(back != -1 & back != defaultControlWhite.ToArgb())) continue;
|
|
if (i < 6) // Main Tab
|
|
tabMain.SelectedIndex = 0;
|
|
else if (i < 9) // Met Tab
|
|
tabMain.SelectedIndex = 1;
|
|
else // Moves
|
|
tabMain.SelectedIndex = 3;
|
|
goto invalid;
|
|
}
|
|
#endregion
|
|
// Further logic checking
|
|
if (Convert.ToUInt32(TB_EVTotal.Text) > 510 && !CHK_HackedStats.Checked)
|
|
{ tabMain.SelectedIndex = 2; goto invalid; }
|
|
// If no errors detected...
|
|
if (Util.getIndex(CB_Species) != 0) return true;
|
|
// Else
|
|
tabMain.SelectedIndex = 0;
|
|
|
|
// else...
|
|
invalid:
|
|
{ SystemSounds.Exclamation.Play(); return false; }
|
|
}
|
|
public PK6 preparepkx(bool click = true)
|
|
{
|
|
if (click)
|
|
tabMain.Select(); // hack to make sure comboboxes are set (users scrolling through and immediately setting causes this)
|
|
|
|
// Repopulate PK6 with Edited Stuff
|
|
if (Util.getIndex(CB_GameOrigin) < 24)
|
|
{
|
|
uint EC = Util.getHEXval(TB_EC.Text);
|
|
uint PID = Util.getHEXval(TB_PID.Text);
|
|
uint SID = Util.ToUInt32(TB_TID.Text);
|
|
uint TID = Util.ToUInt32(TB_TID.Text);
|
|
uint LID = PID & 0xFFFF;
|
|
uint HID = PID >> 16;
|
|
uint XOR = TID ^ LID ^ SID ^ HID;
|
|
|
|
// Ensure we don't have a shiny.
|
|
if (XOR >> 3 == 1) // Illegal, fix. (not 16<XOR>=8)
|
|
{
|
|
// Keep as shiny, so we have to mod the PID
|
|
PID ^= XOR;
|
|
TB_PID.Text = PID.ToString("X8");
|
|
TB_EC.Text = PID.ToString("X8");
|
|
}
|
|
else if ((XOR ^ 0x8000) >> 3 == 1 && PID != EC)
|
|
TB_EC.Text = (PID ^ 0x80000000).ToString("X8");
|
|
else // Not Illegal, no fix.
|
|
TB_EC.Text = PID.ToString("X8");
|
|
}
|
|
|
|
pk6.EncryptionConstant = Util.getHEXval(TB_EC.Text);
|
|
pk6.Checksum = 0; // 0 CHK for now
|
|
|
|
// Block A
|
|
pk6.Species = Util.getIndex(CB_Species);
|
|
pk6.HeldItem = Util.getIndex(CB_HeldItem);
|
|
pk6.TID = Util.ToInt32(TB_TID.Text);
|
|
pk6.SID = Util.ToInt32(TB_SID.Text);
|
|
pk6.EXP = Util.ToUInt32(TB_EXP.Text);
|
|
pk6.Ability = (byte)Array.IndexOf(abilitylist, CB_Ability.Text.Remove(CB_Ability.Text.Length - 4));
|
|
pk6.AbilityNumber = Util.ToInt32(TB_AbilityNumber.Text); // Number
|
|
// pkx[0x16], pkx[0x17] are handled by the Medals UI (Hits & Training Bag)
|
|
pk6.PID = Util.getHEXval(TB_PID.Text);
|
|
pk6.Nature = (byte)Util.getIndex(CB_Nature);
|
|
pk6.FatefulEncounter = CHK_Fateful.Checked;
|
|
pk6.Gender = PKX.getGender(Label_Gender.Text);
|
|
pk6.AltForm = (MT_Form.Enabled ? Convert.ToInt32(MT_Form.Text) : CB_Form.SelectedIndex) & 0x1F; // Form
|
|
pk6.EV_HP = Util.ToInt32(TB_HPEV.Text); // EVs
|
|
pk6.EV_ATK = Util.ToInt32(TB_ATKEV.Text);
|
|
pk6.EV_DEF = Util.ToInt32(TB_DEFEV.Text);
|
|
pk6.EV_SPE = Util.ToInt32(TB_SPEEV.Text);
|
|
pk6.EV_SPA = Util.ToInt32(TB_SPAEV.Text);
|
|
pk6.EV_SPD = Util.ToInt32(TB_SPDEV.Text);
|
|
|
|
pk6.CNT_Cool = Util.ToInt32(TB_Cool.Text); // CNT
|
|
pk6.CNT_Beauty = Util.ToInt32(TB_Beauty.Text);
|
|
pk6.CNT_Cute = Util.ToInt32(TB_Cute.Text);
|
|
pk6.CNT_Smart = Util.ToInt32(TB_Smart.Text);
|
|
pk6.CNT_Tough = Util.ToInt32(TB_Tough.Text);
|
|
pk6.CNT_Sheen = Util.ToInt32(TB_Sheen.Text);
|
|
|
|
pk6.Circle = CHK_Circle.Checked;
|
|
pk6.Triangle = CHK_Triangle.Checked;
|
|
pk6.Square = CHK_Square.Checked;
|
|
pk6.Heart = CHK_Heart.Checked;
|
|
pk6.Star = CHK_Star.Checked;
|
|
pk6.Diamond = CHK_Diamond.Checked;
|
|
|
|
pk6.PKRS_Days = CB_PKRSDays.SelectedIndex;
|
|
pk6.PKRS_Strain = CB_PKRSStrain.SelectedIndex;
|
|
// Already in buff (then transferred to new pkx)
|
|
// 0x2C, 0x2D, 0x2E, 0x2F
|
|
// 0x30, 0x31, 0x32, 0x33
|
|
// 0x34, 0x35, 0x36, 0x37
|
|
// 0x38, 0x39
|
|
|
|
// Unused
|
|
// 0x3A, 0x3B
|
|
// 0x3C, 0x3D, 0x3E, 0x3F
|
|
|
|
// Block B
|
|
// Convert Nickname field back to bytes
|
|
pk6.Nickname = TB_Nickname.Text;
|
|
pk6.Move1 = Util.getIndex(CB_Move1);
|
|
pk6.Move2 = Util.getIndex(CB_Move2);
|
|
pk6.Move3 = Util.getIndex(CB_Move3);
|
|
pk6.Move4 = Util.getIndex(CB_Move4);
|
|
pk6.Move1_PP = Util.getIndex(CB_Move1) > 0 ? Util.ToInt32(TB_PP1.Text) : 0;
|
|
pk6.Move2_PP = Util.getIndex(CB_Move2) > 0 ? Util.ToInt32(TB_PP2.Text) : 0;
|
|
pk6.Move3_PP = Util.getIndex(CB_Move3) > 0 ? Util.ToInt32(TB_PP3.Text) : 0;
|
|
pk6.Move4_PP = Util.getIndex(CB_Move4) > 0 ? Util.ToInt32(TB_PP4.Text) : 0;
|
|
pk6.Move1_PPUps = Util.getIndex(CB_Move1) > 0 ? CB_PPu1.SelectedIndex : 0;
|
|
pk6.Move2_PPUps = Util.getIndex(CB_Move2) > 0 ? CB_PPu2.SelectedIndex : 0;
|
|
pk6.Move3_PPUps = Util.getIndex(CB_Move3) > 0 ? CB_PPu3.SelectedIndex : 0;
|
|
pk6.Move4_PPUps = Util.getIndex(CB_Move4) > 0 ? CB_PPu4.SelectedIndex : 0;
|
|
pk6.RelearnMove1 = Util.getIndex(CB_RelearnMove1);
|
|
pk6.RelearnMove2 = Util.getIndex(CB_RelearnMove2);
|
|
pk6.RelearnMove3 = Util.getIndex(CB_RelearnMove3);
|
|
pk6.RelearnMove4 = Util.getIndex(CB_RelearnMove4);
|
|
// 0x72 - Ribbon editor sets this flag (Secret Super Training)
|
|
// 0x73
|
|
pk6.IV_HP = Util.ToInt32(TB_HPIV.Text);
|
|
pk6.IV_ATK = Util.ToInt32(TB_ATKIV.Text);
|
|
pk6.IV_DEF = Util.ToInt32(TB_DEFIV.Text);
|
|
pk6.IV_SPE = Util.ToInt32(TB_SPEIV.Text);
|
|
pk6.IV_SPA = Util.ToInt32(TB_SPAIV.Text);
|
|
pk6.IV_SPD = Util.ToInt32(TB_SPDIV.Text);
|
|
pk6.IsEgg = CHK_IsEgg.Checked;
|
|
pk6.IsNicknamed = CHK_Nicknamed.Checked;
|
|
|
|
// Block C
|
|
// Convert Latest OT field back to bytes
|
|
pk6.HT_Name = TB_OTt2.Text;
|
|
|
|
// 0x90-0xAF
|
|
pk6.HT_Gender = PKX.getGender(Label_CTGender.Text);
|
|
// Plus more, set by MemoryAmie (already in buff)
|
|
|
|
// Block D
|
|
// Convert OT field back to bytes
|
|
pk6.OT_Name = TB_OT.Text;
|
|
|
|
pk6.CurrentFriendship = Util.ToInt32(TB_Friendship.Text);
|
|
|
|
int egg_year = 2000; // Default Dates
|
|
int egg_month = 0;
|
|
int egg_day = 0;
|
|
int egg_location = 0;
|
|
if (CHK_AsEgg.Checked) // If encountered as an egg, load the Egg Met data from fields.
|
|
{
|
|
egg_year = CAL_EggDate.Value.Year;
|
|
egg_month = CAL_EggDate.Value.Month;
|
|
egg_day = CAL_EggDate.Value.Day;
|
|
egg_location = Util.getIndex(CB_EggLocation);
|
|
}
|
|
// Egg Met Data
|
|
pk6.Egg_Year = egg_year - 2000;
|
|
pk6.Egg_Month = egg_month;
|
|
pk6.Egg_Day = egg_day;
|
|
pk6.Egg_Location = egg_location;
|
|
// Met Data
|
|
pk6.Met_Year = CAL_MetDate.Value.Year - 2000;
|
|
pk6.Met_Month = CAL_MetDate.Value.Month;
|
|
pk6.Met_Day = CAL_MetDate.Value.Day;
|
|
pk6.Met_Location = Util.getIndex(CB_MetLocation);
|
|
|
|
if (pk6.IsEgg && pk6.Met_Location == 0) // If still an egg, it has no hatch location/date. Zero it!
|
|
pk6.Met_Year = pk6.Met_Month = pk6.Met_Day = 0;
|
|
|
|
// 0xD7 Unknown
|
|
|
|
pk6.Ball = Util.getIndex(CB_Ball);
|
|
pk6.Met_Level = Util.ToInt32(TB_MetLevel.Text);
|
|
pk6.OT_Gender = PKX.getGender(Label_OTGender.Text);
|
|
pk6.EncounterType = Util.getIndex(CB_EncounterType);
|
|
pk6.Version = Util.getIndex(CB_GameOrigin);
|
|
pk6.Country = Util.getIndex(CB_Country);
|
|
pk6.Region = Util.getIndex(CB_SubRegion);
|
|
pk6.ConsoleRegion = Util.getIndex(CB_3DSReg);
|
|
pk6.Language = Util.getIndex(CB_Language);
|
|
// 0xE4-0xE7
|
|
|
|
// Toss in Party Stats
|
|
Array.Resize(ref pk6.Data, PK6.SIZE_PARTY);
|
|
pk6.Stat_Level = Util.ToInt32(TB_Level.Text);
|
|
pk6.Stat_HPCurrent = Util.ToInt32(Stat_HP.Text);
|
|
pk6.Stat_HPMax = Util.ToInt32(Stat_HP.Text);
|
|
pk6.Stat_ATK = Util.ToInt32(Stat_ATK.Text);
|
|
pk6.Stat_DEF = Util.ToInt32(Stat_DEF.Text);
|
|
pk6.Stat_SPE = Util.ToInt32(Stat_SPE.Text);
|
|
pk6.Stat_SPA = Util.ToInt32(Stat_SPA.Text);
|
|
pk6.Stat_SPD = Util.ToInt32(Stat_SPD.Text);
|
|
|
|
// Unneeded Party Stats (Status, Flags, Unused)
|
|
pk6.Data[0xE8] = pk6.Data[0xE9] = pk6.Data[0xEA] = pk6.Data[0xEB] =
|
|
pk6.Data[0xED] = pk6.Data[0xEE] = pk6.Data[0xEF] =
|
|
pk6.Data[0xFE] = pk6.Data[0xFF] = pk6.Data[0x100] =
|
|
pk6.Data[0x101] = pk6.Data[0x102] = pk6.Data[0x103] = 0;
|
|
|
|
// Hax Illegality
|
|
if (HaX)
|
|
{
|
|
pk6.Ability = (byte)Util.getIndex(DEV_Ability);
|
|
pk6.Stat_Level = (byte)Math.Min(Convert.ToInt32(MT_Level.Text), byte.MaxValue);
|
|
}
|
|
|
|
// Fix Moves if a slot is empty
|
|
pk6.FixMoves();
|
|
pk6.FixRelearn();
|
|
|
|
// Fix Handler (Memories & OT) -- no foreign memories for Pokemon without a foreign trainer (none for eggs)
|
|
if (Menu_ModifyPK6.Checked)
|
|
pk6.FixMemories();
|
|
|
|
// PKX is now filled
|
|
pk6.RefreshChecksum();
|
|
return pk6;
|
|
}
|
|
// Drag & Drop Events
|
|
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);
|
|
openQuick(files[0]);
|
|
}
|
|
// Decrypted Export
|
|
private void dragout_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
if (!verifiedPKX()) return;
|
|
{
|
|
// Create Temp File to Drag
|
|
Cursor.Current = Cursors.Hand;
|
|
|
|
// Make a new file name
|
|
PK6 pkx = preparepkx();
|
|
string filename = Path.GetFileNameWithoutExtension(pkx.FileName) + (e.Button == MouseButtons.Right ? ".ek6" : ".pk6");
|
|
byte[] dragdata = e.Button == MouseButtons.Right ? pkx.EncryptedBoxData : pkx.DecryptedBoxData;
|
|
// Make file
|
|
string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
|
|
try
|
|
{
|
|
File.WriteAllBytes(newfile, dragdata);
|
|
DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Move);
|
|
}
|
|
catch (Exception x)
|
|
{ Util.Error("Drag & Drop Error", x.ToString()); }
|
|
File.Delete(newfile);
|
|
}
|
|
}
|
|
private void dragout_DragOver(object sender, DragEventArgs e)
|
|
{
|
|
e.Effect = DragDropEffects.Move;
|
|
}
|
|
// Dragout Display
|
|
private void dragoutHover(object sender, EventArgs e)
|
|
{
|
|
dragout.BackgroundImage = Util.getIndex(CB_Species) > 0 ? Properties.Resources.slotSet : Properties.Resources.slotDel;
|
|
}
|
|
private void dragoutLeave(object sender, EventArgs e)
|
|
{
|
|
dragout.BackgroundImage = Properties.Resources.slotTrans;
|
|
}
|
|
private void dragoutDrop(object sender, DragEventArgs e)
|
|
{
|
|
openQuick(((string[])e.Data.GetData(DataFormats.FileDrop))[0]);
|
|
}
|
|
#endregion
|
|
|
|
#region //// SAVE FILE FUNCTIONS ////
|
|
private void clickVerifyCHK(object sender, EventArgs e)
|
|
{
|
|
if (SAV.Edited) { Util.Alert("Save has been edited. Cannot integrity check."); return; }
|
|
|
|
if (SAV.ChecksumsValid) { Util.Alert("Checksums are valid."); return; }
|
|
if (DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Export Checksum Info to Clipboard?"))
|
|
Clipboard.SetText(SAV.ChecksumInfo);
|
|
}
|
|
private void clickExportSAVBAK(object sender, EventArgs e)
|
|
{
|
|
SaveFileDialog sfd = new SaveFileDialog
|
|
{ FileName = Util.CleanFileName(SAV.BAKName) };
|
|
if (sfd.ShowDialog() != DialogResult.OK)
|
|
return;
|
|
|
|
string path = sfd.FileName;
|
|
File.WriteAllBytes(path, SAV.BAK);
|
|
Util.Alert("Saved Backup of current SAV to:", path);
|
|
|
|
if (Directory.Exists(BackupPath)) return;
|
|
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo,
|
|
$"PKHeX can perform automatic backups if you create a folder with the name \"{BackupPath}\" in the same folder as PKHeX's executable.",
|
|
"Would you like to create the backup folder now and save backup of current save?")) return;
|
|
|
|
try { Directory.CreateDirectory(BackupPath); Util.Alert("Backup folder created!",
|
|
$"If you wish to no longer automatically back up save files, delete the \"{BackupPath}\" folder."); }
|
|
catch { Util.Error($"Unable to create backup folder @ {BackupPath}"); }
|
|
}
|
|
private void clickExportSAV(object sender, EventArgs e)
|
|
{
|
|
if (!Menu_ExportSAV.Enabled)
|
|
return;
|
|
|
|
// Chunk Error Checking
|
|
string err = SAV.checkChunkFF();
|
|
if (err.Length > 0 && Util.Prompt(MessageBoxButtons.YesNo, err, "Continue saving?") != DialogResult.Yes)
|
|
return;
|
|
|
|
SaveFileDialog main = new SaveFileDialog
|
|
{
|
|
Filter = "Main SAV|*.*",
|
|
FileName = SAV.FileName,
|
|
RestoreDirectory = true
|
|
};
|
|
if (Directory.Exists(SAV.FilePath))
|
|
main.InitialDirectory = SAV.FilePath;
|
|
|
|
// Export
|
|
if (main.ShowDialog() != DialogResult.OK) return;
|
|
|
|
if (SAV.Box > -1)
|
|
SAV.CurrentBox = CB_BoxSelect.SelectedIndex;
|
|
File.WriteAllBytes(main.FileName, SAV.Write());
|
|
Util.Alert("SAV exported to:", main.FileName);
|
|
}
|
|
|
|
// Box/SAV Functions //
|
|
private void clickBoxRight(object sender, EventArgs e)
|
|
{
|
|
CB_BoxSelect.SelectedIndex = (CB_BoxSelect.SelectedIndex + 1) % 31;
|
|
}
|
|
private void clickBoxLeft(object sender, EventArgs e)
|
|
{
|
|
CB_BoxSelect.SelectedIndex = (CB_BoxSelect.SelectedIndex + 30) % 31;
|
|
}
|
|
private void clickBoxSort(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys != Keys.Control || tabBoxMulti.SelectedIndex != 0)
|
|
return;
|
|
|
|
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo, "Sort Boxes?"))
|
|
return;
|
|
|
|
SAV.sortBoxes();
|
|
setPKXBoxes();
|
|
CB_BoxSelect.SelectedIndex = 0;
|
|
Util.Alert("Boxes sorted!");
|
|
}
|
|
private void clickSlot(object sender, EventArgs e)
|
|
{
|
|
switch (ModifierKeys)
|
|
{
|
|
case Keys.Control | Keys.Alt: clickClone(sender, e); break;
|
|
case Keys.Control: clickView(sender, e); break;
|
|
case Keys.Shift: clickSet(sender, e); break;
|
|
case Keys.Alt: clickDelete(sender, e); break;
|
|
}
|
|
}
|
|
private void clickView(object sender, EventArgs e)
|
|
{
|
|
int slot = getSlot(sender);
|
|
int offset = getPKXOffset(slot);
|
|
|
|
if (SlotPictureBoxes[slot].Image == null)
|
|
{ SystemSounds.Exclamation.Play(); return; }
|
|
|
|
// Load the PKX file
|
|
PK6 pk = SAV.getPK6Stored(offset);
|
|
if (pk.Sanity == 0 && pk.Species != 0)
|
|
{
|
|
try { populateFields(pk); }
|
|
catch // If it fails, try XORing encrypted zeroes
|
|
{
|
|
try
|
|
{
|
|
byte[] blank = (byte[])blankEK6.Clone();
|
|
|
|
for (int i = 0; i < PK6.SIZE_STORED; i++)
|
|
blank[i] = (byte)(pk6.Data[i] ^ blank[i]);
|
|
|
|
populateFields(new PK6(blank));
|
|
}
|
|
catch // Still fails, just let the original errors occur.
|
|
{ populateFields(pk6); }
|
|
}
|
|
// Visual to display what slot is currently loaded.
|
|
getSlotColor(slot, Properties.Resources.slotView);
|
|
}
|
|
else
|
|
SystemSounds.Exclamation.Play();
|
|
}
|
|
private void clickSet(object sender, EventArgs e)
|
|
{
|
|
if (!verifiedPKX()) return;
|
|
int slot = getSlot(sender);
|
|
if (slot == 30 && (CB_Species.SelectedIndex == 0 || CHK_IsEgg.Checked))
|
|
{ Util.Alert("Can't have empty/egg first slot."); return; }
|
|
|
|
int offset = getPKXOffset(slot);
|
|
PK6 pk = preparepkx();
|
|
if (!SAV.ORAS)
|
|
{
|
|
// User Protection
|
|
string err = "";
|
|
if (pk.Moves.Any(m => m > 617))
|
|
err = "Move does not exist in X/Y.";
|
|
else if (pk.Ability > 188)
|
|
err = "Ability does not exist in X/Y.";
|
|
else if (pk.HeldItem > 717)
|
|
err = "Item does not exist in X/Y.";
|
|
|
|
if (err != "" && Util.Prompt(MessageBoxButtons.YesNo, err, "Continue?") != DialogResult.Yes)
|
|
return;
|
|
}
|
|
if (slot >= 30 && slot < 36) // Party
|
|
SAV.setPK6Party(pk, offset);
|
|
else if (slot < 30 || (slot >= 36 && slot < 42 && DEV_Ability.Enabled))
|
|
SAV.setPK6Stored(pk, offset);
|
|
else return;
|
|
|
|
if (slot >= 30 && slot < 36)
|
|
setParty();
|
|
else
|
|
getQuickFiller(SlotPictureBoxes[slot], pk);
|
|
|
|
getSlotColor(slot, Properties.Resources.slotSet);
|
|
}
|
|
private void clickDelete(object sender, EventArgs e)
|
|
{
|
|
int slot = getSlot(sender);
|
|
if (slot == 30 && SAV.PartyCount == 1 && !DEV_Ability.Enabled) { Util.Alert("Can't delete first slot."); return; }
|
|
|
|
if (slot >= 30 && slot < 36) // Party
|
|
{ SAV.setData(blankEK6, getPKXOffset(slot)); setParty(); return; }
|
|
if (slot < 30 || (slot >= 36 && slot < 42 && DEV_Ability.Enabled))
|
|
{ SAV.setEK6Stored(blankEK6, getPKXOffset(slot)); }
|
|
else return;
|
|
|
|
SlotPictureBoxes[slot].Image = null;
|
|
getSlotColor(slot, Properties.Resources.slotDel);
|
|
}
|
|
private void clickClone(object sender, EventArgs e)
|
|
{
|
|
if (getSlot(sender) > 30) return; // only perform action if cloning to boxes
|
|
if (!verifiedPKX()) return; // don't copy garbage to the box
|
|
|
|
PK6 pk;
|
|
int box = CB_BoxSelect.SelectedIndex + 1; // get box we're cloning to
|
|
|
|
if (Util.Prompt(MessageBoxButtons.YesNo, $"Clone Pokemon from Editing Tabs to all slots in Box {box}?") == DialogResult.Yes)
|
|
pk = preparepkx();
|
|
else if (Util.Prompt(MessageBoxButtons.YesNo, $"Delete Pokemon from all slots in Box {box}?") == DialogResult.Yes)
|
|
pk = new PK6();
|
|
else
|
|
return; // abort clone/delete
|
|
|
|
for (int i = 0; i < 30; i++) // write encrypted array to all box slots
|
|
{
|
|
SAV.setPK6Stored(pk, getPKXOffset(i));
|
|
getQuickFiller(SlotPictureBoxes[i], pk);
|
|
}
|
|
}
|
|
private void updateEggRNGSeed(object sender, EventArgs e)
|
|
{
|
|
// Run through a LINQ filter for fun; works fine for GUI purposes, although LINQ may not be the fastest way to do it!
|
|
string filterText = TB_RNGSeed.Text.Select(char.ToUpper).Where("0123456789ABCDEF".Contains).Aggregate("", (str, c) => str + c);
|
|
if (filterText.Length != TB_RNGSeed.Text.Length)
|
|
{
|
|
Util.Alert("Expected HEX (0-9, A-F).", "Received: " + Environment.NewLine + TB_RNGSeed.Text);
|
|
// Reset to Stored Value
|
|
TB_RNGSeed.Text = SAV.DaycareRNGSeed.ToString("X16");
|
|
return; // recursively triggers this method, no need to continue
|
|
}
|
|
|
|
if (TB_RNGSeed.Text.Length == 0)
|
|
{
|
|
// Reset to 0
|
|
TB_RNGSeed.Text = 0.ToString("X16");
|
|
return; // recursively triggers this method, no need to continue
|
|
}
|
|
|
|
// Write final value back to the save
|
|
ulong value = Convert.ToUInt64(TB_RNGSeed.Text, 16);
|
|
if (value != SAV.DaycareRNGSeed)
|
|
{
|
|
SAV.DaycareRNGSeed = value;
|
|
SAV.Edited = true;
|
|
}
|
|
}
|
|
private void updateGameSync(object sender, EventArgs e)
|
|
{
|
|
// Run through a LINQ filter for fun; works fine for GUI purposes, although LINQ may not be the fastest way to do it!
|
|
string filterText = TB_GameSync.Text.Select(char.ToUpper).Where("0123456789ABCDEF".Contains).Aggregate("", (str, c) => str + c);
|
|
if (filterText.Length != TB_GameSync.Text.Length)
|
|
{
|
|
Util.Alert("Expected HEX (0-9, A-F).", "Received: " + Environment.NewLine + TB_GameSync.Text);
|
|
// Reset to Stored Value
|
|
TB_GameSync.Text = SAV.GameSyncID.ToString("X16");
|
|
return; // recursively triggers this method, no need to continue
|
|
}
|
|
|
|
if (TB_GameSync.Text.Length == 0)
|
|
{
|
|
// Reset to 0
|
|
TB_GameSync.Text = 0.ToString("X16");
|
|
return; // recursively triggers this method, no need to continue
|
|
}
|
|
|
|
// Write final value back to the save
|
|
ulong value = Convert.ToUInt64(TB_GameSync.Text, 16);
|
|
if (value != SAV.GameSyncID)
|
|
{
|
|
SAV.GameSyncID = value;
|
|
SAV.Edited = true;
|
|
}
|
|
}
|
|
private void updateSecure1(object sender, EventArgs e)
|
|
{
|
|
// Run through a LINQ filter for fun; works fine for GUI purposes, although LINQ may not be the fastest way to do it!
|
|
string filterText = TB_Secure1.Text.Select(char.ToUpper).Where("0123456789ABCDEF".Contains).Aggregate("", (str, c) => str + c);
|
|
if (filterText.Length != TB_Secure1.Text.Length)
|
|
{
|
|
Util.Alert("Expected HEX (0-9, A-F).", "Received: " + Environment.NewLine + TB_Secure1.Text);
|
|
// Reset to Stored Value
|
|
TB_Secure1.Text = SAV.Secure1.ToString("X16");
|
|
return; // recursively triggers this method, no need to continue
|
|
}
|
|
|
|
if (TB_Secure1.Text.Length == 0)
|
|
{
|
|
// Reset to 0
|
|
TB_Secure1.Text = 0.ToString("X16");
|
|
return; // recursively triggers this method, no need to continue
|
|
}
|
|
|
|
// Write final value back to the save
|
|
ulong value = Convert.ToUInt64(TB_Secure1.Text, 16);
|
|
if (value != SAV.Secure1)
|
|
{
|
|
SAV.Secure1 = value;
|
|
SAV.Edited = true;
|
|
}
|
|
}
|
|
private void updateSecure2(object sender, EventArgs e)
|
|
{
|
|
// Run through a LINQ filter for fun; works fine for GUI purposes, although LINQ may not be the fastest way to do it!
|
|
string filterText = TB_Secure2.Text.Select(char.ToUpper).Where("0123456789ABCDEF".Contains).Aggregate("", (str, c) => str + c);
|
|
if (filterText.Length != TB_Secure2.Text.Length)
|
|
{
|
|
Util.Alert("Expected HEX (0-9, A-F).", "Received: " + Environment.NewLine + TB_Secure2.Text);
|
|
// Reset to Stored Value
|
|
TB_Secure2.Text = SAV.Secure2.ToString("X16");
|
|
return; // recursively triggers this method, no need to continue
|
|
}
|
|
|
|
if (TB_Secure2.Text.Length == 0)
|
|
{
|
|
// Reset to 0
|
|
TB_Secure2.Text = 0.ToString("X16");
|
|
return; // recursively triggers this method, no need to continue
|
|
}
|
|
|
|
// Write final value back to the save
|
|
ulong value = Convert.ToUInt64(TB_Secure2.Text, 16);
|
|
if (value != SAV.Secure2)
|
|
{
|
|
SAV.Secure2 = value;
|
|
SAV.Edited = true;
|
|
}
|
|
}
|
|
// Generic Subfunctions //
|
|
private void setParty()
|
|
{
|
|
SAV.setParty();
|
|
// Refresh slots
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
getQuickFiller(SlotPictureBoxes[i + 30], SAV.getPK6Stored(SAV.Party + PK6.SIZE_PARTY*i));
|
|
getQuickFiller(SlotPictureBoxes[i + 36], SAV.getPK6Stored(SAV.BattleBox + PK6.SIZE_STORED*i));
|
|
}
|
|
}
|
|
private int getPKXOffset(int slot)
|
|
{
|
|
if (slot < 30) // Box Slot
|
|
return SAV.Box + (30 * CB_BoxSelect.SelectedIndex + slot) * PK6.SIZE_STORED;
|
|
if (slot < 36) // Party Slot
|
|
return SAV.Party + (slot - 30) * PK6.SIZE_PARTY;
|
|
if (slot < 42) // Battle Box Slot
|
|
return SAV.BattleBox + (slot - 36) * PK6.SIZE_STORED;
|
|
if (slot < 44) // Daycare
|
|
return SAV.DaycareSlot[DaycareSlot] + 8 + (slot - 42) * (PK6.SIZE_STORED + 8);
|
|
if (slot < 45) // GTS
|
|
return SAV.GTS;
|
|
if (slot < 46) // Fused
|
|
return SAV.Fused;
|
|
if (slot < 50) // SUBE
|
|
return SAV.SUBE + (slot - 46) * (PK6.SIZE_STORED + 4);
|
|
return -1;
|
|
}
|
|
private int getSlot(object sender)
|
|
{
|
|
sender = ((sender as ToolStripItem)?.Owner as ContextMenuStrip)?.SourceControl ?? sender as PictureBox;
|
|
return Array.IndexOf(SlotPictureBoxes, sender);
|
|
}
|
|
public void setPKXBoxes()
|
|
{
|
|
if (SAV.Box > -1)
|
|
{
|
|
int boxoffset = SAV.Box + CB_BoxSelect.SelectedIndex*PK6.SIZE_STORED*30;
|
|
int boxbgval = SAV.getBoxWallpaper(CB_BoxSelect.SelectedIndex);
|
|
string imagename = "box_wp" + boxbgval.ToString("00"); if (SAV.ORAS && boxbgval > 16) imagename += "o";
|
|
PAN_Box.BackgroundImage = (Image)Properties.Resources.ResourceManager.GetObject(imagename);
|
|
|
|
for (int i = 0; i < 30; i++)
|
|
getSlotFiller(boxoffset + PK6.SIZE_STORED * i, SlotPictureBoxes[i]);
|
|
}
|
|
|
|
// Reload Party
|
|
if (SAV.Party > -1)
|
|
for (int i = 0; i < 6; i++)
|
|
getSlotFiller(SAV.Party + PK6.SIZE_PARTY * i, SlotPictureBoxes[i + 30]);
|
|
|
|
// Reload Battle Box
|
|
if (SAV.BattleBox > -1)
|
|
for (int i = 0; i < 6; i++)
|
|
getSlotFiller(SAV.BattleBox + PK6.SIZE_STORED * i, SlotPictureBoxes[i + 36]);
|
|
|
|
// Reload Daycare
|
|
if (SAV.Daycare > -1)
|
|
{
|
|
Label[] dclabela = { L_DC1, L_DC2, };
|
|
TextBox[] dctexta = { TB_Daycare1XP, TB_Daycare2XP };
|
|
uint[] exp = { SAV.DaycareEXP1, SAV.DaycareEXP2 };
|
|
bool[] occ = { SAV.DaycareOccupied1, SAV.DaycareOccupied2 };
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
getSlotFiller(SAV.DaycareSlot[DaycareSlot] + PK6.SIZE_STORED * i + 8 * (i + 1), SlotPictureBoxes[i + 42]);
|
|
dctexta[i].Text = exp[i].ToString();
|
|
if (occ[i]) // If Occupied
|
|
dclabela[i].Text = $"{i + 1}: ✓";
|
|
else
|
|
{
|
|
dclabela[i].Text = $"{i + 1}: ✘";
|
|
SlotPictureBoxes[i + 42].Image = Util.ChangeOpacity(SlotPictureBoxes[i + 42].Image, 0.6);
|
|
}
|
|
}
|
|
DayCare_HasEgg.Checked = SAV.DaycareHasEgg;
|
|
TB_RNGSeed.Text = SAV.DaycareRNGSeed.ToString("X16");
|
|
}
|
|
|
|
// GTS
|
|
if (SAV.GTS > -1)
|
|
getSlotFiller(SAV.GTS, SlotPictureBoxes[44]);
|
|
|
|
// Fused
|
|
if (SAV.Fused > -1)
|
|
getSlotFiller(SAV.Fused, SlotPictureBoxes[45]);
|
|
|
|
// SUBE
|
|
if (SAV.SUBE > -1)
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
int offset = SAV.SUBE + i * (PK6.SIZE_STORED + 4);
|
|
if (BitConverter.ToUInt64(SAV.Data, offset) != 0)
|
|
getSlotFiller(offset, SlotPictureBoxes[46 + i]);
|
|
else SlotPictureBoxes[46 + i].Image = null;
|
|
}
|
|
|
|
// Recoloring of a storage box slot (to not show for other storage boxes)
|
|
if (colorizedslot < 32)
|
|
SlotPictureBoxes[colorizedslot].BackgroundImage = colorizedbox == CB_BoxSelect.SelectedIndex ? colorizedcolor : null;
|
|
}
|
|
private void setBoxNames()
|
|
{
|
|
if (SAV.Box < 0)
|
|
return;
|
|
int selectedbox = CB_BoxSelect.SelectedIndex; // precache selected box
|
|
// Build ComboBox Dropdown Items
|
|
try
|
|
{
|
|
CB_BoxSelect.Items.Clear();
|
|
for (int i = 0; i < 31; i++)
|
|
CB_BoxSelect.Items.Add(SAV.getBoxName(i));
|
|
}
|
|
catch
|
|
{
|
|
CB_BoxSelect.Items.Clear();
|
|
for (int i = 0; i < 31; i++)
|
|
CB_BoxSelect.Items.Add("BOX " + (i+1));
|
|
}
|
|
CB_BoxSelect.SelectedIndex = selectedbox; // restore selected box
|
|
}
|
|
private void getQuickFiller(PictureBox pb, PK6 pk = null)
|
|
{
|
|
if (!fieldsInitialized) return;
|
|
pk = pk ?? preparepkx(false); // don't perform control loss click
|
|
|
|
if (pb == dragout) L_QR.Visible = pk.Species != 0; // Species
|
|
pb.Image = pk.Sprite;
|
|
}
|
|
private void getSlotFiller(int offset, PictureBox pb)
|
|
{
|
|
if (SAV.getData(offset, PK6.SIZE_STORED).SequenceEqual(new byte[PK6.SIZE_STORED]))
|
|
{
|
|
// 00s present in slot.
|
|
pb.Image = null;
|
|
pb.BackColor = Color.Transparent;
|
|
return;
|
|
}
|
|
PK6 p = SAV.getPK6Stored(offset);
|
|
if (p.Sanity != 0 || !p.ChecksumValid) // Invalid
|
|
{
|
|
// Bad Egg present in slot.
|
|
pb.Image = null;
|
|
pb.BackColor = Color.Red;
|
|
return;
|
|
}
|
|
// Something stored in slot. Only display if species is valid.
|
|
pb.Image = p.Species == 0 ? null : p.Sprite;
|
|
pb.BackColor = Color.Transparent;
|
|
}
|
|
private void getSlotColor(int slot, Image color)
|
|
{
|
|
foreach (PictureBox t in SlotPictureBoxes)
|
|
t.BackgroundImage = null;
|
|
|
|
if (slot < 30)
|
|
colorizedbox = CB_BoxSelect.SelectedIndex;
|
|
|
|
SlotPictureBoxes[slot].BackgroundImage = color;
|
|
colorizedcolor = color;
|
|
colorizedslot = slot;
|
|
}
|
|
private void getBox(object sender, EventArgs e)
|
|
{
|
|
setPKXBoxes();
|
|
}
|
|
|
|
private int DaycareSlot;
|
|
private void switchDaycare(object sender, EventArgs e)
|
|
{
|
|
if (!SAV.ORAS) return;
|
|
if (DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Would you like to switch the view to the other Daycare?",
|
|
$"Currently viewing daycare {DaycareSlot + 1}."))
|
|
// If ORAS, alter the daycare offset via toggle.
|
|
DaycareSlot ^= 1;
|
|
|
|
// Refresh Boxes
|
|
setPKXBoxes();
|
|
}
|
|
|
|
private void dumpBoxesToDB(string path, bool individualBoxFolders)
|
|
{
|
|
PK6[] boxdata = SAV.BoxData;
|
|
for (int i = 0; i < boxdata.Length; i++)
|
|
{
|
|
PK6 pk = boxdata[i];
|
|
if (pk.Species == 0 || pk.Sanity != 0)
|
|
continue;
|
|
string fileName = Util.CleanFileName(pk.FileName);
|
|
string boxfolder = "";
|
|
if (individualBoxFolders)
|
|
{
|
|
boxfolder = "BOX" + (i / 30 + 1);
|
|
Directory.CreateDirectory(Path.Combine(path, boxfolder));
|
|
}
|
|
if (!File.Exists(Path.Combine(Path.Combine(path, boxfolder), fileName)))
|
|
File.WriteAllBytes(Path.Combine(Path.Combine(path, boxfolder), fileName), pk.Data.Take(PK6.SIZE_STORED).ToArray());
|
|
}
|
|
}
|
|
private void loadBoxesFromDB(string path)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(path)) return;
|
|
int offset = SAV.Box;
|
|
int ctr = CB_BoxSelect.SelectedIndex * 30;
|
|
int pastctr = 0;
|
|
|
|
// Clear out the box data array.
|
|
// Array.Clear(savefile, offset, size * 30 * 31);
|
|
DialogResult dr = Util.Prompt(MessageBoxButtons.YesNoCancel, "Clear subsequent boxes when importing data?", "If you only want to overwrite for new data, press no.");
|
|
if (dr == DialogResult.Cancel) return;
|
|
if (dr == DialogResult.Yes)
|
|
{
|
|
for (int i = ctr; i < 30 * 31; i++)
|
|
SAV.setData(blankEK6, offset + i * PK6.SIZE_STORED);
|
|
}
|
|
string[] filepaths = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly);
|
|
|
|
foreach (string t in filepaths)
|
|
{
|
|
long len = new FileInfo(t).Length;
|
|
if (len > PK6.SIZE_PARTY)
|
|
continue;
|
|
|
|
if (!new[] {PK6.SIZE_STORED, PK6.SIZE_PARTY, PK5.SIZE_STORED, PK5.SIZE_PARTY, PK4.SIZE_PARTY, PK3.SIZE_STORED, PK3.SIZE_PARTY}.Contains((int)len))
|
|
continue;
|
|
byte[] data = new byte[PK6.SIZE_STORED];
|
|
switch (Path.GetExtension(t)) // Filter all files by extension
|
|
{
|
|
case ".pk5":
|
|
case ".pk4":
|
|
case ".pk3":
|
|
case ".3gpkm":
|
|
case ".pkm":
|
|
{
|
|
// Verify PKM (decrypted)
|
|
byte[] input = File.ReadAllBytes(t);
|
|
if (!PKX.verifychk(input)) continue;
|
|
{
|
|
try // to convert g5pkm
|
|
{ data = PKX.encryptArray(Converter.ConvertPKMtoPK6(input).Data); pastctr++; }
|
|
catch { continue; }
|
|
}
|
|
}
|
|
break;
|
|
case ".pk6":
|
|
case ".pkx":
|
|
{
|
|
byte[] input = File.ReadAllBytes(t);
|
|
if ((BitConverter.ToUInt16(input, 0xC8) == 0) && (BitConverter.ToUInt16(input, 0x58) == 0))
|
|
{
|
|
if (BitConverter.ToUInt16(input, 0x8) == 0) // if species = 0
|
|
continue;
|
|
Array.Resize(ref input, PK6.SIZE_STORED);
|
|
|
|
if (PKX.getCHK(input) != BitConverter.ToUInt16(input, 0x6)) continue;
|
|
data = PKX.encryptArray(input);
|
|
}
|
|
}
|
|
break;
|
|
case ".ek6":
|
|
case ".ekx":
|
|
{
|
|
byte[] input = File.ReadAllBytes(t);
|
|
Array.Resize(ref input, PK6.SIZE_STORED);
|
|
Array.Copy(input, data, PK6.SIZE_STORED);
|
|
// check if it is good data
|
|
byte[] decrypteddata = PKX.decryptArray(input);
|
|
|
|
if (BitConverter.ToUInt16(decrypteddata, 0xC8) != 0 && BitConverter.ToUInt16(decrypteddata, 0x58) != 0)
|
|
continue;
|
|
if (BitConverter.ToUInt16(decrypteddata, 0x8) == 0) // if species = 0
|
|
continue;
|
|
if (PKX.getCHK(input) != BitConverter.ToUInt16(decrypteddata, 0x6)) continue;
|
|
}
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
SAV.setEK6Stored(data, offset + ctr++ * PK6.SIZE_STORED);
|
|
if (ctr == 30 * 31) break; // break out if we have written all 31 boxes
|
|
}
|
|
ctr -= 30*CB_BoxSelect.SelectedIndex; // actual imported count
|
|
if (ctr <= 0) return;
|
|
|
|
setPKXBoxes();
|
|
string result = $"Loaded {ctr} files to boxes.";
|
|
if (pastctr > 0)
|
|
Util.Alert(result, $"Conversion successful for {pastctr} past generation files.");
|
|
else
|
|
Util.Alert(result);
|
|
}
|
|
private void B_SaveBoxBin_Click(object sender, EventArgs e)
|
|
{
|
|
DialogResult dr = Util.Prompt(MessageBoxButtons.YesNoCancel, "Yes: Export All Boxes" + Environment.NewLine + string.Format("No: Export {1} (Box {0})", CB_BoxSelect.SelectedIndex + 1, CB_BoxSelect.Text) + Environment.NewLine + "Cancel: Abort");
|
|
|
|
if (dr == DialogResult.Yes)
|
|
{
|
|
SaveFileDialog sfd = new SaveFileDialog {Filter = "Box Data|*.bin", FileName = "pcdata.bin"};
|
|
if (sfd.ShowDialog() == DialogResult.OK)
|
|
File.WriteAllBytes(sfd.FileName, SAV.getData(SAV.Box, PK6.SIZE_STORED * 30 * 31));
|
|
}
|
|
else if (dr == DialogResult.No)
|
|
{
|
|
SaveFileDialog sfd = new SaveFileDialog {Filter = "Box Data|*.bin", FileName = "boxdata.bin"};
|
|
if (sfd.ShowDialog() == DialogResult.OK)
|
|
File.WriteAllBytes(sfd.FileName, SAV.getData(SAV.Box + PK6.SIZE_STORED * 30 * CB_BoxSelect.SelectedIndex, PK6.SIZE_STORED * 30));
|
|
}
|
|
}
|
|
|
|
// Subfunction Save Buttons //
|
|
private void B_OpenWondercards_Click(object sender, EventArgs e)
|
|
{
|
|
// Open Wondercard Menu
|
|
new SAV_Wondercard().ShowDialog();
|
|
}
|
|
private void B_OpenBoxLayout_Click(object sender, EventArgs e)
|
|
{
|
|
// Open Box Layout Menu
|
|
new SAV_BoxLayout(CB_BoxSelect.SelectedIndex).ShowDialog();
|
|
setBoxNames(); // fix box names
|
|
setPKXBoxes(); // refresh box background
|
|
}
|
|
private void B_OpenTrainerInfo_Click(object sender, EventArgs e)
|
|
{
|
|
new SAV_Trainer().ShowDialog();
|
|
// Refresh PK#->PK6 conversion info
|
|
Converter.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_OpenItemPouch_Click(object sender, EventArgs e)
|
|
{
|
|
new SAV_Inventory().ShowDialog();
|
|
}
|
|
private void B_OpenBerryField_Click(object sender, EventArgs e)
|
|
{
|
|
if (SAV.ORAS)
|
|
new SAV_BerryFieldORAS().ShowDialog();
|
|
else
|
|
new SAV_BerryFieldXY().ShowDialog();
|
|
}
|
|
private void B_OpenEventFlags_Click(object sender, EventArgs e)
|
|
{
|
|
// Open Flag Menu
|
|
if (SAV.ORAS)
|
|
new SAV_EventFlagsORAS().ShowDialog();
|
|
else
|
|
new SAV_EventFlagsXY().ShowDialog();
|
|
}
|
|
private void B_OpenSuperTraining_Click(object sender, EventArgs e)
|
|
{
|
|
// Open ST Menu
|
|
new SAV_SuperTrain().ShowDialog();
|
|
}
|
|
private void B_OpenOPowers_Click(object sender, EventArgs e)
|
|
{
|
|
// Open O-Power Menu
|
|
if (SAV.ORAS)
|
|
{
|
|
DialogResult dr = Util.Prompt(MessageBoxButtons.YesNo, "No editing support for ORAS :(", "Max O-Powers with a working code?");
|
|
if (dr != DialogResult.Yes) return;
|
|
new byte[]
|
|
{
|
|
0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00,
|
|
0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x00, 0x00, 0x00,
|
|
}.CopyTo(SAV.Data, SAV.OPower);
|
|
}
|
|
else
|
|
new SAV_OPower().ShowDialog();
|
|
}
|
|
private void B_OpenPokedex_Click(object sender, EventArgs e)
|
|
{
|
|
// Open Pokedex Menu
|
|
if (SAV.ORAS)
|
|
new SAV_PokedexORAS().ShowDialog();
|
|
else
|
|
new SAV_PokedexXY().ShowDialog();
|
|
}
|
|
private void B_OUTPasserby_Click(object sender, EventArgs e)
|
|
{
|
|
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo, "Export Passerby Info to Clipboard?"))
|
|
return;
|
|
|
|
string result = "PSS List" + Environment.NewLine;
|
|
string[] headers = { "PSS Data - Friends", "PSS Data - Acquaintances", "PSS Data - Passerby", };
|
|
int offset = SAV.PSS;
|
|
for (int g = 0; g < 3; g++)
|
|
{
|
|
result += Environment.NewLine
|
|
+ "----" + Environment.NewLine
|
|
+ headers[g] + Environment.NewLine
|
|
+ "----" + Environment.NewLine;
|
|
// uint count = BitConverter.ToUInt32(savefile, offset + 0x4E20);
|
|
int r_offset = offset;
|
|
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
ulong unkn = BitConverter.ToUInt64(SAV.Data, r_offset);
|
|
if (unkn == 0) break; // No data present here
|
|
if (i > 0) result += Environment.NewLine + Environment.NewLine;
|
|
|
|
string otname = Util.TrimFromZero(Encoding.Unicode.GetString(SAV.Data, r_offset + 8, 0x1A));
|
|
string message = Util.TrimFromZero(Encoding.Unicode.GetString(SAV.Data, r_offset + 0x22, 0x22));
|
|
|
|
// Trim terminated
|
|
|
|
// uint unk1 = BitConverter.ToUInt32(savefile, r_offset + 0x44);
|
|
// ulong unk2 = BitConverter.ToUInt64(savefile, r_offset + 0x48);
|
|
// uint unk3 = BitConverter.ToUInt32(savefile, r_offset + 0x50);
|
|
// uint unk4 = BitConverter.ToUInt16(savefile, r_offset + 0x54);
|
|
byte region = SAV.Data[r_offset + 0x56];
|
|
byte country = SAV.Data[r_offset + 0x57];
|
|
byte game = SAV.Data[r_offset + 0x5A];
|
|
// ulong outfit = BitConverter.ToUInt64(savefile, r_offset + 0x5C);
|
|
int favpkm = BitConverter.ToUInt16(SAV.Data, r_offset + 0x9C) & 0x7FF;
|
|
string gamename;
|
|
try { gamename = gamelist[game]; }
|
|
catch { gamename = "UNKNOWN GAME"; }
|
|
|
|
string[] cr = PKX.getCountryRegionText(country, region, curlanguage);
|
|
result +=
|
|
"OT: " + otname + Environment.NewLine +
|
|
"Message: " + message + Environment.NewLine +
|
|
"Game: " + gamename + Environment.NewLine +
|
|
"Country: " + cr[0] + Environment.NewLine +
|
|
"Region: " + cr[1] + Environment.NewLine +
|
|
"Favorite: " + specieslist[favpkm];
|
|
|
|
r_offset += 0xC8; // Advance to next entry
|
|
}
|
|
offset += 0x5000; // Advance to next block
|
|
}
|
|
Clipboard.SetText(result);
|
|
}
|
|
private void B_OUTHallofFame_Click(object sender, EventArgs e)
|
|
{
|
|
// Open HoF Menu
|
|
new SAV_HallOfFame().ShowDialog();
|
|
}
|
|
private void B_OpenSecretBase_Click(object sender, EventArgs e)
|
|
{
|
|
// Open Secret Base Menu
|
|
new SAV_SecretBase().ShowDialog();
|
|
}
|
|
private void B_JPEG_Click(object sender, EventArgs e)
|
|
{
|
|
byte[] jpeg = SAV.JPEGData;
|
|
if (SAV.JPEGData == null)
|
|
{ Util.Alert("No PGL picture data found in the save file!"); return; }
|
|
string filename = SAV.JPEGTitle + "'s picture";
|
|
SaveFileDialog sfd = new SaveFileDialog {FileName = filename, Filter = "JPEG|*.jpeg"};
|
|
if (sfd.ShowDialog() != DialogResult.OK) return;
|
|
File.WriteAllBytes(sfd.FileName, jpeg);
|
|
}
|
|
// Save Folder Related
|
|
private void clickSaveFileName(object sender, EventArgs e)
|
|
{
|
|
// Get latest SaveDataFiler save location
|
|
pathSDF = Util.GetSDFLocation();
|
|
path3DS = Util.get3DSLocation();
|
|
string path = null;
|
|
|
|
if (path3DS != null && File.Exists(Path.Combine(Path.GetPathRoot(path3DS), "ramsav.bin")))
|
|
path = Path.Combine(Path.GetPathRoot(path3DS), "ramsav.bin");
|
|
if (path3DS != null && Directory.Exists(Path.Combine(path3DS, "SaveDataBackup")) && ModifierKeys != Keys.Control)
|
|
path = Path.Combine(Path.GetPathRoot(path3DS), "SaveDataBackup", "main");
|
|
else if (pathSDF != null && ModifierKeys != Keys.Shift) // if we have a result
|
|
path = Path.Combine(pathSDF, "main");
|
|
else if (File.Exists(Util.NormalizePath(Path.Combine(Util.GetTempFolder(), "root", "main")))) // else if cgse exists
|
|
path = Util.NormalizePath(Path.Combine(Util.GetTempFolder(), "root", "main"));
|
|
|
|
if (path == null || !File.Exists(path)) return;
|
|
if (Util.Prompt(MessageBoxButtons.YesNo, "Open save file from the following location?", path) == DialogResult.Yes)
|
|
openQuick(path); // load save
|
|
}
|
|
|
|
// Drag & Drop within Box
|
|
private void pbBoxSlot_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button != MouseButtons.Left || e.Clicks != 1) return;
|
|
if (ModifierKeys == Keys.Control || ModifierKeys == Keys.Alt || ModifierKeys == Keys.Shift || ModifierKeys == (Keys.Control | Keys.Alt))
|
|
{ clickSlot(sender, e); return; }
|
|
PictureBox pb = (PictureBox)sender;
|
|
if (pb.Image == null)
|
|
return;
|
|
|
|
pkm_from_slot = getSlot(sender);
|
|
int offset = getPKXOffset(pkm_from_slot);
|
|
// Create Temp File to Drag
|
|
Cursor.Current = Cursors.Hand;
|
|
|
|
// Prepare Data
|
|
pkm_from = SAV.getData(offset, PK6.SIZE_STORED);
|
|
pkm_from_offset = offset;
|
|
|
|
// Make a new file name based off the PID
|
|
byte[] dragdata = PKX.decryptArray(pkm_from);
|
|
Array.Resize(ref dragdata, PK6.SIZE_STORED);
|
|
var pkx = new PK6(dragdata, "Boxes");
|
|
string filename = pkx.FileName;
|
|
|
|
// Make File
|
|
string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
|
|
try
|
|
{
|
|
File.WriteAllBytes(newfile, dragdata);
|
|
DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Move);
|
|
}
|
|
catch (ArgumentException x)
|
|
{ Util.Error("Drag & Drop Error:", x.ToString()); }
|
|
File.Delete(newfile);
|
|
pkm_from_offset = 0;
|
|
}
|
|
private void pbBoxSlot_DragDrop(object sender, DragEventArgs e)
|
|
{
|
|
int slot = getSlot(sender);
|
|
int offset = getPKXOffset(slot);
|
|
|
|
// Check for In-Dropped files (PKX,SAV,ETC)
|
|
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
|
if (Directory.Exists(files[0])) { loadBoxesFromDB(files[0]); return; }
|
|
if (pkm_from_offset == 0)
|
|
{
|
|
if (files.Length > 0)
|
|
{
|
|
FileInfo fi = new FileInfo(files[0]);
|
|
|
|
// Detect if PKM/PKX
|
|
if (new[] { PK3.SIZE_PARTY, PK3.SIZE_STORED, PK4.SIZE_PARTY, PK4.SIZE_STORED, PK5.SIZE_PARTY }.Contains((int)fi.Length))
|
|
{
|
|
byte[] input = File.ReadAllBytes(files[0]);
|
|
if (!PKX.verifychk(input)) Util.Alert("Invalid File Loaded.", "Checksum is not valid.");
|
|
try // to convert past gen pkm
|
|
{
|
|
SAV.setPK6Stored(Converter.ConvertPKMtoPK6(input), offset);
|
|
}
|
|
catch
|
|
{ Util.Error("Attempted to load previous generation PKM.", "Conversion failed."); }
|
|
}
|
|
else if (fi.Length == PK6.SIZE_STORED || fi.Length == PK6.SIZE_PARTY)
|
|
{
|
|
byte[] data = File.ReadAllBytes(files[0]);
|
|
if (fi.Extension == ".pkx" || fi.Extension == ".pk6")
|
|
data = PKX.encryptArray(data);
|
|
else if (fi.Extension != ".ekx" && fi.Extension != ".ek6")
|
|
{ openQuick(files[0]); return; } // lazy way of aborting
|
|
|
|
byte[] decdata = PKX.decryptArray(data);
|
|
if (!PKX.verifychk(decdata))
|
|
Util.Alert("Attempted to load Invalid File.", "Checksum is not valid.");
|
|
else
|
|
{
|
|
SAV.setEK6Stored(data, offset);
|
|
getQuickFiller(SlotPictureBoxes[slot], new PK6(decdata));
|
|
getSlotColor(slot, Properties.Resources.slotSet);
|
|
}
|
|
}
|
|
else // not PKX/EKX, so load with the general function
|
|
{ openQuick(files[0]); }
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ModifierKeys == Keys.Alt && slot > -1) // overwrite delete old slot
|
|
{
|
|
// Clear from slot picture
|
|
getQuickFiller(SlotPictureBoxes[pkm_from_slot], new PK6());
|
|
|
|
// Clear from slot data
|
|
SAV.setEK6Stored(blankEK6, pkm_from_offset);
|
|
}
|
|
else if (ModifierKeys != Keys.Control && slot > -1)
|
|
{
|
|
// Load data from destination
|
|
PK6 pk = SAV.getPK6Stored(offset);
|
|
|
|
// Swap slot picture
|
|
getQuickFiller(SlotPictureBoxes[pkm_from_slot], pk);
|
|
|
|
// Swap slot data to source
|
|
SAV.setPK6Stored(pk, pkm_from_offset);
|
|
}
|
|
// Copy from temp slot to new.
|
|
SAV.setEK6Stored(pkm_from, offset);
|
|
getQuickFiller(SlotPictureBoxes[slot], new PK6(PKX.decryptArray(pkm_from)));
|
|
|
|
pkm_from_offset = 0; // Clear offset value
|
|
}
|
|
|
|
SAV.Edited = true;
|
|
}
|
|
private void pbBoxSlot_DragEnter(object sender, DragEventArgs e)
|
|
{
|
|
if (e.AllowedEffect == (DragDropEffects.Copy | DragDropEffects.Link)) // external file
|
|
e.Effect = DragDropEffects.Copy;
|
|
else if (e.Data != null) // within
|
|
e.Effect = DragDropEffects.Move;
|
|
}
|
|
private byte[] pkm_from = (byte[])blankEK6.Clone();
|
|
private int pkm_from_offset;
|
|
private int pkm_from_slot = -1;
|
|
#endregion
|
|
}
|
|
}
|