PKHeX/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs
Kurt 5e96c6e035 Extract main window strings to translatable class
Similar to LegalityCheckStrings
no resource files yet, will generate those tomorrow(?)

some strings are not translatable (useless gen6 passerby export text),
not really worth
2018-04-05 21:25:18 -07:00

1735 lines
67 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using PKHeX.Core;
using PKHeX.WinForms.Properties;
using System.ComponentModel;
using static PKHeX.Core.MessageStrings;
namespace PKHeX.WinForms.Controls
{
public partial class PKMEditor : UserControl, IMainEditor
{
public PKMEditor()
{
InitializeComponent();
Legality = new LegalityAnalysis(pkm = new PK7());
SetPKMFormatMode(pkm.Format);
GB_OT.Click += ClickGT;
GB_nOT.Click += ClickGT;
GB_CurrentMoves.Click += ClickMoves;
GB_RelearnMoves.Click += ClickMoves;
TB_Nickname.Font = FontUtil.GetPKXFont(11);
TB_OT.Font = (Font)TB_Nickname.Font.Clone();
TB_OTt2.Font = (Font)TB_Nickname.Font.Clone();
// Commonly reused Control arrays
Moves = new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4 };
Relearn = new[] { CB_RelearnMove1, CB_RelearnMove2, CB_RelearnMove3, CB_RelearnMove4 };
PPUps = new[] { CB_PPu1, CB_PPu2, CB_PPu3, CB_PPu4 };
MovePP = new[] { TB_PP1, TB_PP2, TB_PP3, TB_PP4 };
ValidationRequired = Moves.Concat(Relearn).Concat(new[]
{
CB_Species, CB_Nature, CB_HeldItem, CB_Ability, // Main Tab
CB_MetLocation, CB_EggLocation, CB_Ball, // Met Tab
}).ToArray();
relearnPB = new[] { PB_WarnRelearn1, PB_WarnRelearn2, PB_WarnRelearn3, PB_WarnRelearn4 };
movePB = new[] { PB_WarnMove1, PB_WarnMove2, PB_WarnMove3, PB_WarnMove4 };
foreach (var c in WinFormsUtil.GetAllControlsOfType(this, typeof(ComboBox)))
c.KeyDown += WinFormsUtil.RemoveDropCB;
Stats.SetMainEditor(this);
LoadShowdownSet = LoadShowdownSetDefault;
}
private void UpdateStats() => Stats.UpdateStats();
private void LoadPartyStats(PKM pk) => Stats.LoadPartyStats(pk);
private void SavePartyStats(PKM pk)
{
Stats.SavePartyStats(pk);
pk.Stat_Level = CurrentLevel;
}
public PKM CurrentPKM { get => FieldsInitialized ? PreparePKM() : pkm; set => pkm = value; }
public bool ModifyPKM { private get; set; } = true;
public bool Unicode { get; set; } = true;
public bool HaX { get; set; }
public byte[] LastData { private get; set; }
public PKM pkm { get; private set; }
public bool FieldsInitialized { get; private set; }
public bool FieldsLoaded { get; private set; }
public bool ChangingFields { get; set; }
public int CurrentLevel => Convert.ToInt32((HaX ? MT_Level : TB_Level).Text);
private GameVersion origintrack;
private Action GetFieldsfromPKM;
private Func<PKM> GetPKMfromFields;
private LegalityAnalysis Legality;
private string[] gendersymbols = { "♂", "♀", "-" };
private readonly Image mixedHighlight = ImageUtil.ChangeOpacity(Resources.slotSet, 0.5);
public event EventHandler LegalityChanged;
public event EventHandler UpdatePreviewSprite;
public event EventHandler RequestShowdownImport;
public event EventHandler RequestShowdownExport;
public event ReturnSAVEventHandler SaveFileRequested;
public delegate SaveFile ReturnSAVEventHandler(object sender, EventArgs e);
private readonly PictureBox[] movePB, relearnPB;
private readonly ToolTip Tip1 = new ToolTip(), Tip2 = new ToolTip(), Tip3 = new ToolTip(), NatureTip = new ToolTip();
private SaveFile RequestSaveFile => SaveFileRequested?.Invoke(this, EventArgs.Empty);
public bool PKMIsUnsaved => FieldsInitialized && FieldsLoaded && LastData != null && LastData.Any(b => b != 0) && !LastData.SequenceEqual(CurrentPKM.Data);
public bool IsEmptyOrEgg => CHK_IsEgg.Checked || CB_Species.SelectedIndex == 0;
private readonly ComboBox[] Moves, Relearn, ValidationRequired, PPUps;
private readonly MaskedTextBox[] MovePP;
private bool forceValidation;
public PKM PreparePKM(bool click = true)
{
if (click)
{
forceValidation = true;
ValidateChildren();
forceValidation = false;
}
PKM pk = GetPKMfromFields();
return pk?.Clone();
}
public bool VerifiedPKM()
{
if (ModifierKeys == (Keys.Control | Keys.Shift | Keys.Alt))
return true; // Override
// Make sure the PKX Fields are filled out properly (color check)
var cb = ValidationRequired.FirstOrDefault(c => c.BackColor == Color.DarkSalmon && c.Items.Count != 0);
if (cb != null)
{
Control c = cb.Parent; while (!(c is TabPage)) c = c.Parent;
tabMain.SelectedTab = c as TabPage;
}
else if (!Stats.Valid)
tabMain.SelectedTab = Tab_Stats;
else if (WinFormsUtil.GetIndex(CB_Species) == 0)
tabMain.SelectedTab = Tab_Main;
else
return true;
System.Media.SystemSounds.Exclamation.Play();
return false;
}
public void InitializeFields()
{
// Now that the ComboBoxes are ready, load the data.
Stats.SetMainEditor(this);
FieldsInitialized = true;
PopulateFields(pkm);
}
public void SetPKMFormatMode(int Format)
{
byte[] extraBytes = new byte[0];
switch (Format)
{
case 1:
GetFieldsfromPKM = PopulateFieldsPK1;
GetPKMfromFields = PreparePK1;
break;
case 2:
GetFieldsfromPKM = PopulateFieldsPK2;
GetPKMfromFields = PreparePK2;
break;
case 3:
if (pkm is CK3)
{
GetFieldsfromPKM = PopulateFieldsCK3;
GetPKMfromFields = PrepareCK3;
extraBytes = CK3.ExtraBytes;
break;
}
if (pkm is XK3)
{
GetFieldsfromPKM = PopulateFieldsXK3;
GetPKMfromFields = PrepareXK3;
extraBytes = XK3.ExtraBytes;
break;
}
GetFieldsfromPKM = PopulateFieldsPK3;
GetPKMfromFields = PreparePK3;
extraBytes = PK3.ExtraBytes;
break;
case 4:
GetFieldsfromPKM = PopulateFieldsPK4;
GetPKMfromFields = PreparePK4;
extraBytes = PK4.ExtraBytes;
break;
case 5:
GetFieldsfromPKM = PopulateFieldsPK5;
GetPKMfromFields = PreparePK5;
extraBytes = PK5.ExtraBytes;
break;
case 6:
GetFieldsfromPKM = PopulateFieldsPK6;
GetPKMfromFields = PreparePK6;
extraBytes = PK6.ExtraBytes;
break;
case 7:
GetFieldsfromPKM = PopulateFieldsPK7;
GetPKMfromFields = PreparePK7;
extraBytes = PK7.ExtraBytes;
break;
}
// Load Extra Byte List
GB_ExtraBytes.Visible = GB_ExtraBytes.Enabled = extraBytes.Length != 0;
CB_ExtraBytes.Items.Clear();
foreach (byte b in extraBytes)
CB_ExtraBytes.Items.Add($"0x{b:X2}");
if (GB_ExtraBytes.Enabled)
CB_ExtraBytes.SelectedIndex = 0;
}
public void PopulateFields(PKM pk, bool focus = true, bool skipConversionCheck = false) => LoadFieldsFromPKM(pk, focus, skipConversionCheck);
private void LoadFieldsFromPKM(PKM pk, bool focus = true, bool skipConversionCheck = true)
{
if (pk == null) { WinFormsUtil.Error(MsgPKMLoadNull); return; }
if (focus)
Tab_Main.Focus();
if (!skipConversionCheck && !PKMConverter.TryMakePKMCompatible(pk, CurrentPKM, out string c, out pk))
{ WinFormsUtil.Alert(c); return; }
bool oldInit = FieldsInitialized;
FieldsInitialized = FieldsLoaded = false;
pkm = pk.Clone();
try { GetFieldsfromPKM(); }
finally { FieldsInitialized = oldInit; }
Stats.UpdateIVs(null, null);
UpdatePKRSInfected(null, null);
UpdatePKRSCured(null, null);
if (HaX) // Load original values from pk not pkm
{
MT_Level.Text = (pk.Stat_HPMax != 0 ? pk.Stat_Level : PKX.GetLevel(pk.Species, pk.EXP)).ToString();
TB_EXP.Text = pk.EXP.ToString();
MT_Form.Text = pk.AltForm.ToString();
if (pk.Stat_HPMax != 0) // stats present
Stats.LoadPartyStats(pk);
}
FieldsLoaded = true;
SetMarkings();
UpdateLegality();
UpdateSprite();
LastData = PreparePKM()?.Data;
}
public void UpdateLegality(LegalityAnalysis la = null, bool skipMoveRepop = false)
{
if (!FieldsLoaded)
return;
Legality = la ?? new LegalityAnalysis(pkm, RequestSaveFile.Personal);
if (!Legality.Parsed || HaX || pkm.Species == 0)
{
PB_WarnMove1.Visible = PB_WarnMove2.Visible = PB_WarnMove3.Visible = PB_WarnMove4.Visible =
PB_WarnRelearn1.Visible = PB_WarnRelearn2.Visible = PB_WarnRelearn3.Visible = PB_WarnRelearn4.Visible = false;
LegalityChanged?.Invoke(Legality.Valid, null);
return;
}
// Refresh Move Legality
for (int i = 0; i < 4; i++)
movePB[i].Visible = !Legality.Info?.Moves[i].Valid ?? false;
if (pkm.Format >= 6)
for (int i = 0; i < 4; i++)
relearnPB[i].Visible = !Legality.Info?.Relearn[i].Valid ?? false;
if (skipMoveRepop)
return;
// Resort moves
bool tmp = FieldsLoaded;
FieldsLoaded = false;
var moves = Legality.AllSuggestedMovesAndRelearn;
var moveList = GameInfo.MoveDataSource.OrderByDescending(m => moves.Contains(m.Value)).ToList();
foreach (var c in Moves)
{
var index = WinFormsUtil.GetIndex(c);
c.DataSource = new BindingSource(moveList, null);
c.SelectedValue = index;
if (c.Visible)
c.SelectionLength = 0; // flicker hack
}
FieldsLoaded |= tmp;
LegalityChanged?.Invoke(Legality.Valid, null);
}
public void UpdateUnicode(string[] symbols)
{
gendersymbols = symbols;
if (!Unicode)
{
BTN_Shinytize.Text = "*";
TB_Nickname.Font = TB_OT.Font = TB_OTt2.Font = Label_TID.Font;
}
else
{
BTN_Shinytize.Text = "☆";
TB_Nickname.Font = TB_OT.Font = TB_OTt2.Font = FontUtil.GetPKXFont(11);
}
// Switch active gender labels to new if they are active.
if (PKX.GetGenderFromString(Label_Gender.Text) < 2)
Label_Gender.Text = gendersymbols[PKX.GetGenderFromString(Label_Gender.Text)];
if (PKX.GetGenderFromString(Label_OTGender.Text) < 2)
Label_OTGender.Text = gendersymbols[PKX.GetGenderFromString(Label_OTGender.Text)];
if (PKX.GetGenderFromString(Label_CTGender.Text) < 2)
Label_CTGender.Text = gendersymbols[PKX.GetGenderFromString(Label_CTGender.Text)];
}
private void UpdateSprite()
{
if (FieldsLoaded && FieldsInitialized && !forceValidation)
UpdatePreviewSprite?.Invoke(this, null);
}
// General Use Functions //
private Color GetGenderColor(int gender)
{
if (gender == 0) // male
return Color.Blue;
if (gender == 1) // female
return Color.Red;
return CB_Species.ForeColor;
}
private void SetDetailsOT(ITrainerInfo SAV)
{
if (!(SAV.OT?.Length > 0))
return;
// Get Save Information
TB_OT.Text = SAV.OT;
Label_OTGender.Text = gendersymbols[SAV.Gender & 1];
Label_OTGender.ForeColor = GetGenderColor(SAV.Gender & 1);
TB_TID.Text = SAV.TID.ToString("00000");
TB_SID.Text = SAV.SID.ToString("00000");
if (SAV.Game >= 0)
CB_GameOrigin.SelectedValue = SAV.Game;
if (SAV.Language >= 0)
CB_Language.SelectedValue = SAV.Language;
if (SAV.ConsoleRegion != 0)
{
CB_3DSReg.SelectedValue = SAV.ConsoleRegion;
CB_Country.SelectedValue = SAV.Country;
CB_SubRegion.SelectedValue = SAV.SubRegion;
}
// Copy OT trash bytes for sensitive games (Gen1/2)
if (SAV is SAV1 s1 && pkm is PK1 p1) p1.OT_Trash = s1.OT_Trash;
else if (SAV is SAV2 s2 && pkm is PK2 p2) p2.OT_Trash = s2.OT_Trash;
UpdateNickname(null, null);
}
private void SetDetailsHT(ITrainerInfo SAV)
{
if (!(SAV.OT?.Length > 0))
return;
if (TB_OTt2.Text.Length > 0)
Label_CTGender.Text = gendersymbols[SAV.Gender & 1];
}
private void SetForms()
{
int species = WinFormsUtil.GetIndex(CB_Species);
if (pkm.Format < 4 && species != 201)
{
Label_Form.Visible = CB_Form.Visible = CB_Form.Enabled = false;
return;
}
int count = (RequestSaveFile?.Personal[species] ?? pkm.PersonalInfo).FormeCount;
bool hasForms = count > 1 || new[] { 201, 664, 665, 414 }.Contains(species);
CB_Form.Enabled = CB_Form.Visible = Label_Form.Visible = hasForms;
if (HaX && pkm.Format >= 4)
Label_Form.Visible = true;
if (!hasForms)
return;
var ds = PKX.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, gendersymbols, pkm.Format).ToList();
if (ds.Count == 1 && string.IsNullOrEmpty(ds[0])) // empty (Alolan Totems)
CB_Form.Enabled = CB_Form.Visible = Label_Form.Visible = false;
else CB_Form.DataSource = ds;
}
private void SetAbilityList()
{
if (pkm.Format < 3) // no abilities
return;
if (pkm.Format > 3 && FieldsLoaded) // has forms
pkm.AltForm = CB_Form.SelectedIndex; // update pkm field for form specific abilities
int abil = CB_Ability.SelectedIndex;
bool tmp = FieldsLoaded;
FieldsLoaded = false;
InitializeBinding(CB_Ability);
CB_Ability.DataSource = GetAbilityList(pkm);
CB_Ability.SelectedIndex = GetSafeIndex(CB_Ability, abil); // restore original index if available
FieldsLoaded = tmp;
}
private static int GetSafeIndex(ComboBox cb, int index) => Math.Max(0, Math.Min(cb.Items.Count - 1, index));
private static readonly string[] abilIdentifier = { " (1)", " (2)", " (H)" };
private static List<ComboItem> GetAbilityList(PKM pkm)
{
var abils = pkm.PersonalInfo.Abilities;
if (abils[1] == 0 && pkm.Format != 3)
abils[1] = abils[0];
var list = abils.Where(a => a != 0).Select(GetItem).ToList();
if (list.Count == 0)
list.Add(GetItem(0, 0));
return list;
ComboItem GetItem(int ability, int index) => new ComboItem
{
Value = ability,
Text = GameInfo.Strings.abilitylist[ability] + abilIdentifier[index]
};
}
private void SetIsShiny(object sender)
{
if (sender == TB_PID)
pkm.PID = Util.GetHexValue(TB_PID.Text);
else if (sender == TB_TID)
pkm.TID = (int)Util.ToUInt32(TB_TID.Text);
else if (sender == TB_SID)
pkm.SID = (int)Util.ToUInt32(TB_SID.Text);
// Recalculate shininiess
bool isShiny = pkm.IsShiny;
// 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()
{
double getOpacity(bool b) => b ? 1 : 0.175;
Image changeOpacity(PictureBox p, double opacity) => opacity == 1 ? p.InitialImage
: ImageUtil.ChangeOpacity(p.InitialImage, opacity);
PictureBox[] pba = { PB_Mark1, PB_Mark2, PB_Mark3, PB_Mark4, PB_Mark5, PB_Mark6 };
for (int i = 0; i < pba.Length; i++)
pba[i].Image = changeOpacity(pba[i], getOpacity(pkm.Markings[i] != 0));
PB_MarkShiny.Image = changeOpacity(PB_MarkShiny, getOpacity(!BTN_Shinytize.Enabled));
PB_MarkCured.Image = changeOpacity(PB_MarkCured, getOpacity(CHK_Cured.Checked));
PB_MarkPentagon.Image = changeOpacity(PB_MarkPentagon, getOpacity(pkm.Gen6));
// Gen7 Markings
if (pkm.Format != 7)
return;
PB_MarkAlola.Image = changeOpacity(PB_MarkAlola, getOpacity(pkm.Gen7));
PB_MarkVC.Image = changeOpacity(PB_MarkVC, getOpacity(pkm.VC));
PB_MarkHorohoro.Image = changeOpacity(PB_MarkHorohoro, getOpacity(pkm.Horohoro));
var markings = pkm.Markings;
for (int i = 0; i < pba.Length; i++)
if (GetMarkingColor(markings[i], out Color c))
pba[i].Image = ImageUtil.ChangeAllColorTo(pba[i].Image, c);
}
private static bool GetMarkingColor(int markval, out Color c)
{
switch (markval)
{
case 1:
c = Color.FromArgb(000, 191, 255);
return true;
case 2:
c = Color.FromArgb(255, 117, 179);
return true;
default:
c = Color.Black;
return false;
}
}
private void UpdateGender()
{
int cg = PKX.GetGenderFromString(Label_Gender.Text);
int Gender = pkm.GetSaneGender(cg);
Label_Gender.Text = gendersymbols[Gender];
Label_Gender.ForeColor = GetGenderColor(Gender);
}
private void SetCountrySubRegion(ComboBox CB, string type)
{
int index = CB.SelectedIndex;
// fix for Korean / Chinese being swapped
string cl = GameInfo.CurrentLanguage + "";
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;
}
// Prompted Updates of PKM //
private void ClickFriendship(object sender, EventArgs e)
{
if (ModifierKeys == Keys.Control) // prompt to reset
TB_Friendship.Text = pkm.CurrentFriendship.ToString();
else
TB_Friendship.Text = TB_Friendship.Text == "255" ? pkm.PersonalInfo.BaseFriendship.ToString() : "255";
}
private void ClickLevel(object sender, EventArgs e)
{
if (ModifierKeys == Keys.Control)
((MaskedTextBox)sender).Text = "100";
}
private void ClickGender(object sender, EventArgs e)
{
// Get Gender Threshold
int gt = pkm.PersonalInfo.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)
int newGender = PKX.GetGenderFromString(Label_Gender.Text) ^ 1;
if (pkm.Format <= 2)
{
Stats.SetATKIVGender(newGender);
SetIsShiny(null);
}
else if (pkm.Format <= 4)
{
if (FieldsLoaded)
pkm.Species = WinFormsUtil.GetIndex(CB_Species);
pkm.Version = WinFormsUtil.GetIndex(CB_GameOrigin);
pkm.Nature = WinFormsUtil.GetIndex(CB_Nature);
pkm.AltForm = CB_Form.SelectedIndex;
pkm.SetPIDGender(newGender);
TB_PID.Text = pkm.PID.ToString("X8");
}
pkm.Gender = newGender;
Label_Gender.Text = gendersymbols[pkm.Gender];
Label_Gender.ForeColor = GetGenderColor(pkm.Gender);
if (PKX.GetGenderFromString(CB_Form.Text) < 2) // Gendered Forms
CB_Form.SelectedIndex = PKX.GetGenderFromString(Label_Gender.Text);
UpdatePreviewSprite(Label_Gender, null);
}
private void ClickPPUps(object sender, EventArgs e)
{
CB_PPu1.SelectedIndex = !ModifierKeys.HasFlag(Keys.Control) && WinFormsUtil.GetIndex(CB_Move1) > 0 ? 3 : 0;
CB_PPu2.SelectedIndex = !ModifierKeys.HasFlag(Keys.Control) && WinFormsUtil.GetIndex(CB_Move2) > 0 ? 3 : 0;
CB_PPu3.SelectedIndex = !ModifierKeys.HasFlag(Keys.Control) && WinFormsUtil.GetIndex(CB_Move3) > 0 ? 3 : 0;
CB_PPu4.SelectedIndex = !ModifierKeys.HasFlag(Keys.Control) && WinFormsUtil.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 };
int index = Array.IndexOf(pba, sender);
// Handling Gens 3-6
int[] markings = pkm.Markings;
switch (pkm.Format)
{
case 3:
case 4:
case 5:
case 6: // on/off
markings[index] ^= 1; // toggle
pkm.Markings = markings;
break;
case 7: // 0 (none) | 1 (blue) | 2 (pink)
markings[index] = (markings[index] + 1) % 3; // cycle
pkm.Markings = markings;
break;
default:
return;
}
SetMarkings();
}
private void ClickOT(object sender, EventArgs e) => SetDetailsOT(SaveFileRequested?.Invoke(this, e));
private void ClickCT(object sender, EventArgs e) => SetDetailsHT(SaveFileRequested?.Invoke(this, e));
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.GetGenderFromString(lbl.Text) ^ 1;
lbl.Text = gendersymbols[gender];
lbl.ForeColor = GetGenderColor(gender);
}
}
private void ClickBall(object sender, EventArgs e) => CB_Ball.SelectedIndex = 0;
private void ClickShinyLeaf(object sender, EventArgs e) => ShinyLeaf.CheckAll(ModifierKeys != Keys.Control);
private void ClickMetLocation(object sender, EventArgs e)
{
if (HaX)
return;
pkm = PreparePKM();
UpdateLegality(skipMoveRepop: true);
if (Legality.Valid)
return;
if (!SetSuggestedMetLocation())
return;
pkm = PreparePKM();
UpdateLegality();
}
private void ClickGT(object sender, EventArgs e)
{
if (!GB_nOT.Visible)
return;
if (sender == GB_OT)
{
pkm.CurrentHandler = 0;
GB_OT.BackgroundImage = mixedHighlight;
GB_nOT.BackgroundImage = null;
}
else if (TB_OTt2.Text.Length > 0)
{
pkm.CurrentHandler = 1;
GB_OT.BackgroundImage = null;
GB_nOT.BackgroundImage = mixedHighlight;
}
TB_Friendship.Text = pkm.CurrentFriendship.ToString();
}
private void ClickMoves(object sender, EventArgs e)
{
UpdateLegality(skipMoveRepop: true);
if (sender == GB_CurrentMoves)
{
if (!SetSuggestedMoves(random: ModifierKeys == Keys.Control))
return;
}
else if (sender == GB_RelearnMoves)
{
if (!SetSuggestedRelearnMoves())
return;
}
else
{
return;
}
UpdateLegality();
}
private bool SetSuggestedMoves(bool random = false, bool silent = false)
{
int[] m = Legality.GetSuggestedMoves(tm: random, tutor: random, reminder: random);
if (m == null)
{
if (!silent)
WinFormsUtil.Alert(MsgPKMSuggestionFormat);
return false;
}
if (random)
Util.Shuffle(m);
if (m.Length > 4)
m = m.Skip(m.Length - 4).ToArray();
Array.Resize(ref m, 4);
if (pkm.Moves.SequenceEqual(m))
return false;
if (!silent)
{
var movestrings = m.Select(v => v >= GameInfo.Strings.movelist.Length ? MsgProgramError : GameInfo.Strings.movelist[v]);
string r = string.Join(Environment.NewLine, movestrings);
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgPKMSuggestionMoves, r))
return false;
}
pkm.SetMoves(m);
FieldsLoaded = false;
LoadMoves(pkm);
FieldsLoaded = true;
return true;
}
private bool SetSuggestedRelearnMoves(bool silent = false)
{
if (pkm.Format < 6)
return false;
int[] m = pkm.GetSuggestedRelearnMoves(Legality);
if (pkm.RelearnMoves.SequenceEqual(m))
return false;
if (!silent)
{
var movestrings = m.Select(v => v >= GameInfo.Strings.movelist.Length ? MsgProgramError : GameInfo.Strings.movelist[v]);
string r = string.Join(Environment.NewLine, movestrings);
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgPKMSuggestionRelearn, r))
return false;
}
CB_RelearnMove1.SelectedValue = m[0];
CB_RelearnMove2.SelectedValue = m[1];
CB_RelearnMove3.SelectedValue = m[2];
CB_RelearnMove4.SelectedValue = m[3];
return true;
}
private bool SetSuggestedMetLocation(bool silent = false)
{
var encounter = Legality.GetSuggestedMetInfo();
if (encounter == null || pkm.Format >= 3 && encounter.Location < 0)
{
if (!silent)
WinFormsUtil.Alert(MsgPKMSuggestionNone);
return false;
}
int level = encounter.Level;
int location = encounter.Location;
int minlvl = Legal.GetLowestLevel(pkm, encounter.LevelMin);
if (minlvl == 0)
minlvl = level;
if (pkm.CurrentLevel >= minlvl && pkm.Met_Level == level && pkm.Met_Location == location)
return false;
if (minlvl < level)
minlvl = level;
if (!silent)
{
List<string> suggestion = GetSuggestionMessage(pkm, level, location, minlvl);
if (suggestion.Count == 1) // no suggestion
return false;
string suggest = string.Join(Environment.NewLine, suggestion);
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, suggest) != DialogResult.Yes)
return false;
}
if (pkm.Format >= 3)
{
TB_MetLevel.Text = level.ToString();
CB_MetLocation.SelectedValue = location;
if (pkm.GenNumber == 6 && pkm.WasEgg && ModifyPKM)
pkm.SetHatchMemory6();
}
if (pkm.CurrentLevel < minlvl)
TB_Level.Text = minlvl.ToString();
return true;
}
public void UpdateIVsGB(bool skipForm)
{
Label_Gender.Text = gendersymbols[pkm.Gender];
Label_Gender.ForeColor = GetGenderColor(pkm.Gender);
if (pkm.Species == 201 && !skipForm) // Unown
CB_Form.SelectedIndex = pkm.AltForm;
SetIsShiny(null);
UpdateSprite();
}
private void UpdateBall(object sender, EventArgs e)
{
PB_Ball.Image = PKMUtil.GetBallSprite(WinFormsUtil.GetIndex(CB_Ball));
}
private void UpdateEXPLevel(object sender, EventArgs e)
{
if (ChangingFields || !FieldsInitialized) return;
ChangingFields = true;
if (sender == TB_EXP)
{
// Change the Level
uint EXP = Util.ToUInt32(TB_EXP.Text);
int Species = WinFormsUtil.GetIndex(CB_Species);
int Level = PKX.GetLevel(Species, EXP);
if (Level == 100)
EXP = PKX.GetEXP(100, Species);
TB_Level.Text = Level.ToString();
if (!HaX)
TB_EXP.Text = EXP.ToString();
else if (Level <= 100 && Util.ToInt32(MT_Level.Text) <= 100)
MT_Level.Text = Level.ToString();
}
else
{
// Change the XP
int Level = Util.ToInt32((HaX ? MT_Level : TB_Level).Text);
if (Level <= 0)
TB_Level.Text = "1";
else if (Level > 100)
{
TB_Level.Text = "100";
if (!HaX)
Level = 100;
}
if (Level > byte.MaxValue) MT_Level.Text = "255";
if (Level <= 100)
TB_EXP.Text = PKX.GetEXP(Level, WinFormsUtil.GetIndex(CB_Species)).ToString();
}
ChangingFields = false;
if (FieldsLoaded) // store values back
{
pkm.EXP = Util.ToUInt32(TB_EXP.Text);
pkm.Stat_Level = Util.ToInt32((HaX ? MT_Level : TB_Level).Text);
}
Stats.UpdateStats();
UpdateLegality();
}
private void UpdateRandomPID(object sender, EventArgs e)
{
if (pkm.Format < 3)
return;
if (FieldsLoaded)
pkm.PID = Util.GetHexValue(TB_PID.Text);
if (sender == Label_Gender)
pkm.SetPIDGender(pkm.Gender);
else if (sender == CB_Nature && pkm.Nature != WinFormsUtil.GetIndex(CB_Nature))
pkm.SetPIDNature(WinFormsUtil.GetIndex(CB_Nature));
else if (sender == BTN_RerollPID)
pkm.SetPIDGender(pkm.Gender);
else if (sender == CB_Ability && CB_Ability.SelectedIndex != pkm.PIDAbility && pkm.PIDAbility > -1)
pkm.PID = PKX.GetRandomPID(pkm.Species, pkm.Gender, pkm.Version, pkm.Nature, pkm.Format, (uint)(CB_Ability.SelectedIndex * 0x10001));
TB_PID.Text = pkm.PID.ToString("X8");
SetIsShiny(null);
UpdateSprite();
if (pkm.Format >= 6 && 3 <= pkm.GenNumber && pkm.GenNumber <= 5)
TB_EC.Text = TB_PID.Text;
}
private void UpdateRandomEC(object sender, EventArgs e)
{
if (pkm.Format < 6)
return;
int wIndex = Array.IndexOf(Legal.WurmpleEvolutions, WinFormsUtil.GetIndex(CB_Species));
uint EC = wIndex < 0 ? Util.Rand32() : PKX.GetWurmpleEC(wIndex/2);
TB_EC.Text = EC.ToString("X8");
UpdateLegality();
}
private void Update255_MTB(object sender, EventArgs e)
{
if (!(sender is MaskedTextBox tb)) return;
if (Util.ToInt32(tb.Text) > byte.MaxValue)
tb.Text = "255";
}
private void UpdateForm(object sender, EventArgs e)
{
if (CB_Form == sender && FieldsLoaded)
pkm.AltForm = CB_Form.SelectedIndex;
UpdateGender();
Stats.UpdateStats();
// Repopulate Abilities if Species Form has different abilities
SetAbilityList();
// Gender Forms
if (WinFormsUtil.GetIndex(CB_Species) == 201 && FieldsLoaded)
{
if (pkm.Format == 3)
{
pkm.SetPIDUnown3(CB_Form.SelectedIndex);
TB_PID.Text = pkm.PID.ToString("X8");
}
else if (pkm.Format == 2)
{
int desiredForm = CB_Form.SelectedIndex;
while (pkm.AltForm != desiredForm)
Stats.UpdateRandomIVs(null, null);
}
}
else if (PKX.GetGenderFromString(CB_Form.Text) < 2)
{
if (CB_Form.Items.Count == 2) // actually M/F; Pumpkaboo formes in German are S,M,L,XL
Label_Gender.Text = gendersymbols[PKX.GetGenderFromString(CB_Form.Text)];
}
if (ChangingFields)
return;
ChangingFields = true;
MT_Form.Text = CB_Form.SelectedIndex.ToString();
ChangingFields = false;
UpdateSprite();
}
private void UpdateHaXForm(object sender, EventArgs e)
{
if (ChangingFields)
return;
ChangingFields = true;
int form = pkm.AltForm = Util.ToInt32(MT_Form.Text);
CB_Form.SelectedIndex = CB_Form.Items.Count > form ? form : -1;
ChangingFields = false;
UpdateSprite();
}
private void UpdatePP(object sender, EventArgs e)
{
if (!(sender is ComboBox cb))
return;
int index = Array.IndexOf(Moves, cb);
if (index < 0)
index = Array.IndexOf(PPUps, cb);
if (index < 0)
return;
int move = WinFormsUtil.GetIndex(Moves[index]);
var ppctrl = PPUps[index];
int ppups = ppctrl.SelectedIndex;
if (move <= 0)
ppctrl.SelectedIndex = 0;
else
MovePP[index].Text = pkm.GetMovePP(move, ppups).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)
CHK_Cured.Checked = CHK_Infected.Checked = false; // No Strain = Never Cured / Infected, triggers Strain update
else CHK_Cured.Checked = true; // Any Strain = Cured
}
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 = CB_PKRSDays.SelectedIndex = 1;
Label_PKRSdays.Visible = CB_PKRSDays.Visible = true;
UpdatePKRSCured(sender, e);
}
}
private void UpdateCountry(object sender, EventArgs e)
{
int index;
if (sender is ComboBox c && (index = WinFormsUtil.GetIndex(c)) > 0)
SetCountrySubRegion(CB_SubRegion, $"sr_{index:000}");
}
private void UpdateSpecies(object sender, EventArgs e)
{
// Get Species dependent information
if (FieldsLoaded)
pkm.Species = WinFormsUtil.GetIndex(CB_Species);
SetAbilityList();
SetForms();
UpdateForm(null, null);
if (!FieldsLoaded)
return;
// Recalculate EXP for Given Level
uint EXP = PKX.GetEXP(pkm.CurrentLevel, pkm.Species);
TB_EXP.Text = EXP.ToString();
// Check for Gender Changes
UpdateGender();
// 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)
{
GameVersion Version = (GameVersion)WinFormsUtil.GetIndex(CB_GameOrigin);
// check if differs
GameVersion newTrack = GameUtil.GetMetLocationVersionGroup(Version);
if (newTrack == GameVersion.GSC && pkm.Format >= 7)
newTrack = GameVersion.USUM;
else if (pkm.Format < 3)
newTrack = GameVersion.GSC;
if (newTrack != origintrack)
{
var met_list = GameInfo.GetLocationList(Version, pkm.Format, egg: false);
InitializeBinding(CB_MetLocation);
CB_MetLocation.DataSource = new BindingSource(met_list, null);
if (FieldsLoaded)
{
SetMarkings(); // Set/Remove the Nativity marking when gamegroup changes too
pkm.Version = (int)Version;
int metLoc = EncounterSuggestion.GetSuggestedTransferLocation(pkm);
CB_MetLocation.SelectedValue = Math.Max(0, metLoc);
}
var egg_list = GameInfo.GetLocationList(Version, pkm.Format, egg: true);
InitializeBinding(CB_EggLocation);
CB_EggLocation.DataSource = new BindingSource(egg_list, null);
if (FieldsLoaded)
CB_EggLocation.SelectedIndex = CHK_AsEgg.Checked ? 1 : 0; // daycare : none
origintrack = newTrack;
// Stretch C/XD met location dropdowns
int width = CB_EggLocation.DropDownWidth;
if (Version == GameVersion.CXD && pkm.Format == 3)
width = 2 * width;
CB_MetLocation.DropDownWidth = width;
if (!FieldsLoaded)
CB_GameOrigin.Focus(); // hacky validation forcing
}
// Visibility logic for Gen 4 encounter type; only show for Gen 4 Pokemon.
if (pkm.Format >= 4)
{
bool g4 = pkm.Gen4;
CB_EncounterType.Visible = Label_EncounterType.Visible = g4 && pkm.Format < 7;
if (!g4)
CB_EncounterType.SelectedValue = 0;
}
if (!FieldsLoaded)
return;
pkm.Version = (int)Version;
UpdateLegality();
}
private void UpdateExtraByteValue(object sender, EventArgs e)
{
if (CB_ExtraBytes.Items.Count == 0 || !(sender is MaskedTextBox mtb))
return;
// Changed Extra Byte's Value
if (Util.ToInt32(mtb.Text) > byte.MaxValue)
mtb.Text = "255";
int value = Util.ToInt32(mtb.Text);
int offset = Convert.ToInt32(CB_ExtraBytes.Text, 16);
pkm.Data[offset] = (byte)value;
}
private void UpdateExtraByteIndex(object sender, EventArgs e)
{
if (CB_ExtraBytes.Items.Count == 0)
return;
// Byte changed, need to refresh the Text box for the byte's value.
TB_ExtraByte.Text = pkm.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString();
}
private void UpdateNatureModification(object sender, EventArgs e)
{
if (sender != CB_Nature) return;
int nature = WinFormsUtil.GetIndex(CB_Nature);
string text = Stats.UpdateNatureModification(nature);
NatureTip.SetToolTip(CB_Nature, text);
}
private void UpdateIsNicknamed(object sender, EventArgs e)
{
if (!FieldsLoaded)
return;
pkm.Nickname = TB_Nickname.Text;
if (CHK_Nicknamed.Checked)
return;
int species = WinFormsUtil.GetIndex(CB_Species);
if (species < 1 || species > pkm.MaxSpeciesID)
return;
if (CHK_IsEgg.Checked)
species = 0; // get the egg name.
if (PKX.IsNicknamedAnyLanguage(species, TB_Nickname.Text, pkm.Format))
CHK_Nicknamed.Checked = true;
}
private void UpdateNickname(object sender, EventArgs e)
{
if (sender == Label_Species)
{
switch (ModifierKeys)
{
case Keys.Control: RequestShowdownImport?.Invoke(sender, e); return;
case Keys.Alt: RequestShowdownExport?.Invoke(sender, e); return;
default:
if (pkm is PK1 pk1)
pk1.Catch_Rate = pk1.PersonalInfo.CatchRate;
return;
}
}
int lang = WinFormsUtil.GetIndex(CB_Language);
if (!FieldsInitialized || CHK_Nicknamed.Checked)
return;
// Fetch Current Species and set it as Nickname Text
int species = WinFormsUtil.GetIndex(CB_Species);
if (species < 1 || species > pkm.MaxSpeciesID)
{ TB_Nickname.Text = ""; return; }
if (CHK_IsEgg.Checked)
species = 0; // get the egg name.
// If name is that of another language, don't replace the nickname
if (sender != CB_Language && species != 0 && !PKX.IsNicknamedAnyLanguage(species, TB_Nickname.Text, pkm.Format))
return;
TB_Nickname.Text = PKX.GetSpeciesNameGeneration(species, lang, pkm.Format);
if (pkm.Format == 1)
((PK1)pkm).SetNotNicknamed();
if (pkm.Format == 2)
((PK2)pkm).SetNotNicknamed();
}
private void UpdateNicknameClick(object sender, MouseEventArgs e)
{
TextBox tb = sender as TextBox ?? TB_Nickname;
// Special Character Form
if (ModifierKeys != Keys.Control)
return;
var SAV = RequestSaveFile;
if (SAV == null) // form did not provide the needed info
return;
if (tb == TB_Nickname)
{
pkm.Nickname = tb.Text;
var d = new TrashEditor(tb, pkm.Nickname_Trash, SAV);
d.ShowDialog();
tb.Text = d.FinalString;
pkm.Nickname_Trash = d.FinalBytes;
}
else if (tb == TB_OT)
{
pkm.OT_Name = tb.Text;
var d = new TrashEditor(tb, pkm.OT_Trash, SAV);
d.ShowDialog();
tb.Text = d.FinalString;
pkm.OT_Trash = d.FinalBytes;
}
else if (tb == TB_OTt2)
{
pkm.HT_Name = tb.Text;
var d = new TrashEditor(tb, pkm.HT_Trash, SAV);
d.ShowDialog();
tb.Text = d.FinalString;
pkm.HT_Trash = d.FinalBytes;
}
}
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 = pkm.CurrentFriendship.ToString();
}
else if (string.IsNullOrWhiteSpace(Label_CTGender.Text))
Label_CTGender.Text = gendersymbols[0];
}
private void UpdateIsEgg(object sender, EventArgs e)
{
// Display hatch counter if it is an egg, Display Friendship if it is not.
Label_HatchCounter.Visible = CHK_IsEgg.Checked && pkm.Format > 1;
Label_Friendship.Visible = !CHK_IsEgg.Checked && pkm.Format > 1;
if (!FieldsLoaded)
return;
pkm.IsEgg = CHK_IsEgg.Checked;
if (CHK_IsEgg.Checked)
{
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);
// if egg wasn't originally obtained by OT => Link Trade, else => None
bool isTraded = false;
var SAV = SaveFileRequested?.Invoke(this, e);
if (SAV != null)
isTraded = SAV.OT != TB_OT.Text || SAV.TID != Util.ToInt32(TB_TID.Text) || SAV.SID != Util.ToInt32(TB_SID.Text);
CB_MetLocation.SelectedIndex = isTraded ? 2 : 0;
if (!CHK_Nicknamed.Checked)
{
TB_Nickname.Text = PKX.GetSpeciesNameGeneration(0, WinFormsUtil.GetIndex(CB_Language), pkm.Format);
if (pkm.Format != 4) // eggs in gen4 do not have nickname flag
CHK_Nicknamed.Checked = true;
}
// Wipe egg memories
if (pkm.Format >= 6 && ModifyPKM)
pkm.ClearMemories();
}
else // Not Egg
{
if (!CHK_Nicknamed.Checked)
UpdateNickname(null, null);
TB_Friendship.Text = pkm.PersonalInfo.BaseFriendship.ToString();
if (CB_EggLocation.SelectedIndex == 0)
{
CAL_EggDate.Value = new DateTime(2000, 01, 01);
CHK_AsEgg.Checked = false;
GB_EggConditions.Enabled = false;
}
if (TB_Nickname.Text == PKX.GetSpeciesNameGeneration(0, WinFormsUtil.GetIndex(CB_Language), pkm.Format))
CHK_Nicknamed.Checked = false;
}
UpdateNickname(null, null);
UpdateSprite();
}
private void UpdateMetAsEgg(object sender, EventArgs e)
{
GB_EggConditions.Enabled = CHK_AsEgg.Checked;
if (CHK_AsEgg.Checked)
{
if (!FieldsLoaded)
return;
CAL_EggDate.Value = DateTime.Now;
CB_EggLocation.SelectedIndex = 1;
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)
{
var ShinyPID = pkm.Format <= 2 || ModifierKeys != Keys.Control;
UpdateShiny(ShinyPID);
}
private void UpdateShiny(bool PID)
{
pkm.TID = Util.ToInt32(TB_TID.Text);
pkm.SID = Util.ToInt32(TB_SID.Text);
pkm.PID = Util.GetHexValue(TB_PID.Text);
pkm.Nature = WinFormsUtil.GetIndex(CB_Nature);
pkm.Gender = PKX.GetGenderFromString(Label_Gender.Text);
pkm.AltForm = CB_Form.SelectedIndex;
pkm.Version = WinFormsUtil.GetIndex(CB_GameOrigin);
if (pkm.Format > 2)
{
if (PID)
{
pkm.SetShinyPID();
TB_PID.Text = pkm.PID.ToString("X8");
if (pkm.GenNumber < 6 && TB_EC.Visible)
TB_EC.Text = TB_PID.Text;
}
else
{
pkm.SetShinySID();
TB_SID.Text = pkm.SID.ToString();
}
}
else
{
pkm.SetShinyIVs();
Stats.LoadIVs(pkm.IVs);
Stats.UpdateIVs(null, null);
}
SetIsShiny(null);
UpdatePreviewSprite?.Invoke(this, null);
UpdateLegality();
}
private void UpdateTSV(object sender, EventArgs e)
{
if (pkm.Format < 6)
return;
string IDstr = $"TSV: {pkm.TSV:d4}";
if (pkm.Format > 6)
IDstr += Environment.NewLine + $"G7TID: ({pkm.TrainerSID7:d4}){pkm.TrainerID7:d6}";
Tip1.SetToolTip(TB_TID, IDstr);
Tip2.SetToolTip(TB_SID, IDstr);
pkm.PID = Util.GetHexValue(TB_PID.Text);
Tip3.SetToolTip(TB_PID, $"PSV: {pkm.PSV:d4}");
}
private void Update_ID(object sender, EventArgs e)
{
// Trim out nonhex characters
TB_PID.Text = Util.GetHexValue(TB_PID.Text).ToString("X8");
TB_EC.Text = Util.GetHexValue(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(sender);
UpdateSprite();
Stats.UpdateIVs(null, null); // If the EC is changed, EC%6 (Characteristic) might be changed.
if (pkm.Format <= 4 && FieldsLoaded)
{
FieldsLoaded = false;
pkm.PID = Util.GetHexValue(TB_PID.Text);
CB_Nature.SelectedValue = pkm.Nature;
Label_Gender.Text = gendersymbols[pkm.Gender];
Label_Gender.ForeColor = GetGenderColor(pkm.Gender);
FieldsLoaded = true;
}
}
private void UpdateShadowID(object sender, EventArgs e)
{
if (!FieldsLoaded)
return;
FLP_Purification.Visible = NUD_ShadowID.Value > 0;
}
private void UpdatePurification(object sender, EventArgs e)
{
if (!FieldsLoaded)
return;
FieldsLoaded = false;
CHK_Shadow.Checked = NUD_Purification.Value > 0;
FieldsLoaded = true;
}
private void UpdateShadowCHK(object sender, EventArgs e)
{
if (!FieldsLoaded)
return;
FieldsLoaded = false;
NUD_Purification.Value = CHK_Shadow.Checked ? NUD_Purification.Maximum : 0;
FieldsLoaded = true;
}
private void ValidateComboBox(object sender)
{
if (!FieldsInitialized)
return;
ComboBox cb = sender as ComboBox;
if (cb == null)
return;
if (cb.Text == "" && cb.Items.Count > 0)
{ cb.SelectedIndex = 0; return; }
if (cb.SelectedValue == null)
cb.BackColor = Color.DarkSalmon;
else
cb.ResetBackColor();
}
private void ValidateComboBox(object sender, CancelEventArgs e)
{
if (!(sender is ComboBox))
return;
ValidateComboBox(sender);
UpdateSprite();
}
private void ValidateComboBox2(object sender, EventArgs e)
{
if (!FieldsInitialized)
return;
ValidateComboBox(sender, null);
if (FieldsLoaded)
{
if (sender == CB_Ability && pkm.Format >= 6)
TB_AbilityNumber.Text = (1 << CB_Ability.SelectedIndex).ToString();
if (sender == CB_Ability && pkm.Format <= 5 && CB_Ability.SelectedIndex < 2) // not hidden
UpdateRandomPID(sender, e);
if (sender == CB_Nature && pkm.Format <= 4)
{
pkm.Nature = CB_Nature.SelectedIndex;
UpdateRandomPID(sender, e);
}
if (sender == CB_HeldItem || sender == CB_Ability)
UpdateLegality();
}
UpdateNatureModification(sender, null);
Stats.UpdateIVs(null, null); // updating Nature will trigger stats to update as well
}
private void ValidateMove(object sender, EventArgs e)
{
if (!FieldsInitialized)
return;
ValidateComboBox(sender);
if (!FieldsLoaded)
return;
if (Moves.Contains(sender)) // Move
UpdatePP(sender, e);
// Legality
pkm.Moves = Moves.Select(WinFormsUtil.GetIndex).ToArray();
pkm.RelearnMoves = Relearn.Select(WinFormsUtil.GetIndex).ToArray();
UpdateLegality(skipMoveRepop: true);
}
private void ValidateMovePaint(object sender, DrawItemEventArgs e)
{
if (e.Index < 0) return;
var i = (ComboItem)((ComboBox)sender).Items[e.Index];
var moves = Legality.AllSuggestedMovesAndRelearn;
bool vm = moves != null && moves.Contains(i.Value) && !HaX;
bool current = (e.State & DrawItemState.Selected) == DrawItemState.Selected;
Brush tBrush = current ? SystemBrushes.HighlightText : new SolidBrush(e.ForeColor);
Brush brush = current ? SystemBrushes.Highlight : vm ? Brushes.PaleGreen : new SolidBrush(e.BackColor);
e.Graphics.FillRectangle(brush, e.Bounds);
e.Graphics.DrawString(i.Text, e.Font, tBrush, e.Bounds, StringFormat.GenericDefault);
if (current) return;
tBrush.Dispose();
if (!vm)
brush.Dispose();
}
private void ValidateLocation(object sender, EventArgs e)
{
ValidateComboBox(sender);
if (!FieldsLoaded)
return;
pkm.Met_Location = WinFormsUtil.GetIndex(CB_MetLocation);
pkm.Egg_Location = WinFormsUtil.GetIndex(CB_EggLocation);
UpdateLegality();
}
// Secondary Windows for Ribbons/Amie/Memories
private void OpenRibbons(object sender, EventArgs e)
{
new RibbonEditor(pkm).ShowDialog();
}
private void OpenMedals(object sender, EventArgs e)
{
new SuperTrainingEditor(pkm).ShowDialog();
}
private void OpenHistory(object sender, EventArgs e)
{
// Write back current values
pkm.HT_Name = TB_OTt2.Text;
pkm.OT_Name = TB_OT.Text;
pkm.IsEgg = CHK_IsEgg.Checked;
pkm.CurrentFriendship = Util.ToInt32(TB_Friendship.Text);
new MemoryAmie(pkm).ShowDialog();
TB_Friendship.Text = pkm.CurrentFriendship.ToString();
}
/// <summary>
/// Refreshes the interface for the current PKM format.
/// </summary>
public bool ToggleInterface(SaveFile sav, PKM pk)
{
if (pk.GetType() != sav.PKMType || pkm.Format < 3)
pk = sav.BlankPKM;
pkm = pk;
ToggleInterface(pkm.Format);
ToggleInterface(pkm.GetType());
return FinalizeInterface(sav);
}
private void ToggleInterface(Type t)
{
FLP_Purification.Visible = FLP_ShadowID.Visible = t == typeof(XK3) || t == typeof(CK3);
}
private void ToggleInterface(int gen)
{
Tip1.RemoveAll(); Tip2.RemoveAll(); Tip3.RemoveAll(); // TSV/PSV
FLP_Country.Visible = FLP_SubRegion.Visible = FLP_3DSRegion.Visible = gen >= 6;
Label_EncryptionConstant.Visible = BTN_RerollEC.Visible = TB_EC.Visible = gen >= 6;
GB_nOT.Visible = GB_RelearnMoves.Visible = BTN_Medals.Visible = BTN_History.Visible = gen >= 6;
PB_MarkPentagon.Visible = gen >= 6;
PB_MarkAlola.Visible = PB_MarkVC.Visible = PB_MarkHorohoro.Visible = gen >= 7;
FLP_NSparkle.Visible = L_NSparkle.Visible = CHK_NSparkle.Visible = gen == 5;
CB_Form.Visible = Label_Form.Visible = CHK_AsEgg.Visible = GB_EggConditions.Visible = PB_Mark5.Visible = PB_Mark6.Visible = gen >= 4;
FLP_ShinyLeaf.Visible = L_ShinyLeaf.Visible = ShinyLeaf.Visible = gen == 4;
DEV_Ability.Enabled = DEV_Ability.Visible = gen > 3 && HaX;
CB_Ability.Visible = !DEV_Ability.Enabled && gen >= 3;
FLP_Nature.Visible = gen >= 3;
FLP_Ability.Visible = gen >= 3;
GB_ExtraBytes.Visible = GB_ExtraBytes.Enabled = gen >= 3;
GB_Markings.Visible = gen >= 3;
BTN_Ribbons.Visible = gen >= 3;
CB_Form.Enabled = gen >= 3;
BTN_RerollPID.Visible = Label_PID.Visible = TB_PID.Visible = Label_SID.Visible = TB_SID.Visible = gen >= 3;
FLP_FriendshipForm.Visible = gen >= 2;
FLP_HeldItem.Visible = gen >= 2;
CHK_IsEgg.Visible = gen >= 2;
FLP_PKRS.Visible = FLP_EggPKRSRight.Visible = gen >= 2;
Label_OTGender.Visible = gen >= 2;
Label_Gender.Visible = gen >= 1;
// HaX override, needs to be after DEV_Ability enabled assignment.
TB_AbilityNumber.Visible = gen >= 6 && DEV_Ability.Enabled;
// Met Tab
FLP_MetDate.Visible = gen >= 4;
FLP_Fateful.Visible = FLP_Ball.Visible = FLP_OriginGame.Visible = gen >= 3;
FLP_MetLocation.Visible = FLP_MetLevel.Visible = gen >= 2;
FLP_EncounterType.Visible = gen >= 4 && gen <= 6;
FLP_TimeOfDay.Visible = gen == 2;
Contest.ToggleInterface(gen);
Stats.ToggleInterface(gen);
CenterSubEditors();
}
private bool FinalizeInterface(SaveFile sav)
{
bool init = FieldsInitialized;
FieldsInitialized = FieldsLoaded = false;
bool TranslationRequired = false;
PopulateFilteredDataSources(sav);
PopulateFields(pkm);
FieldsInitialized |= init;
// SAV Specific Limits
TB_OT.MaxLength = pkm.OTLength;
TB_OTt2.MaxLength = pkm.OTLength;
TB_Nickname.MaxLength = pkm.NickLength;
// Hide Unused Tabs
if (pkm.Format == 1 && tabMain.TabPages.Contains(Tab_Met))
tabMain.TabPages.Remove(Tab_Met);
else if (pkm.Format != 1 && !tabMain.TabPages.Contains(Tab_Met))
{
tabMain.TabPages.Insert(1, Tab_Met);
TranslationRequired = true;
}
// Common HaX Interface
MT_Level.Enabled = MT_Level.Visible = MT_Form.Enabled = MT_Form.Visible = HaX;
TB_Level.Visible = !HaX;
// Setup PKM Preparation/Extra Bytes
SetPKMFormatMode(pkm.Format);
// pk2 save files do not have an Origin Game stored. Prompt the met location list to update.
if (pkm.Format == 2)
UpdateOriginGame(null, null);
return TranslationRequired;
}
private void CenterSubEditors()
{
// Recenter PKM SubEditors
FLP_PKMEditors.Location = new Point((Tab_OTMisc.Width - FLP_PKMEditors.Width) / 2, FLP_PKMEditors.Location.Y);
}
// Loading Setup
public void TemplateFields(PKM template)
{
if (template != null)
{
PopulateFields(template);
LastData = null;
return;
}
if (CB_GameOrigin.Items.Count > 0)
CB_GameOrigin.SelectedIndex = 0;
CB_Move1.SelectedValue = 1;
var info = new SimpleTrainerInfo{Language = Math.Max(0, WinFormsUtil.GetIndex(CB_Language))};
SetDetailsOT(info);
CB_Ball.SelectedIndex = Math.Min(0, CB_Ball.Items.Count - 1);
CAL_MetDate.Value = CAL_EggDate.Value = DateTime.Today;
CB_Species.SelectedValue = pkm.MaxSpeciesID;
CHK_Nicknamed.Checked = false;
LastData = null;
}
public void EnableDragDrop(DragEventHandler enter, DragEventHandler drop)
{
AllowDrop = true;
DragDrop += drop;
foreach (TabPage tab in tabMain.TabPages)
{
tab.AllowDrop = true;
tab.DragEnter += enter;
tab.DragDrop += drop;
}
}
// ReSharper disable once FieldCanBeMadeReadOnly.Global
public Action<ShowdownSet> LoadShowdownSet;
private void LoadShowdownSetDefault(ShowdownSet Set)
{
var pk = PreparePKM();
pk.ApplySetDetails(Set);
PopulateFields(pk);
}
public void ChangeLanguage(SaveFile sav, PKM pk)
{
// Force an update to the met locations
origintrack = GameVersion.Invalid;
bool alreadyInit = FieldsInitialized;
FieldsInitialized = false;
InitializeLanguage(sav);
CenterSubEditors();
PopulateFields(pk); // put data back in form
FieldsInitialized |= alreadyInit;
}
public void FlickerInterface()
{
tabMain.SelectedTab = Tab_Met; // parent tab of CB_GameOrigin
tabMain.SelectedTab = Tab_Main; // first tab
}
private void InitializeLanguage(SaveFile SAV)
{
ComboBox[] cbs =
{
CB_Country, CB_SubRegion, CB_3DSReg, CB_Language, CB_Ball, CB_HeldItem, CB_Species, DEV_Ability,
CB_Nature, CB_EncounterType, CB_GameOrigin,
};
foreach (var cb in cbs)
InitializeBinding(cb);
// Set the various ComboBox DataSources up with their allowed entries
SetCountrySubRegion(CB_Country, "countries");
CB_3DSReg.DataSource = Util.GetUnsortedCBList("regions3ds");
GameInfo.InitializeDataSources(GameInfo.Strings);
CB_EncounterType.DataSource = Util.GetCBList(GameInfo.Strings.encountertypelist, new[] { 0 }, Legal.Gen4EncounterTypes);
CB_Nature.DataSource = new BindingSource(GameInfo.NatureDataSource, null);
// Sub editors
Stats.InitializeDataSources();
PopulateFilteredDataSources(SAV);
}
private void PopulateFilteredDataSources(SaveFile SAV)
{
GameInfo.SetItemDataSource(SAV.MaxItemID, SAV.HeldItems, SAV.Generation, SAV.Version, GameInfo.Strings, HaX);
if (SAV.Generation > 1)
CB_HeldItem.DataSource = new BindingSource(GameInfo.ItemDataSource.Where(i => i.Value <= SAV.MaxItemID).ToList(), null);
var languages = Util.GetUnsortedCBList("languages");
if (SAV.Generation == 3)
languages.RemoveAll(l => l.Value >= (int)LanguageID.Korean);
else if (SAV.Generation < 7)
languages.RemoveAll(l => l.Value > (int)LanguageID.Korean);
CB_Language.DataSource = languages;
CB_Ball.DataSource = new BindingSource(GameInfo.BallDataSource.Where(b => b.Value <= SAV.MaxBallID).ToList(), null);
CB_Species.DataSource = new BindingSource(GameInfo.SpeciesDataSource.Where(s => s.Value <= SAV.MaxSpeciesID).ToList(), null);
DEV_Ability.DataSource = new BindingSource(GameInfo.AbilityDataSource.Where(a => a.Value <= SAV.MaxAbilityID).ToList(), null);
CB_GameOrigin.DataSource = new BindingSource(GameInfo.VersionDataSource.Where(g => g.Value <= SAV.MaxGameID || SAV.Generation >= 3 && g.Value == 15).ToList(), null);
// Set the Move ComboBoxes too..
GameInfo.MoveDataSource = (HaX ? GameInfo.HaXMoveDataSource : GameInfo.LegalMoveDataSource).Where(m => m.Value <= SAV.MaxMoveID).ToList(); // Filter Z-Moves if appropriate
foreach (var cb in Moves.Concat(Relearn))
{
InitializeBinding(cb);
cb.DataSource = new BindingSource(GameInfo.MoveDataSource, null);
}
}
private static List<string> GetSuggestionMessage(PKM pkm, int level, int location, int minlvl)
{
var suggestion = new List<string> { MsgPKMSuggestionStart };
if (pkm.Format >= 3)
{
var met_list = GameInfo.GetLocationList((GameVersion)pkm.Version, pkm.Format, egg: false);
var locstr = met_list.FirstOrDefault(loc => loc.Value == location).Text;
suggestion.Add($"{MsgPKMSuggestionMetLocation} {locstr}");
suggestion.Add($"{MsgPKMSuggestionMetLevel} {level}");
}
if (pkm.CurrentLevel < minlvl)
suggestion.Add($"{MsgPKMSuggestionLevel} {minlvl}");
return suggestion;
}
private static void InitializeBinding(ListControl cb)
{
cb.DisplayMember = nameof(ComboItem.Text);
cb.ValueMember = nameof(ComboItem.Value);
}
}
}